2012-12-20 82 views
3

在下面的代碼中,我遇到了線self.dmenu1.bind("<Button-1>", self.branches)的問題,如果有人可以請我指出正確的方向,我將非常感激。Python TKinter下拉菜單問題

我期待在下拉菜單中選擇一個選項,它會改變它下面的列表框中的排序。
但是實際發生的是,在我做出選擇之後,在排序生效之前,我必須再次單擊下拉框。

這不是用戶期望的下拉菜單的工作方式。我已經發布了完整的代碼,你可以看到我是新來的這一切,但它是一個學習:)提前

感謝您的幫助一個很好的挑戰。
問候,

from tkinter import * 

ALL = N+S+W+E 

users = ['Fred Asus','Tom Yahoo','Jessy Samsung','Jermain Sony','Nikki Nikon', 
     'Ian IBM','Elena Google','Rob Braun','Tammy Tonika','James Intel', 
     'Murphy Richards','Daniel Denon'] 

branchlst = {138:'Driving - St Albans', 170:'Brighton', 271:'Driving - Birmingham', 
      330:'Leeds', 680:'Edinburgh'} 

class Application(Frame): 

    def __init__(self, master=None): 
     #initiate the primary window. 
     Frame.__init__(self, master) 
     self.master.rowconfigure(0, weight=1) 
     self.master.columnconfigure(0, weight=1) 

     self.rowconfigure(0, weight=0) 
     self.rowconfigure(1, weight=0) 
     self.rowconfigure(2, weight=3) 
     self.columnconfigure(0, weight=0) 
     self.columnconfigure(1, weight=1) 
     self.columnconfigure(2, weight=1) 

     self.grid(sticky=ALL) 
     self.frameset() 

    def frameset(self): 
     #define and setup frames with columns and rows for widgets 
     #Colours added to framesets to help designing layout. delete them 
     self.Frame1 = Frame(self) # D 
     self.Frame2 = Frame(self, bg='blue') # E 
     self.Frame3 = Frame(self)    # L 
     self.Frame4 = Frame(self, bg='blue') # E 
     self.Frame5 = Frame(self) # T 
     self.Frame6 = Frame(self) # E colours 

     self.Frame1.rowconfigure(0,weight=0) 
     self.Frame2.rowconfigure(0,weight=0) 
     self.Frame3.rowconfigure(0,weight=1) 
     self.Frame4.rowconfigure(0,weight=1) 
     self.Frame5.rowconfigure(0,weight=1) 
     self.Frame6.rowconfigure(0,weight=1) 

     self.Frame1.columnconfigure(0,weight=0) 
     self.Frame2.columnconfigure(0,weight=0) 
     self.Frame3.columnconfigure(0,weight=1) 
     self.Frame4.columnconfigure(0,weight=1) 
     self.Frame5.columnconfigure(0,weight=1) 
     self.Frame6.columnconfigure(0,weight=1) 

     self.Frame1.grid(row=0, column=0, rowspan=1, columnspan=1, sticky=ALL) 
     self.Frame2.grid(row=0, column=1, columnspan=2, sticky=ALL) 
     self.Frame3.grid(row=1, column=0, rowspan=2, sticky=ALL) 
     self.Frame4.grid(row=1, column=1, columnspan=2, sticky=ALL) 
     self.Frame5.grid(row=2, column=1, rowspan=1, columnspan=1, sticky=ALL) 
     self.Frame6.grid(row=2, column=2, sticky=ALL) 


     label4a = Label(self.Frame4, text='table1', bg='orange') 
     label4b = Label(self.Frame4, text='table2', bg='yellow') 
     label4a.pack(side=LEFT) 
     label4b.pack(side=RIGHT) 

     self.objects() 

    def objects(self): 
     var = StringVar() 
     var.set('Name') 
     self.dmenu1 = OptionMenu(self.Frame1, var,'Costcode','Name') 
     self.dmenu1.pack(side=TOP, fill=BOTH) 
     self.dmenu1.bind("<Button-1>", self.branches) 

     self.f3ListBox = Listbox(self.Frame3, selectmode='single') 
     #self.branches() 
     self.f3ListBox.grid(sticky=ALL) 
     self.f3ListBox.bind("<Button-3>", self.f1handler1) 

     f5ListBox = Listbox(self.Frame5, selectmode='single') 
     n = 0 
     for item in users: 
      f5ListBox.insert(n,item) 
      n += 1 
     f5ListBox.grid(sticky=ALL) 

     f6ListBox = Listbox(self.Frame6, selectmode='single') 
     f6ListBox.insert(1,'S123456') # DELETE 
     f6ListBox.insert(2,'S313414') # DELETE 
     f6ListBox.insert(3,'S573343') # DELETE 
     f6ListBox.grid(sticky=ALL)  


    def f1handler1(self, event): 
     """Creates a popup menu for the alternative mouse button. 
     Edit this to add more options to that popup""" 
     select = lambda: self.f3ListBox.delete(ACTIVE) 
     popup = Menu(self, tearoff=0) 
     popup.add_command(label='Quit',command=self.quit) 
     popup.add_command(label='delete',command=select) #add more of these for more options 


     try: 
      popup.post(event.x_root, event.y_root) 
     except: 
      pass 
    def branches(self, event): 
     self.f3ListBox.delete(0,END) 
     n = 0 
     if self.dmenu1.cget('text') == 'Costcode': 
      cc = sorted(list(branchlst.keys())) 
      for item in cc: 
       self.f3ListBox.insert(n,str(item)+' '+branchlst[item]) 
       n += 1 
     elif self.dmenu1.cget('text') == 'Name': 
      bb = sorted(list(branchlst.values())) 
      for item in bb: 
       for name,val in branchlst.items(): 
        if item == val: 
         self.f3ListBox.insert(n,item+' '+str(name)) 

root = Tk() 
app = Application(master=root) 
app.mainloop() 

回答

5

我更喜歡理解問題和解決問題的途徑,所以讓我們通過它。在你的代碼中你有self.dmenu1.bind("<Button-1>", self.branches)

你問自己這個事件是什麼時候真正解僱?當您點擊OptionMenu時,它會被解僱。這意味着當前選項將是使用的選項。所以,假設選項「a」已激活,並且您更改爲選項「b」。此選擇更改不會觸發Button-1事件,但當您再次單擊您的OptionMenu時,它將觸發,然後小部件將具有「b」作爲當前選項。

什麼,你實際上是在你的代碼是:

self.dmenu1 = OptionMenu(self.Frame1, var,'Costcode','Name', 
         command=self.branches) 

和前面提到的結合可以安全地消除。剛剛添加的command選項將在您的OptionMenu上進行選擇時調用某個功能。除了這個改變,你可能還想在程序啓動時填充它的下面的列表框。爲此,請在定義self.f3ListBox後致電self.branches(None)

+0

謝謝你。這幫助我瞭解了很多。我在印象中需要綁定,並且你很好地回答了我想知道的另一個問題,self.branches(無),我沒有意識到無法在這裏工作。非常感謝,經驗教訓:) – Zenettii

+0

還有其他需要綁定的地方/場合,但這次不是。繼續與您的Tkinter發展,你會發現這些其他情況:) – mmgp

2

的STRINGVAR類有一個trace方法,它可以讓你的回調函數附加到它。該函數將在變量更改值時調用。

在你的代碼,添加剛剛在objects方法var.set('Name')線以下這一行。

var.trace('w', self.branches) 

這將導致self.branches被稱爲每當var變化。這將有三個參數來調用,所以你需要改變分行的定義:

def branches(self, name, index, mode): 

你也應該刪除self.dmenu1.bind("<Button-1>", self.branches)線,因爲它現在是多餘的。

+0

凱文,你的回覆在實現時確實很好地工作,我現在發現了var.trace方法,非常感謝你。我覺得@mmgp提供了一個更適合我和我現在的理解水平的答案。謝謝您的回覆。非常讚賞和信息。 – Zenettii

+0

@Zenettii這裏是一個免費的提示,我會給你:儘可能地堅持Python。我的意思是這個變量追蹤實際上是由Tcl完成的,而不是由Python完成的。由於兩種語言之間的根本區別,Python和Tcl之間的橋樑給出了關於數據類型的各種驚喜。如果您可以在Python中使用Tkinter時處理遠離Tcl變量,請執行此操作。 – mmgp