2017-01-25 1 views
0

Ранее у меня был вопрос «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() 

ответ

2

Чтобы сделать ListBox появится в верхней части соседних виджетов я должен был сделать две вещи:

1) Изменение главного виджета фрейма, содержащего ListBox в NewWidget классе:

self.lbframe = tk.Frame(self, background='orange', borderwidth=10) 

становится

self.lbframe = tk.Frame(parent, background='orange', borderwidth=10) 

так, что он имеет тот же мастер, как neighborin g.

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') 
+0

Отлично! Оно работает. Можете ли вы объяснить логику для второго шага? –

+0

Я думаю, это потому, что виджет, созданный последним, «выше», чем тот, который был создан ранее (если они перекрываются). Сначала я подумал использовать метод 'lift' на' self.newwidget', чтобы поставить его перед всеми его соседями, но почему-то это мешало мне щелкнуть по метке, чтобы отобразить список. Поэтому вместо этого я попытался создать его последним, и это сработало. –

Смежные вопросы