2013-07-07 2 views
1

У меня в основном такой же вопрос, но я не чувствую, что было отвечено правильно:разрушающих динамически созданный виджет

Tkinter: How can I dynamically create a widget that can then be destroyed or removed?

accepted answer является:

Вы хотите хранить динамически созданные виджеты в списке. Есть что-то вроде

 dynamic_buttons = [] 

    def onDoubleClick(event): 
    ... 
    button = Button(...) 
    dynamic_buttons.append(button) 
    button.pack() 

You can then access the buttons for removal with, say, 

    dynamic_buttons[0].destroy() 

Вы можете увидеть, что ссылка они говорят не изменяется, при этом число 0 используется. Но когда вы динамически создаете виджеты, как вы связываете эти ссылки с кнопками?

Скажите, что вы создаете виджет Toplevel (отображает содержимое файла) и хотите иметь кнопку, чтобы закрыть виджет. Динамическое создание позволит открыть несколько файлов. Проблема в том, что даже с этим списком, как кнопка «знает», к какому виджетам она принадлежит, поскольку нет жесткой ссылки (отлично, что у вас есть список элементов, но кнопка 5 уровня 5 не имеет понятия, они 5 в списке). Всегда будет только одна «активная» версия кнопки и верхнего уровня, и эту можно удалить.

aanstuur_files = [] 
aanstuur_frames = [] 
aanstuur_buttons = [] 

def editAanstuur(): 
    openfiles = filedialog.askopenfilenames() 
    if not openfiles: 
     return 
    for file in openfiles: 
     newtop = Toplevel(nGui, height=100, width=100) 
     labelTitle = Label(newtop, text=file).pack() 
     newButton = Button(newtop, text="save & close", command= ...).pack() 
     aanstuur_files.append(file) 
     aanstuur_buttons.append(newButton) 
     aanstuur_frames.append(newtop) 

ответ

1

Как знать, какая кнопка окна она принадлежит? Вы говорите это:

newButton = Button(newtop, command=lambda top=newtop: top.destroy()) 

Кстати, вы присваиваете None к newButton в вашем коде. Это потому, что вы делаете newbutton = Button(...).pack(), что означает, что newbutton получает значение pack(), которое всегда равно None.

Если вы хотите сохранить ссылку на виджет, вы должны создать виджет на отдельном шаге с того места, где вы поместите его в окно.

Еще лучше использовать преимущества классов и объектов. Создайте свой собственный подкласс Toplevel, и экземпляр будет отслеживать все подвижки для вас. Например:

class MyToplevel(Toplevel): 
    def __init__(self, parent, filename, *args, **kwargs): 
     Toplevel.__init__(self, parent, *args, **kwargs) 
     self.filename = filename 
     self.savebutton = Button(..., command=self.save) 
     ... 
    def save(self): 
     print "saving...", self.filename 
     ... 
     self.destroy() 
... 
openfiles = filedialog.askopenfilenames() 
if not openfiles: 
    return 
for file in openfiles: 
    newtop = MyToplevel(nGui, file, height=100, width=100) 
+0

Ах да, я знаю об этой проблеме .pack(). Дело в том, что я хочу сохранить файл, который является дочерним элементом этого верхнего виджета перед закрытием, как получить доступ к содержимому этого текстового поля и записать его в файл? – PascalVKooten

+0

Получил это, давая дополнительные аргументы. Большое спасибо. – PascalVKooten

+0

@Dualinity: еще лучшее решение, чем держать нагромождение аргументов, - это создать свой собственный класс. Я обновил свой ответ, чтобы дать представление о том, как вы можете это сделать. –

0

APass в индексе к вашей функции команд с помощью enumerate() function:

def editAanstuur(): 
    openfiles = filedialog.askopenfilenames() 
    if not openfiles: 
     return 
    for i, file in enumerate(openfiles): 
     newtop = Toplevel(nGui, height=100, width=100) 
     labelTitle = Label(newtop, text=file).pack() 
     newButton = Button(newtop, text="Save", command=lambda index=i: print(index)).pack() 
     aanstuur_files.append(file) 
     aanstuur_buttons.append(newButton) 
     aanstuur_frames.append(newtop) 

Убедитесь, что вы передаете индекс в качестве ключевого слова параметра, чтобы связать значение при определении лямбды (замыкание будет использовать последнее значение i).

enumerate() принимает второй аргумент, индекс начать с, который по умолчанию в 0.

+0

Когда функция 'editAanstuur()' будет использоваться снова, как она сможет продолжить, где она остановилась? (после того, как было открыто несколько файлов, еще больше будет открыто) Или индекс отправлен таким образом, как жесткая ссылка? – PascalVKooten

+0

@Dualinity: вы можете передать начальный индекс в 'enumerate()'. Он будет начинаться с 0 по умолчанию. –

+0

Я пропустил что-то с помощью 'command'? Будет ли lambda: saveButton (i) 'вызвать функцию saveButton с правильным, жестко связанным,' i'? Здесь он показывает что-то среднее между 'lambda' и': ' – PascalVKooten

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