如何解决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 举报,一经查实,本站将立刻删除。