Ранее у меня был вопрос «how to create a listbox that can appear and disappear over another widget without moving the other widget?». Брайан Оукли ответил на мой вопрос и дал очень полезные объяснения и указатели.tkinter: Как создать пользовательский виджет, имеющий список, который может появляться и исчезать над другим виджетами без перемещения другого виджета?
В настоящее время я рассматриваю сценарий следующего уровня для моего предыдущего вопроса. То есть, я хочу настроить новый виджет, состоящий из метки и списка. Он должен появиться и исчезнуть перед окружающими виджетами, когда новый виджет щелкнул указателем мыши, а положение окружающего виджета не должно меняться. Я попытался применить то, что я узнал ранее, и изменил свой предыдущий код, чтобы попытаться достичь моей цели. Мой код показан ниже.
Проблема, с которой я столкнулся, - это список из моего пользовательского виджета, который отображается только в кадре пользовательского виджета (зеленый), хотя я использовал диспетчер компоновки .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()
Отлично! Оно работает. Можете ли вы объяснить логику для второго шага? –
Я думаю, это потому, что виджет, созданный последним, «выше», чем тот, который был создан ранее (если они перекрываются). Сначала я подумал использовать метод 'lift' на' self.newwidget', чтобы поставить его перед всеми его соседями, но почему-то это мешало мне щелкнуть по метке, чтобы отобразить список. Поэтому вместо этого я попытался создать его последним, и это сработало. –