我之前发过一个关于“how to create a listbox that can appear and disappear over another widget without moving the other widget?”的问题。布莱恩奥克利回答了我的问题并提供了非常有用的解释和指示。
目前,我正在研究上一个问题的下一个级别方案。也就是说,我想自定义一个由标签和列表框组成的新窗口小部件。当鼠标指针单击新窗口小部件并且周围窗口小部件的位置不得更改时,它的列表框应该出现并消失在周围窗口小部件的前面。我试图应用我之前学到的东西,并修改了我之前的代码,试图实现我的目标。我的代码如下所示。
我遇到的问题是我的自定义窗口小部件的列表框只出现在自定义窗口小部件的框架内(绿色),即使我使用了.place
布局管理器。布莱恩以前写过这个
place
不会影响同一父母的其他孩子。
在这种情况下,我应该如何重构我的代码和窗口小部件,以便自定义窗口小部件中的列表框出现时会出现在自定义窗口小部件的相邻窗口小部件前面?在我的代码中,当单击self.label2
时,我希望列表框显示在class 'App'
中定义的self.newwidget
前面。
#!/usr/bin/python3
# -*- coding: utf-8 -*-
try:
import tkinter as tk # Python 3 tkinter modules
except ImportError:
import Tkinter as tk # Python 2 tkinter modules
class NewWidget(tk.Frame):
def __init__(self, parent, lb_values):
tk.Frame.__init__(self, parent, background='green', borderwidth=10,
pady=30)
# Initialise local variable
self.toggle = True
# Create widgets of NewWidget
self.label1 = tk.Label(
self, text='Click me to see Names of Famous Folks')
self.lbframe = tk.Frame(self, background='orange', borderwidth=10)
self.lbframe.list= tk.Listbox(self.lbframe, height=5, width=10)
# Put values into listbox
for item in lb_values:
self.lbframe.list.insert(tk.END, item)
# Manage widgets layout
self.label1.pack(fill="both", expand=True)
self.lbframe.list.pack(fill="both", expand=True)
# Set widget bindding
self.label1.bind("<Button-1>", self.ShowHideListbox)
def ShowHideListbox(self, event):
if self.toggle: # Show
self.toggle=False
self.lbframe.place(
in_=event.widget, x=0, rely=1, relwidth=1.0, anchor="nw")
else: # Hide
self.toggle=True
self.lbframe.place_forget()
class App(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent, background='pink')
self.label1 = tk.Label(self, text='Welcome!')
nlist = ['Peter', 'Scotty', 'Walter', 'Scott', 'Mary']
self.newwidget = NewWidget(self, nlist)
self.label2 = tk.Label(self, height=10,
text='The World of Famous Folks! Revealed!',)
self.label1.grid(row=0, column=0, sticky='nsew', pady=10)
self.newwidget.grid(row=1, column=0, sticky='nsew')
self.label2.grid(row=2, column=0, sticky='nsew')
self.label2.columnconfigure(2, weight=1)
if __name__ == '__main__':
root = tk.Tk()
root.geometry("300x300")
app = App(root)
app.pack(fill="both", expand=True)
app.mainloop()
答案 0 :(得分:2)
要使列表框显示在相邻小部件的顶部,我必须做两件事:
1)更改NewWidget
类中包含列表框的框架的主窗口小部件:
self.lbframe = tk.Frame(self, background='orange', borderwidth=10)
变为
self.lbframe = tk.Frame(parent, background='orange', borderwidth=10)
使它与相邻的小部件具有相同的主控。
2)在NewWidget
类中的所有其他小部件之后创建App
实例:
class App(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent, background='pink')
self.rowconfigure(1, weight=1)
self.label1 = tk.Label(self, text='Welcome!')
nlist = ['Peter', 'Scotty', 'Walter', 'Scott', 'Mary']
# self.newwidget = NewWidget(self, nlist) # former position
self.label2 = tk.Label(self, height=10,
text='The World of Famous Folks! Revealed!',)
self.label1.grid(row=0, column=0, sticky='nsew', pady=10)
self.label2.grid(row=2, column=0, sticky='nsew')
self.label2.columnconfigure(2, weight=1)
self.newwidget = NewWidget(self, nlist)
self.newwidget.grid(row=1, column=0, sticky='nsew')