【问题标题】:How do I enable multiple selection of values from a combobox?如何从组合框中启用多项选择值?
【发布时间】:2015-12-31 17:36:41
【问题描述】:

Python 3.4.3、Windows 10、Tkinter

我正在尝试创建一个允许从下拉列表中进行多项选择的组合框。我为列表框 (Python Tkinter multiple selection Listbox) 找到了类似的工作,但无法使其与组合框一起使用。

有没有一种简单的方法可以从组合框的下拉菜单中启用多项选择?

【问题讨论】:

    标签: python combobox tkinter


    【解决方案1】:

    试试这个吧……

    import tkinter as Tkinter
    import tkinter.font as tkFont
    import tkinter.ttk as ttk
    
    class Picker(ttk.Frame):
    
        def __init__(self, master=None,activebackground='#b1dcfb',values=[],entry_wid=None,activeforeground='black', selectbackground='#003eff', selectforeground='white', command=None, borderwidth=1, relief="solid"):
    
            self._selected_item = None
    
            self._values = values
    
            self._entry_wid = entry_wid
    
            self._sel_bg = selectbackground 
            self._sel_fg = selectforeground
    
            self._act_bg = activebackground 
            self._act_fg = activeforeground
    
            self._command = command
            ttk.Frame.__init__(self, master, borderwidth=borderwidth, relief=relief)
    
            self.bind("<FocusIn>", lambda event:self.event_generate('<<PickerFocusIn>>'))
            self.bind("<FocusOut>", lambda event:self.event_generate('<<PickerFocusOut>>'))
    
            self._font = tkFont.Font()
    
            self.dict_checkbutton = {}
            self.dict_checkbutton_var = {}
            self.dict_intvar_item = {}
    
            for index,item in enumerate(self._values):
    
                self.dict_intvar_item[item] = Tkinter.IntVar()
                self.dict_checkbutton[item] = ttk.Checkbutton(self, text = item, variable=self.dict_intvar_item[item],command=lambda ITEM = item:self._command(ITEM))
                self.dict_checkbutton[item].grid(row=index, column=0, sticky=Tkinter.NSEW)
                self.dict_intvar_item[item].set(0)
    
    
    class Combopicker(ttk.Entry, Picker):
        def __init__(self, master, values= [] ,entryvar=None, entrywidth=None, entrystyle=None, onselect=None,activebackground='#b1dcfb', activeforeground='black', selectbackground='#003eff', selectforeground='white', borderwidth=1, relief="solid"):
    
            if entryvar is not None:
                self.entry_var = entryvar
            else:
                self.entry_var = Tkinter.StringVar()
    
            entry_config = {}
            if entrywidth is not None:
                entry_config["width"] = entrywidth
    
            if entrystyle is not None:
                entry_config["style"] = entrystyle
    
            ttk.Entry.__init__(self, master, textvariable=self.entry_var, **entry_config, state = "readonly")
    
            self._is_menuoptions_visible = False
    
            self.picker_frame = Picker(self.winfo_toplevel(), values=values,entry_wid = self.entry_var,activebackground=activebackground, activeforeground=activeforeground, selectbackground=selectbackground, selectforeground=selectforeground, command=self._on_selected_check)
    
            self.bind_all("<1>", self._on_click, "+")
    
            self.bind("<Escape>", lambda event: self.hide_picker())
    
        @property
        def current_value(self):
            try:
                value = self.entry_var.get()
                return value
            except ValueError:
                return None
    
        @current_value.setter
        def current_value(self, INDEX):
            self.entry_var.set(values.index(INDEX))
    
        def _on_selected_check(self, SELECTED):
    
            value = []
            if self.entry_var.get() != "" and self.entry_var.get() != None:
                temp_value = self.entry_var.get()
                value = temp_value.split(",")
    
            if str(SELECTED) in value:
                value.remove(str(SELECTED))
    
            else:    
                value.append(str(SELECTED))
    
            value.sort()
    
            temp_value = ""
            for index,item in enumerate(value):
                if item!= "":
                    if index != 0:
                        temp_value += ","
                    temp_value += str(item)
    
            self.entry_var.set(temp_value)
    
        def _on_click(self, event):
            str_widget = str(event.widget)
    
            if str_widget == str(self):
                if not self._is_menuoptions_visible:
                    self.show_picker()
            else:
                if not str_widget.startswith(str(self.picker_frame)) and self._is_menuoptions_visible:
                    self.hide_picker()
    
        def show_picker(self):
            if not self._is_menuoptions_visible:
                self.picker_frame.place(in_=self, relx=0, rely=1, relwidth=1 )
                self.picker_frame.lift()
    
            self._is_menuoptions_visible = True
    
        def hide_picker(self):
            if self._is_menuoptions_visible:
                self.picker_frame.place_forget()
    
            self._is_menuoptions_visible = False
    
    if __name__ == "__main__":
        import sys
    
        try:
            from Tkinter import Tk, Frame, Label
        except ImportError:
            from tkinter import Tk, Frame, Label
    
        root = Tk()
        root.geometry("500x600")
    
        main =Frame(root, pady =15, padx=15)
        main.pack(expand=True, fill="both")
    
        Label(main, justify="left", text=__doc__).pack(anchor="w", pady=(0,15))
    
        COMBOPICKER1 = Combopicker(main, values = [1, 2, 3, 4])
        COMBOPICKER1.pack(anchor="w")
    
    
        if 'win' not in sys.platform:
            style = ttk.Style()
            style.theme_use('clam')
    
        root.mainloop()
    

    【讨论】:

      【解决方案2】:

      按照设计,ttk 组合框不支持多选。它旨在让您从选项列表中选择一项。

      如果您需要能够做出多项选择,您可以使用带有关联菜单的菜单按钮,并向菜单添加复选按钮或单选按钮。

      这是一个例子:

      import Tkinter as tk
      
      class Example(tk.Frame):
          def __init__(self, parent):
              tk.Frame.__init__(self, parent)
      
              menubutton = tk.Menubutton(self, text="Choose wisely", 
                                         indicatoron=True, borderwidth=1, relief="raised")
              menu = tk.Menu(menubutton, tearoff=False)
              menubutton.configure(menu=menu)
              menubutton.pack(padx=10, pady=10)
      
              self.choices = {}
              for choice in ("Iron Man", "Superman", "Batman"):
                  self.choices[choice] = tk.IntVar(value=0)
                  menu.add_checkbutton(label=choice, variable=self.choices[choice], 
                                       onvalue=1, offvalue=0, 
                                       command=self.printValues)
          def printValues(self):
              for name, var in self.choices.items():
                  print "%s: %s" % (name, var.get())
      
      if __name__ == "__main__":
          root = tk.Tk()
          Example(root).pack(fill="both", expand=True)
          root.mainloop()
      

      【讨论】:

      • 尝试这个例子......但是,在 macOS 10.13.6 和 Python 3.7.1 Homebrew 上,单击菜单项会给我带来混乱的结果,复选标记的出现和消失不符合假设的逻辑你点击每个项目。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-11-28
      • 2022-06-30
      • 1970-01-01
      • 2013-12-04
      • 2012-05-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多