Python Tkinter无法在optionmenu中选择选项

时间:2014-09-24 15:51:11

标签: python tkinter optionmenu

我遇到的问题是我能够使用Tkinter填充两个optionmenus(第二个动态基于第一个),但我注意到当我尝试选择第二个optionmenu中的一个值时,它没有请允许我选择。我注意到在同一个GUI上,有时在运行另一个函数时,它会对运行该函数之前工作正常的其他选项菜单产生影响。选项将正确显示,鼠标可以扫描它们,但是当您单击它时,它不会显示它已被选中,或执行设置为它的命令。以前有人有这个问题吗?

enter image description here 好吧,所以我对其他人有相同问题的希望正在下降,我会根据一些响应者的要求包含更多代码,以防这可能揭示问题。我会尝试拉一切适用的东西:

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()

1 个答案:

答案 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