我遇到的问题是我能够使用Tkinter填充两个optionmenus(第二个动态基于第一个),但我注意到当我尝试选择第二个optionmenu中的一个值时,它没有请允许我选择。我注意到在同一个GUI上,有时在运行另一个函数时,它会对运行该函数之前工作正常的其他选项菜单产生影响。选项将正确显示,鼠标可以扫描它们,但是当您单击它时,它不会显示它已被选中,或执行设置为它的命令。以前有人有这个问题吗?
好吧,所以我对其他人有相同问题的希望正在下降,我会根据一些响应者的要求包含更多代码,以防这可能揭示问题。我会尝试拉一切适用的东西:
class GUI(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
self.build_gui()
#reads the tabs on an excel and inputs the tab names as the values in the first optionmenu (this works)
def read_board_tabs(self):
#many of these variables in the function may not be defined. Ignore them as they are taken out of context. This should just help visually see the structure.
filepath = 'Board Control.xlsx'
wkbk = load_workbook((filepath))
sheets = wkbk.get_sheet_names()
print sheets
return sheets
#reads content of that excel tab chosen to populate the second optionmenu (populating the option menu works, but they can't be selected once populated)
def read_serials(self, board):
#many of these variables in the function may not be defined. Ignore them as they are taken out of context. This should just help visually see the structure.
sheet = board
if(sheet == ''):
return ['']
else:
filepath = 'Board Control.xlsx'
workbook = excel_transfer.workbook(filepath)
wb = workbook.open_existing_workbook()
ws = workbook.activate_specific_worksheet(wb, sheet)
row = 1
current_row = 0
previous_row = 0
serials = []
#read the serials that exist for the board selected
while current_row != None:
previous_row = current_row
row = row + 1
cell = 'A' + str(row)
current_row = workbook.read_new_cell(cell, ws)
if(current_row != None):
serials.append(current_row)
if(len(serials) == 0):
serials = ['']
self.BOARD_SERIAL_OPTION['menu'].delete(0, 'end')
for item in serials:
self.BOARD_SERIAL_OPTION['menu'].add_command(label=item)
#this is the command that won't execute when I try to select the second optionmenu value
def find_board_info(self, serial):
#many of these variables in the function may not be defined. Ignore them as they are taken out of context. This should just help visually see the structure.
self.board_checkout_status_var.set('')
sheet = (self.boards_var).get()
new_search = StringFound.StringSearch(serial)
results = new_search.read_board(sheet)
if(results == ['']):
self.boardstatusvar.set('No board was found')
else:
self.boardstatusvar.set('Board: %s Serial: %s' %(results[1], serial))
self.boardstatus_locationvar.set('Found in file: %s' %results[0])
self.boards_var.set('%s serial %s' %(results[1], serial))
self.dispositionvar.set(results[3])
self.TXvar.set(results[5])
self.RXvar.set(results[6])
self.lastvar.set(results[10])
self.datevar.set(results[9])
if(results[14] != None):
self.currentvar.set(results[10])
self.locationvar.set(results[4])
self.imagevar.set(results[8])
self.notesvar.set(results[12])
self.current_board_chosen = [sheet, serial, results[15]]
#creates the gui
def build_gui(self):
n = Notebook(self)
board_process = Tkinter.LabelFrame(self, text="Board Updates")
n.add(board_process, text='Board Signout')
n.pack()
self.boards_var = StringVar()
self.boards_var.set("")
self.serials_var = StringVar()
self.serials_var.set("")
self.SEARCHBOARDFRAME = Tkinter.LabelFrame(board_process, text='Find Board')
self.SEARCHBOARDFRAME.grid(row=0, column=0, sticky='WE')
self.BOARD_SEARCH_LABEL = Label(self.SEARCHBOARDFRAME, text='Type:')
self.BOARD_SEARCH_LABEL.grid(row=0, column=0, sticky='W', padx=5, pady=2)
self.BOARD_SEARCH_OPTION = OptionMenu(self.SEARCHBOARDFRAME, self.boards_var, *self.list_of_boards, command=self.read_serials)
self.BOARD_SEARCH_OPTION.grid(row=0, column=1, sticky='W', padx=5, pady=2)
self.BOARD_SERIAL_LABEL = Label(self.SEARCHBOARDFRAME, text='Serial:')
self.BOARD_SERIAL_LABEL.grid(row=1, column=0, sticky='W', padx=5, pady=2)
self.BOARD_SERIAL_OPTION = OptionMenu(self.SEARCHBOARDFRAME, self.serials_var, *self.list_of_serials, command=self.find_board_info)
self.BOARD_SERIAL_OPTION.grid(row=1, column=1, sticky='W', padx=5, pady=2)
if __name__ == '__main__':
root = Tk()
app = GUI(root)
root.mainloop()
答案 0 :(得分:2)
问题在于以下几行代码:
for item in serials:
self.BOARD_SERIAL_OPTION['menu'].add_command(label=item)
您正在选项菜单中添加标签,但您没有给他们命令。 Optionmenu小部件存在的全部原因是为每个项添加一个特殊命令,为命令菜单提供其行为。除非您在动态创建新项目时添加该命令,否则这些项目在您选择它们时不会做任何事情 - 它只是一个带有标签的愚蠢菜单。
不幸的是,与私有工厂类(Tkinter._setit)返回与每个项目关联的命令,因此您没有任何官方支持的方法将新项目添加到选项菜单。如果您不担心使用私人命令,可以将代码更改为:
for item in serials:
command=Tkinter._setit(self.serials_var, item, self.find_board_info)
self.BOARD_SERIAL_OPTION['menu'].add_command(label=item, command=command)
要解决此问题,请参阅Change OptionMenu based on what is selected in another OptionMenu