点击entry,弹出下拉框(toplevel窗体),但是当我最小化主窗体时,下拉框并没有跟随最小化而是留在原来的位置,请问怎样处理才能跟随主窗体最小化一起隐藏呢?
from tkinter import Frame, Listbox, Scrollbar, StringVar, Toplevel # , Tk,Entry,
# from tkinter.constants import END, EW, HORIZONTAL, NS
import ttkbootstrap as ttk
from ttkbootstrap.constants import *
my_str = ['', '', '', '', '', '']
# global my_bool_hide
my_bool_hide = False # 判断顶置窗口是否隐藏,默认隐藏
def singleton(cls, *args, **kwargs):
instances = {}
def _singleton():
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return _singleton
@singleton
class ListBox(object):
"""ListBox Class"""
def __init__(self):
self.top_window = None
def init(self, width):
self.width = width
def my_show(self, p_master, values, master, my_levels):
self.p_master = p_master
self.master = master
self.values = values
self.my_levels = my_levels
if self.top_window:
return
x = self.master.winfo_rootx()
y = self.master.winfo_rooty() + self.master.winfo_height()
# self.top_window = Toplevel(self.master)
self.top_window = Toplevel(self.master) # winfo_toplevel
# self.top_window.
####################
# self.top_window.grab_set()
# self.top_window.transient(self.master.master.master.master.master.master.master)
######################
self.top_window.overrideredirect(1)
self.top_window.geometry("+%d+%d" % (x, y))
self.top_window.bind('<Configure>', self.on_change_geometry)
self.top_window.bind_all("<Button-1>", self.on_gloabl_click) # <ButtonRelease-1>
# self.top_window.bind_all("<ButtonRelease-1>", self.on_gloabl_click) # <ButtonRelease-1>
# self.top_window.bind("<FocusOut>", self.on_focus_out)
self.sb_y = Scrollbar(self.top_window)
self.sb_x = Scrollbar(self.top_window, orient=HORIZONTAL)
# self.sb_x.grid(row=1, column=0, sticky=EW)
self.sb_x.pack(fill=X)
self.list_box = Listbox(self.top_window,
xscrollcommand=self.sb_x.set,
yscrollcommand=self.sb_y.set,
width=self.width)
for data in self.values:
self.list_box.insert(END, data)
if self.p_master.input_var.get() != '' and self.p_master.input_var.get() in self.values:
index = self.values.index(self.p_master.input_var.get())
else:
index = 0
self.list_box.select_set(index)
self.list_box.bind("<ButtonRelease-1>", self.on_click_item)
self.sb_x.config(command=self.list_box.xview)
self.sb_y.config(command=self.list_box.yview)
# self.sb_y.grid(row=0, column=1, sticky=NS)
self.sb_y.pack(fill=Y, anchor=E, side='right')
# self.sb_x.grid(row=1, column=0, sticky=EW)
self.sb_x.pack(fill=X, anchor=N, side='bottom')
# self.list_box.grid(row=0, column=0)
self.list_box.pack(fill=BOTH, expand=1)
global my_bool_hide
my_bool_hide = True
# print(master.winfo_children())
def on_gloabl_click(self, event):
if isinstance(event.widget, Listbox) or isinstance(
event.widget, Scrollbar):
pass
else:
self.hide()
def hide(self):
if self.top_window:
# if self.p_master.input_var.get() == '' or self.p_master.input_var.get() not in self.values:
# self.p_master.input_var.set(self.list_box.get(0))
self.p_master.entry.icursor(len(self.p_master.input_var.get()))
self.top_window.destroy()
self.top_window = None
global my_bool_hide
my_bool_hide = False
# self.master.master.master.master.master.master.master.attributes("-disabled", 0)
# print(my_bool_hide)
def on_change_geometry(self, event):
x = self.master.winfo_rootx()
y = self.master.winfo_rooty() + self.master.winfo_height()
self.top_window.wm_geometry("+%d+%d" % (x, y))
def on_click_item(self, event):
self.p_master.input_var.set(
self.list_box.get(self.list_box.curselection()))
global my_str
if self.my_levels == 0: # 第一个参数
my_str[0] = self.p_master.input_var.get()
elif self.my_levels == 1: # 第二个参数
my_str[1] = self.p_master.input_var.get()
elif self.my_levels == 2:
my_str[2] = self.p_master.input_var.get()
elif self.my_levels == 3:
my_str[3] = self.p_master.input_var.get()
elif self.my_levels == 4:
my_str[4] = self.p_master.input_var.get()
elif self.my_levels == 5:
my_str[5] = self.p_master.input_var.get()
# #####################
self.hide()
def update_list(self):
datas = []
for value in self.values:
if self.p_master.input_var.get() in value:
datas.append(value)
self.list_box.delete(0, END)
if len(datas) == 0 and self.p_master.input_var.get() == '':
datas = self.values
elif len(datas) == 0 and self.p_master.input_var.get() != '' and self.p_master.input_var.get() not in self.values:
# datas = self.values # 2023年11月04日注释此行
# datas.append(self.p_master.input_var.get()) # 2023年11月04日新增此行
datas = [] # 2023年11月05日新增此行
else:
pass
for data in datas:
self.list_box.insert(END, data)
def is_show(self):
if self.top_window and self.top_window.state() == 'normal':
return True
else:
return False
class ComboBox(ttk.Entry):
"""ComboBox Class"""
def __init__(self, values, width, master, my_string, my_levels, entryvar=None, entrywidth=None, entrystyle=None, state='normal'):
self.master = master
self.values = values
self.my_string = my_string
self.my_levels = my_levels
# ########################
# if entryvar is not None:
# self.input_var = entryvar
# else:
# self.input_var = StringVar()
entry_config = {}
if entrywidth is not None:
entry_config["width"] = entrywidth
if entrystyle is not None:
entry_config["style"] = entrystyle
# ################################
self.frame = Frame(self.master)
self.frame.pack(fill=BOTH, expand=1)
self.input_var = StringVar()
# self.input_var.set(self.values[0]) # 测试
# self.entry = Entry(self.frame, textvariable=self.input_var, width=width)
self.entry = ttk.Entry(self.frame, textvariable=self.input_var, **entry_config,
state=state, width=width, bootstyle=SUCCESS)
self.entry.pack()
self.entry.bind('<KeyRelease>', self.on_update_list)
self.entry.bind('<ButtonRelease-1>', self.on_entry_click)
self.entry.bind('<Return>', self.on_enter)
self.input_var.set(my_string)
ListBox().init(width)
def on_enter(self, event):
if self.input_var.get() in self.values:
pass
# else:
# self.input_var.set(self.values[0])
# self.entry.icursor(len(self.input_var.get()))
def on_entry_click(self, event):
if ListBox().is_show():
ListBox().hide()
else:
ListBox().my_show(self, self.values, self.entry, self.my_levels)
def on_update_list(self, event):
# ##########################
global my_str
if self.my_levels == 0: # 第一个参数
my_str[0] = self.input_var.get()
elif self.my_levels == 1: # 第二个参数
my_str[1] = self.input_var.get()
elif self.my_levels == 2:
my_str[2] = self.input_var.get()
elif self.my_levels == 3:
my_str[3] = self.input_var.get()
elif self.my_levels == 4:
my_str[4] = self.input_var.get()
elif self.my_levels == 5:
my_str[5] = self.input_var.get()
# print(my_str)
if ListBox().is_show():
ListBox().update_list()
def return_str():
return my_str
def return_my_bool_hide():
return my_bool_hide
# print(ComboBox(ttk.Entry))