tkinter使用按钮名称变量来设置状态时抛出错误

如何解决tkinter使用按钮名称变量来设置状态时抛出错误

我想将按钮名称作为变量传递给tkinter。此方法适用于“文本”字段,但不适用于我代码中的按钮。

我正在构建一个gui应用程序,我想拥有一个通用的清除功能,该功能可以打断文本输入字段并将按钮从NORMAL重置为DiSABLED。

有多个按钮和字段,因此希望使它通用。 对于我拥有的代码,除了全部清除之外,这些按钮都存在。

我根据传递给函数的内容将变量w_button设置为(现有)按钮的特定名称。

def switch_clear(elem_type):
    
if elem_type == 'scn':
    w_button = 'b_clear_scn'
    clear_field = 'scn_file_entry'
    print ('scenario')
elif elem_type == 'sol2':
    w_button = 'b_clear_sol2'
    clear_field = 'sol2_file_entry'
    print ('sol2')
elif elem_type == 'mdl':
    w_button = 'b_clear_mdlList'
    clear_field = 'mdlList_file_entry'
    print ('mdl')
elif elem_type == 'all':
    print ('clear all TBD')
    return()
    
if w_button["state"] == NORMAL:
    clear_field.delete(0,END)
    w_button["state"] = DISABLED
return()

发生了什么事

C:\utils>my_frame3.py
scenario
Traceback (most recent call last):
  File "C:\utils\my_frame3.py",line 127,in <module>
    b_clear_scn =  Button(first_frame,text = "Clear scenario",command = switch_clear('scn'),height = 2,state=DISABLED)
  File "C:\utils\my_frame3.py",line 100,in switch_clear
    if w_button["state"] == NORMAL:
TypeError: string indices must be integers

C:\utils>

我意识到我可以复制清除操作并将其推送到if / elif语句中,我可能不得不忍受,但是-是否可以将按钮作为变量引用?我该怎么办?

按以下要求填写代码。尽管使用了代码小部件,预览还是一团糟,但是在我的文件行中,其格式正确(记事本++)。 Tx

import os,sys
from tkinter import *
from tkinter import messagebox
from tkinter import filedialog

root2 = Tk()
root2.title('Model Processing')
root2.geometry('{}x{}'.format(512,400))

# colors
color1 = 'light cyan'
color2 = 'gold'
color3 = 'RosyBrown1'
color4 = 'lavender'
color5 = 'linen'

bg_color = 'azure'

# number of items to process; until >1 OK is disabled; if >1 OK is enabled TBD
l_to_do = [] # items to process; scn,sol2,modelList,installed models

# functions/commands

def callback():
    print ('A button was clicked.')
    return;

def my_exit():
    result = messagebox.askquestion("Cancel Model Processing","Are you sure?",icon='warning')
    if result == 'yes':
        root2.quit()
    else: # user changed mind
        pass

def choose_import_file(str_ftype):
    which_field = ''
    which_clear_btn = ''
    ftype = str_ftype
    mdl_opts = {}
    
    if ftype == 'scn':
        title_msg = 'Choose a scenario file'
        
        mdl_opts['filetypes'] = [('Supported types',('.scn')),('scenario files',('.scn'))]     
        which_field = scn_file_entry                             
        which_clear_btn = 'b_clear_scn'

    elif ftype == 'sol2':
        title_msg = 'Choose a SOL2 file'
        mdl_opts['filetypes'] = [('Supported types',('.txt')),('sol2 files',('.txt'))]     
        which_field = sol2_file_entry 
        
    elif ftype == 'mdllist':
        title_msg = 'Choose a ModelList file'
        print ('TBD: ModelList file')
                                 
    file_input = filedialog.askopenfilename(title = title_msg,**mdl_opts)
    if file_input == '':
        print ('error or cancelled by user')
        return
    else:
         f_inp_file = os.path.basename(file_input)
         f_inp_file_base = str(file_input.split('.')[0])
         f_inp_file_ext = str.lower(str(file_input.split('.')[1]))

         f_inp_d_name = os.path.dirname(file_input)
         print('File chosen:',f_inp_file_base)

         # populate scenario file field
         which_field.insert(INSERT,file_input)

         which_clear_btn["state"] = NORMAL
         
         # define appropriate clear button active
         # define_clear_btn.configure(state = ACTIVE)

         return

def switch_clear(elem_type):
        
    if elem_type == 'scn':
        if b_clear_scn["state"] == NORMAL:
            scn_file_entry.delete(0,END)
            b_clear_scn["state"] = DISABLED
    elif elem_type == 'sol2':
        f b_clear_sol2["state"] == NORMAL:
            clear_field = 'sol2_file_entry'
            b_clear_sol2["state"] = DISABLED
    elif elem_type == 'mdl':
        if b_clear_mdlList["state"] == NORMAL:
            clear_field = 'mdlList_file_entry'
            b_clear_mdlList["state"] = DISABLED
    elif elem_type == 'all':
        print ('clear all TBD')
        return()
    return()    
    

# create all of the main containers
first_frame = Frame(root2,bg=color5,width = 512,height=90,pady=10)
second_frame = Frame(root2,pady=10)
third_frame = Frame(root2,width=512,pady=10)
fourth_frame = Frame(root2,height = 90,pady=10)

# layout all of the main containers
root2.grid_rowconfigure(3,weight=1)
root2.grid_rowconfigure(2,weight=1)
root2.grid_rowconfigure(1,weight=1)
root2.grid_columnconfigure(0,weight=1)

first_frame.grid(row=0,sticky="ew")
second_frame.grid(row=1,sticky="ew")
third_frame.grid(row=2,sticky="ew")
fourth_frame.grid(row = 3,sticky="e")

# create the widgets for the first frame
#scn_label = Label(first_frame,text = 'Scenario file')
scn_file_entry = Entry(first_frame,background=bg_color,width = 50)
b_choose_scn = Button(first_frame,text = "Choose a scenario..",command = lambda: choose_import_file('scn'),height = 2)
b_clear_scn =  Button(first_frame,state=DISABLED)


# layout the widgets in the first frame
#scn_label.grid(row = 0,column = 0,padx = (10,50),pady=5)
scn_file_entry.grid(row = 0,column = 1,10))
b_choose_scn.grid(row=0,column=0,10),sticky=W)
b_clear_scn.grid(row=2,sticky=W)

# second frame
# sol2_label = Label(second_frame,text = 'Sol2 file')
sol2_file_entry = Entry(second_frame,width = 50)
b_choose_sol2 = Button(second_frame,text = "Choose SOL2 file..",command = lambda: choose_import_file('sol2'),height = 2)
b_clear_sol2 =  Button(second_frame,text = "Clear SOL2",command = switch_clear('sol2'),state=DISABLED)

# layout the widgets in the second frame
# sol2_label.grid(row = 0,pady=5)
sol2_file_entry.grid(row = 0,sticky=EW)
b_choose_sol2.grid(row=0,sticky=W)
b_clear_sol2.grid(row=2,sticky=W)

# third frame
# mdlList_label = Label(third_frame,text = 'ModelList.txt file')
mdlList_file_entry = Entry(third_frame,width = 50)
b_choose_mdlList = Button(third_frame,text = "Choose ModelList.txt file..",command = callback,height = 2)
b_clear_mdlList =  Button(third_frame,text = "Clear ModelList",state=DISABLED)

# layout the widgets in the third frame
#mdlList_label.grid(row = 0,pady=5,sticky = 'ns')
mdlList_file_entry.grid(row = 0,sticky=EW)
b_choose_mdlList.grid(row=0,sticky=W)
b_clear_mdlList.grid(row=2,sticky=W)


#####################################################################
# create bottom widgets
#####################################################################
clear_all = Button(fourth_frame,text='Clear All',padx = '5',state=DISABLED)
ok_btn = Button(fourth_frame,text='OK',state=DISABLED)
cancel_btn = Button(fourth_frame,text='Cancel',padx = '12',command = my_exit)

#####################################################################
# layout the bottom widgets
#####################################################################
clear_all.grid(row = 0,column = 2,sticky = 'e')
ok_btn.grid(row = 0,column = 3,sticky = 'e')
cancel_btn.grid(row = 0,column = 4,sticky = 'e')

# commands/bindings

root2.mainloop()

解决方法

我相信这就是您要尝试做的。以下是对评论的完整注释。使用此方法,switch_clear变得完全不必要。这些按钮直接清除其command中的相应条目,而Entry验证则负责相应的按钮state

注意:在您发布完整代码之前,我已经写下了所有这些信息

import tkinter as tk

root = tk.Tk()
root.geometry('400x400')

#toggle the state of buttons based on entry text length        
def toggle_button(name,text):
    global btn_switch
    btn_switch[name]['state'] = 'normal' if len(text) else 'disabled'
    return True


#to hold the buttons so they are easy to position
#just for this example
buttons = tk.Frame(root)
buttons.pack(side='top',anchor='nw')

#create a tcl wrapper for the validate command
vcmd = tk.Widget.register(root,toggle_button)

#mock-up of your entries ~ validate on key press. send widget name and full text to vcmd
scn_file_entry     = tk.Entry(root,width=20)
scn_file_entry.configure(validate="key",validatecommand=(vcmd,'%W','%P'))
scn_file_entry.pack(side='left',anchor='nw')

sol2_file_entry    = tk.Entry(root,width=20)
sol2_file_entry.configure(validate="key",'%P'))
sol2_file_entry.pack(side='left',anchor='nw')

mdlList_file_entry = tk.Entry(root,width=20)
mdlList_file_entry.configure(validate="key",'%P'))
mdlList_file_entry.pack(side='left',anchor='nw')


#mock-up of your buttons ~ delete the entry text in a lambda and let entry validation handle the button state
b_clear_scn = tk.Button(buttons,text="scn",state='disabled')
b_clear_scn.configure(command=lambda: scn_file_entry.delete(0,'end'))
b_clear_scn.pack(side='left',anchor='nw')

b_clear_sol2 = tk.Button(buttons,text="sol2",state='disabled')
b_clear_sol2.configure(command=lambda: sol2_file_entry.delete(0,'end'))
b_clear_sol2.pack(side='left',anchor='nw')

b_clear_mdlList = tk.Button(buttons,text="mdl",state='disabled')
b_clear_mdlList.configure(command=lambda: mdlList_file_entry.delete(0,'end'))
b_clear_mdlList.pack(side='left',anchor='nw')


#create a dictionary of 'widget name':corresponding button,for toggle_button to reference
btn_switch = {
    f'{scn_file_entry}':b_clear_scn,f'{sol2_file_entry}':b_clear_sol2,f'{mdlList_file_entry}':b_clear_mdlList,}
   
root.mainloop()

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-