2013-05-10 67 views
2

大家好,並提前致謝!Python tkinter:排序OptionMenu小部件的內容

我在谷歌周圍搜索了幾乎每一個結果,我得到了,我仍然無法確定
它,所以請至少指出我的方向!
我讀了關於pmw,但我想看看是否有任何方式與tkinter首先做到這一點。

我正在爲DnD骰子卷寫一個簡單的程序,我有一個OptionMenu
包含一些人需要玩的骰子。我還有一個輸入字段,用於輸入
一個未包含在我的默認選項中的模具。我的問題是,即使新的
選項已成功添加,選項不排序。

我解決了它在某些時候被破壞OptionMenu添加了新的選項時,
整理我的列表,然後從頭開始重建OptionMenu,但是我用的是
地方管理方法在那個時候,我不得不稍後重寫程序,因爲我有
一些解決問題。我現在正在使用包管理器,並且銷燬/重建
不是一個選項,除非我想「重新」打包所有的小部件或爲它們製作獨佔標籤!

這裏是我的代碼工作示例:

from tkinter import * 

class DropdownExample(Frame): 
    def __init__(self, master = None): 
     Frame.__init__(self, master) 
     self.pack(fill = 'both', expand = True) 

     # Add Option Button 
     self.addOptBtn = Button(self, text = "Add Option", command = self.add_option) 

     # Option Input Field 
     self.newOpt = IntVar() 
     self.newOpt.set("Type a number") 

     self.optIn = Entry(self) 
     self.optIn['textvariable'] = self.newOpt 

     # Dropdown Menu 
     self.myOptions = [0, 1, 2] 

     self.selOpt = IntVar() 
     self.selOpt.set("Options") 

     self.optMenu = OptionMenu(self, self.selOpt, *self.myOptions) 

     # Positioning 
     self.addOptBtn.pack(side = 'left', padx = 5) 
     self.optIn.pack(side = 'left', padx = 5) 
     self.optMenu.pack(side = 'left', padx = 5) 


    def add_option(self): 
     self.numToAdd = "" 
     self.counter = 0 

     try: 
      self.numToAdd = int(self.optIn.get())           # Integer validation 

      while self.counter < len(self.myOptions):          # Comparison loop & error handling 
       if self.numToAdd == self.myOptions[self.counter]: 
        print("Already exists!")      
        break; 

       elif self.numToAdd < 0: 
        print("No less than 0!") 
        break; 

       elif self.counter < len(self.myOptions)-1: 
        self.counter += 1 

       else:                  # Dropdown menu option addition 
        self.myOptions.append(self.numToAdd) 
        self.myOptions.sort() 

        self.optMenu['menu'].add_command(label = self.numToAdd) 

        self.selOpt.set(self.numToAdd) 

        print("Added succesfully!") 

        self.counter += 2 

     except ValueError: 
      print("Type ONLY numbers!") 


def runme(): 
    app = DropdownExample() 
    app.master.title("Dropdown Menu Example") 
    app.master.resizable(0, 0) 
    app.mainloop() 

runme() 

我使用Python 3.3在Windows 7

回答

1

有一組在Menuinsert_something()方法。您必須保持您的列表與每個插入(bisect模塊)分類。

from tkinter import * 
import bisect 

... 
       else:                  # Dropdown menu option addition 
        index = bisect.bisect(self.myOptions, self.numToAdd) 
        self.myOptions.insert(index, self.numToAdd) 
        self.optMenu['menu'].insert_command(index, label=self.numToAdd) 
        self.selOpt.set(self.numToAdd) 
        print("Added succesfully!", self.myOptions) 
        self.counter += 2 
+0

非常感謝!這工作很好,正是我所需要的。我不知道_bisect_模塊。我讀了一些關於在我的菜單中插入索引特定項目的地方,但我無法獲得我需要的索引。這一切都有道理,再次感謝! – 2013-05-10 14:52:51

0

將行:

self.optMenu['menu'].add_command(label = self.numToAdd) 

有:

for dit in self.myOptions: 
    self.optMenu['menu'].delete(0) 
for dat in self.myOptions: 
    self.optMenu['menu'].add_command(label = dat) 

的小問題,就是 「add_command」 需要的項目添加到菜單,而 「刪除」 採取指數的項目。

+0

這種方式也有效,但還有另一個問題。一旦我添加一個選項到菜單,我不能選擇任何其他。我和@kalgasnik的回答有幾乎相同的問題,我可以輸入一個新號碼,排序菜單,但我只能選擇其中一個默認選項。所有其他的只是出現。 myOptions列表已更新,菜單列表已更新,所以我的猜測是它與更新optMenu ['menu']有關。 (我可能完全錯了那個^^)。我會進一步研究併發布解決方案。 – 2013-05-11 01:46:12

+0

順便說一句,這個問題也存在於我的示例代碼中 – 2013-05-11 01:59:51

0

看來,無論我選擇在這一個上面選擇什麼方式,它都歸結爲更新
小部件。
更新一個框架通常會根據需要重新繪製一部分或整個框架。
所以我回到原點。我摧毀了小部件,更新了列表,然後再次創建它。
至於位置,我只使用OptionMenu作爲背景的標籤。
這樣我就可以按我的要求刪除/替換我的OptionMenu,而無需移動任何附件,只要它保留在它的標籤內,並且它是唯一一個,當然只要我不移動任何標籤。

這可能是一個解決方法,而不是一個解決方案,但它可以完成工作,並且可以用於任何其他具有相同問題的窗口小部件。

from tkinter import * 

class DropdownExample(Frame): 
    def __init__(self, master = None): 
     Frame.__init__(self, master) 
     self.pack(fill = 'both', expand = True) 

     # Add Option Button 
     self.addOptBtn = Button(self, text = "Add Option", command = self.add_option) 

     # Option Input Field 
     self.newOpt = IntVar() 
     self.newOpt.set("Type a number") 

     self.optIn = Entry(self) 
     self.optIn['textvariable'] = self.newOpt 

     # Dropdown Menu 
     # menu's label 
     self.optMenuLabel = Label(self) 

     # option menu 
     self.myOptions = [0, 1, 2] 

     self.selOpt = IntVar() 
     self.selOpt.set("Options") 

     self.optMenu = OptionMenu(self.optMenuLabel, self.selOpt, *self.myOptions) 

     # Positioning 
     self.addOptBtn.pack(side = 'left', padx = 5) 
     self.optIn.pack(side = 'left', padx = 5) 
     self.optMenuLabel.pack(side = 'left', padx = 5) 
     self.optMenu.pack(side = 'left', padx = 5) 


    def add_option(self): 
     self.numToAdd = "" 
     self.counter = 0 

     try: 
      self.numToAdd = int(self.optIn.get())           # Integer validation 

      while self.counter < len(self.myOptions):          # Comparison loop & error handling 
       if self.numToAdd == self.myOptions[self.counter]: 
        print("Already exists!")      
        break; 

       elif self.numToAdd < 0: 
        print("No less than 0!") 
        break; 

       elif self.counter < len(self.myOptions)-1: 
        self.counter += 1 

       else:                  # Dropdown menu option addition 
        self.myOptions.append(self.numToAdd) 
        self.myOptions.sort() 

        self.selOpt.set(self.numToAdd) 

        self.optMenu.destroy() 
        self.optMenu = OptionMenu(self.optMenuLabel, self.selOpt, *self.myOptions) 
        self.optMenu.pack(side = 'left', padx = 5) 

        print("Added succesfully!", self.myOptions) 
        break; 

     except ValueError: 
      print("Type ONLY numbers!") 


def runme(): 
    app = DropdownExample() 
    app.master.title("Dropdown Menu Example") 
    app.master.resizable(0, 0) 
    app.mainloop() 

runme()