2014-09-24 125 views
-2

我遇到了問題,我能夠使用Tkinter填充兩個選項菜單(第二個動態基於第一個菜單),但我注意到當我嘗試選擇其中一個第二個選項菜單中的值,它不允許我選擇。我注意到在同一個圖形用戶界面中,有時運行另一個函數時,它會在運行該函數之前運行良好的不同選項菜單上產生這種影響。這些選項將正確顯示,並且鼠標可以掃描它們,但是當您點擊一個選項時,它不會顯示它已被選中,或者執行對其設置的命令。有沒有人有過這個問題?好的,所以我對其他人有同樣問題的希望正在下降,並且我會通過請求某些響應者來包含更多的代碼,以防這可能會解決問題。我會試着拉適用一切:Python Tkinter無法在選項菜單中選擇選項

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

您可能希望更精確。展示一小段代碼來再現您的問題。 – joaquin 2014-09-24 16:03:00

+0

我認爲這是很多問題所在。我不確定代碼中問題的確切位置,並且有超過一千行代碼,在這裏發佈它是不切實際的。我有一個較早的帖子[這裏](http://stackoverflow.com/questions/25898211/tkinter-how-to-make-a-dynamic-optionmenu-without-using-a-dictionary),顯示更多的結構代碼如果有幫助。我希望別人可能遇到類似的問題,因爲一旦某個函數運行後就無法選擇一個值,並且可能能夠分享他們爲什麼會遇到這個問題的經驗。 – Joe 2014-09-24 16:08:08

+3

@Joe:減少問題的運用通常足以發現問題。 Tkinter沒有像這樣的錯誤,所以問題當然是你如何做事。沒有我們能夠看到複製問題的代碼,我們無法提供幫助。 – 2014-09-24 16:12:25

回答

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

+0

謝謝你的幫助!將命令添加到add_command解決了問題! – Joe 2014-09-26 15:13:33

+0

我最終不得不將它改變爲這個參數來傳遞:self.BOARD_SERIAL_OPTION ['menu']。add_command(label = item,command = lambda item = item:self.find_board_info(item)) – Joe 2014-09-26 15:51:13