tkinter自定義下拉多選框問題
更新時間:2023年01月28日 10:17:12 作者:奮斗中的打工人
這篇文章主要介紹了tkinter自定義下拉多選框問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
使用tkinter實(shí)現(xiàn)下拉多選框
效果如圖:
1、選擇一些選項(xiàng)
2、全選選項(xiàng)
代碼如下:
import tkinter from ComBoPicker import Combopicker list = ["全選", "選項(xiàng)1", "選項(xiàng)2", "選項(xiàng)3", "選項(xiàng)4", "選項(xiàng)5", "選項(xiàng)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) #創(chuàng)建框架 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() # 清空選項(xiàng) 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) # 可以通過復(fù)選框的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
總結(jié)
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Django?Rest?Framework實(shí)現(xiàn)身份認(rèn)證源碼詳解
這篇文章主要為大家介紹了Django?Rest?Framework實(shí)現(xiàn)身份認(rèn)證源碼詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05使用Scrapy框架爬取網(wǎng)頁并保存到Mysql的實(shí)現(xiàn)
本文主要介紹了使用Scrapy框架爬取網(wǎng)頁并保存到Mysql的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07python3 requests庫文件上傳與下載實(shí)現(xiàn)詳解
這篇文章主要介紹了python3 requests庫文件上傳與下載實(shí)現(xiàn)詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-08-08Python中關(guān)于函數(shù)的具體用法范例以及介紹
函數(shù)是組織好的,可重復(fù)使用的,用來實(shí)現(xiàn)單一,或相關(guān)聯(lián)功能的代碼段。函數(shù)能提高應(yīng)用的模塊性,和代碼的重復(fù)利用率。你已經(jīng)知道Python提供了許多內(nèi)建函數(shù),比如print()。但你也可以自己創(chuàng)建函數(shù),這被叫做用戶自定義函數(shù)2021-09-09Python 調(diào)用有道翻譯接口實(shí)現(xiàn)翻譯
這篇文章主要介紹了Python 調(diào)用有道翻譯接口實(shí)現(xiàn)翻譯,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03