tkinter自定义下拉多选框问题

 更新时间:2023年01月28日 10:17:12   作者:奋斗中的打工人  
这篇文章主要介绍了tkinter自定义下拉多选框问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

使用tkinter实现下拉多选框

效果如图:

1、选择一些选项

2、全选选项

代码如下:

import tkinter
 
from ComBoPicker import Combopicker
 
list = ["全选", "选项1", "选项2", "选项3", "选项4", "选项5", "选项6"]
root = tkinter.Tk()
co = Combopicker(root, values=list)
co.pack()
root.geometry("800x600")
 
root.mainloop()

ComBoPicker.py代码:

'''
	自定义多选下拉列表
'''
import tkinter.ttk as ttk
from tkinter import *
 
 
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
        self.index = 0
        ttk.Frame.__init__(self, master, borderwidth=borderwidth, height=10, relief=relief)
 
        self.bind("<FocusIn>", lambda event: self.event_generate('<<PickerFocusIn>>'))
        self.bind("<FocusOut>", lambda event: self.event_generate('<<PickerFocusOut>>'))
        F = LabelFrame(self)
        F.pack(fill='x')
        self.canvas = Canvas(F, scrollregion=(0, 0, 500, (len(self._values) * 23)))
 
 
        vbar = Scrollbar(F, orient=VERTICAL)
        vbar.pack(side=RIGHT, fill=Y)
 
        frame = Frame(self.canvas) #创建框架
        vbar.config(command=self.canvas.yview)
 
        sbar2 = Scrollbar(F, orient=HORIZONTAL)
        sbar2.pack(side=BOTTOM, fill=X)
        sbar2.config(command=self.canvas.yview)
        # self.canvas.pack(side='left',fill='x',expand=True)
        self.canvas.create_window((0, 0,), window=frame, anchor='nw', tags='frame')
 
        self.canvas.config(highlightthickness=0)  # 去掉选中边框
        vbar.config(command=self.canvas.yview)
        sbar2.config(command=self.canvas.xview)
        self.canvas.config(width=300, height=150)
        self.canvas.config(yscrollcommand=vbar.set,xscrollcommand=sbar2.set)
        # self.canvas.config(scrollregion=self.canvas.bbox('all'))
        # 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] = IntVar()
            self.dict_checkbutton[item] = ttk.Checkbutton(frame, 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=NSEW, padx=5)
            self.dict_intvar_item[item].set(0)
            if item in self._entry_wid.get().split(','):
                self.dict_intvar_item[item].set(1)
        self.canvas.pack(side=LEFT, expand=True, fill=BOTH)
        self.canvas.bind("<MouseWheel>", self.processWheel)
        frame.bind("<MouseWheel>", self.processWheel)
        for i in self.dict_checkbutton:
            self.dict_checkbutton[i].bind("<MouseWheel>", self.processWheel)
        self.bind("<MouseWheel>", self.processWheel)
 
 
 
    def processWheel(self, event):
        a = int(-(event.delta))
        if a > 0:
            self.canvas.yview_scroll(1, UNITS)
        else:
            self.canvas.yview_scroll(-1, UNITS)
 
 
class Combopicker(ttk.Combobox, Picker):
    def __init__(self, master, values=[], entryvar=None, entrywidth=None, entrystyle=None, onselect=None,
                 activebackground='#ef476f', activeforeground='red', selectbackground='#ffd166',
                 selectforeground='green', borderwidth=1, relief="solid"):
 
        self.values = values
        self.master = master
        self.activeforeground = activeforeground
        self.activebackground = activebackground
        self.selectbackground = selectbackground
        self.selectforeground = selectforeground
 
        if entryvar is not None:
            self.entry_var = entryvar
        else:
            self.entry_var = 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="")
 
        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(self.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:
            if '全选' == str(SELECTED):
                value.clear()  # 清空选项
            else:
                value.remove(str(SELECTED))
                value.sort()
        else:
            if '全选' == str(SELECTED):
                value = self.values
            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)
        # 可以通过复选框的variable来让勾选中或取消,但下面也行,问题不大
        if '全选' == str(SELECTED):
            self.hide_picker()
            self.show_picker()
 
    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 = Picker(self.winfo_toplevel(), values=self.values, entry_wid=self.entry_var,
                                       activebackground=self.activebackground,
                                       activeforeground=self.activeforeground, selectbackground=self.selectbackground,
                                       selectforeground=self.selectforeground, command=self._on_selected_check)
 
            self.bind_all("<1>", self._on_click, "+")
 
            self.bind("<Escape>", lambda event: self.hide_picker())
            self.picker_frame.lift()
            self.picker_frame.place(in_=self, relx=0, rely=1, relwidth=1)
 
        self._is_menuoptions_visible = True
 
    def hide_picker(self):
        if self._is_menuoptions_visible:
            self.picker_frame.place_forget()  # 不知道为什么这个方式在mac下不起作用,所以就直接销毁这个控件
            # self.picker_frame.destroy()
 
        self._is_menuoptions_visible = False

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Python图像锐化与边缘检测之Sobel与Laplacian算子详解

    Python图像锐化与边缘检测之Sobel与Laplacian算子详解

    图像锐化和边缘检测主要包括一阶微分锐化和二阶微分锐化,本文主要讲解常见的图像锐化和边缘检测方法,即Sobel算子和Laplacian算子,感兴趣的可以了解一下
    2022-12-12
  • Python提高运行速度工具之Pandarallel的使用教程

    Python提高运行速度工具之Pandarallel的使用教程

    为了提高运行速度,我们一般会采用多进程的方式。而常见的方案对于普通python玩家来说都不是特别友好,怎样才能算作一个友好的并行处理方案?本文就来和大家讲讲pandarallel的使用
    2022-09-09
  • pytorch教程之网络的构建流程笔记

    pytorch教程之网络的构建流程笔记

    这篇文章主要介绍了pytorch教程中网络的构建流程,文中附含了详细的示例代码流程,有需要的朋友可以借鉴参考下,希望可以有所帮助
    2021-09-09
  • Python排序搜索基本算法之选择排序实例分析

    Python排序搜索基本算法之选择排序实例分析

    这篇文章主要介绍了Python排序搜索基本算法之选择排序,简单说明了选择排序的原理,并结合实例形式分析了Python实现选择排序的具体操作技巧,需要的朋友可以参考下
    2017-12-12
  • Python实现的求解最大公约数算法示例

    Python实现的求解最大公约数算法示例

    这篇文章主要介绍了Python实现的求解最大公约数算法,涉及Python数学运算相关操作技巧,需要的朋友可以参考下
    2018-05-05
  • 详解python3 GUI刷屏器(附源码)

    详解python3 GUI刷屏器(附源码)

    这篇文章主要介绍了详解python3 GUI刷屏器(附源码),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-02-02
  • 卡尔曼滤波数据处理技巧通俗理解及python实现

    卡尔曼滤波数据处理技巧通俗理解及python实现

    这篇文章主要为大家介绍了卡尔曼滤波数据处理技巧的通俗理解及python实现,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-05-05
  • Python实现的银行系统模拟程序完整案例

    Python实现的银行系统模拟程序完整案例

    这篇文章主要介绍了Python实现的银行系统模拟程序,结合完整实例形式分析了Python基于面向对象程序设计模拟的银行系统登录验证、开户、找回密码、挂失、查询、存取款、转账等功能相关操作技巧,需要的朋友可以参考下
    2019-04-04
  • Python处理键映射值操作详解

    Python处理键映射值操作详解

    这篇文章主要为大家详细介绍了Python中的处理键映射值操作的相关资料,文中的示例代码讲解详细,具有一定的学习价值,感兴趣的小伙伴可以了解一下
    2022-11-11
  • 浅谈django orm 优化

    浅谈django orm 优化

    这篇文章主要介绍了浅谈django orm 优化,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-08-08

最新评论