Python tkinter:如何创建一个具有列表框的自定义小部件,该列表框可以在另一个小部件上显示和消失,而无需移动另一个小部件?

Python tkinter:如何创建一个具有列表框的自定义小部件,该列表框可以在另一个小部件上显示和消失,而无需移动另一个小部件?,python,tkinter,listbox,Python,Tkinter,Listbox,我早些时候在“”上发布了一个问题。布莱恩·奥克利回答了我的问题,并提供了非常有用的解释和建议 目前,我正在研究上一个问题的下一个层次场景。也就是说,我想定制一个由标签和列表框组成的新小部件。当鼠标指针点击新的小部件时,它的列表框应该在周围的小部件前面出现和消失,并且周围小部件的位置不能改变。我试图应用我以前学到的知识,并修改我以前的代码以实现我的目标。我的代码如下所示 我遇到的问题是mythe自定义小部件的列表框仅出现在自定义小部件的框架内(绿色),即使我使用了.place布局管理器。布莱恩以前

我早些时候在“”上发布了一个问题。布莱恩·奥克利回答了我的问题,并提供了非常有用的解释和建议

目前,我正在研究上一个问题的下一个层次场景。也就是说,我想定制一个由标签和列表框组成的新小部件。当鼠标指针点击新的小部件时,它的列表框应该在周围的小部件前面出现和消失,并且周围小部件的位置不能改变。我试图应用我以前学到的知识,并修改我以前的代码以实现我的目标。我的代码如下所示

我遇到的问题是mythe自定义小部件的列表框仅出现在自定义小部件的框架内(绿色),即使我使用了
.place
布局管理器。布莱恩以前写过这个

place
不会影响同一父项的其他子项

在这种情况下,我应该如何重新构造代码和小部件,使自定义小部件中的列表框在出现时显示在自定义小部件的相邻小部件前面?在我的代码中,我希望在单击
self.newwidget
时,列表框出现在
class'App'
中定义的
self.label2
前面

#!/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()
#/usr/bin/python3
#-*-编码:utf-8-*-
尝试:
将tkinter作为tk#Python 3 tkinter模块导入
除恐怖外:
将Tkinter作为tk#Python 2 Tkinter模块导入
类NewWidget(tk.Frame):
定义初始值(自、父、磅值):
tk.Frame.\uuuuu init\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu,
帕迪=30)
#初始化局部变量
self.toggle=True
#创建NewWidget的小部件
self.label1=tk.Label(
self,text='单击我查看名人的姓名')
self.lbframe=tk.Frame(self,background='orange',borderwidth=10)
self.lbframe.list=tk.Listbox(self.lbframe,高度=5,宽度=10)
#将值放入列表框
对于lb_值中的项目:
self.lbframe.list.insert(tk.END,item)
#管理小部件布局
self.label1.pack(fill=“both”,expand=True)
self.lbframe.list.pack(fill=“both”,expand=True)
#设置控件绑定
self.label1.bind(“,self.ShowHideListbox)
def ShowHideListbox(自身、事件):
如果self.toggle:#显示
self.toggle=False
自我介绍(
在@event.widget中,x=0,rely=1,relwidth=1.0,anchor=“nw”)
其他:#隐藏
self.toggle=True
self.lbframe.place\u忘记()
类应用程序(tk.Frame):
定义初始化(自身,父级):
tk.Frame.\uuuu init\uuuuuu(自、父、背景='pink')
self.label1=tk.Label(self,text='Welcome!')
nlist=['Peter','Scotty','Walter','Scott','Mary']
self.newwidget=newwidget(self,nlist)
self.label2=tk.Label(self,高度=10,
text='名人世界!揭晓!'
self.label1.grid(行=0,列=0,sticky='nsew',pady=10)
self.newwidget.grid(行=1,列=0,sticky='nsew')
self.label2.grid(行=2,列=0,sticky='nsew')
self.label2.columnconfigure(2,权重=1)
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
root=tk.tk()
根几何(“300x300”)
app=app(根目录)
app.pack(fill=“两者”,expand=True)
app.mainloop()

要使列表框显示在相邻小部件的顶部,我必须做两件事:

1) 在
NewWidget
类中更改包含列表框的框架的主窗口小部件:

self.lbframe = tk.Frame(self, background='orange', borderwidth=10)
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')
变成

self.lbframe = tk.Frame(parent, background='orange', borderwidth=10)
因此,它与相邻的小部件具有相同的主部件

2) 在
App
类中的所有其他小部件之后创建
NewWidget
实例:

self.lbframe = tk.Frame(self, background='orange', borderwidth=10)
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')

要使列表框显示在相邻小部件的顶部,我必须做两件事:

1) 在
NewWidget
类中更改包含列表框的框架的主窗口小部件:

self.lbframe = tk.Frame(self, background='orange', borderwidth=10)
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')
变成

self.lbframe = tk.Frame(parent, background='orange', borderwidth=10)
因此,它与相邻的小部件具有相同的主部件

2) 在
App
类中的所有其他小部件之后创建
NewWidget
实例:

self.lbframe = tk.Frame(self, background='orange', borderwidth=10)
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')

杰出的它起作用了。你能解释第二步的逻辑吗?我认为这是因为最后创建的小部件比之前创建的小部件“更高”(如果它们重叠)。我第一次想到使用
self.newwidget
上的
lift
方法,将它放在所有邻居面前,但不知怎的,它阻止了我点击标签来显示列表框。所以我试着最后一次创造它,它成功了。太棒了!它起作用了。你能解释第二步的逻辑吗?我认为这是因为最后创建的小部件比之前创建的小部件“更高”(如果它们重叠)。我第一次想到使用
self.newwidget
上的
lift
方法,将它放在所有邻居面前,但不知怎的,它阻止了我点击标签来显示列表框。所以我试着在最后创建它,它成功了。