Уведомления

Группа в Telegram: @pythonsu

#1 Апрель 1, 2013 13:39:03

vanvanov
Зарегистрирован: 2013-03-31
Сообщения: 252
Репутация: +  4  -
Профиль   Отправить e-mail  

Скрыть окно Tkinter

Использую messagebox, который, помимо диалога, создает пустое окно root . Для скрытия этого окна на форумах предлагается использовать root.withdraw(), но после этого я не всегда могу снова использовать окна Tkinter, потому что он ждет, пока я закрою скрытое окно root. Если же не скрывать пустые окна, они плодятся . Могу ли я как-нибудь по-другому избавиться от этого окна или полностью закрыть все окна Tkinter перед его повторным использованием?

Офлайн

#2 Апрель 1, 2013 20:38:55

Griffon
От: Ukrain, Zaporozhie
Зарегистрирован: 2009-03-04
Сообщения: 324
Репутация: +  11  -
Профиль   Отправить e-mail  

Скрыть окно Tkinter

Возможно вы не хотите закрывать главное окно и потом заново его создавать. Возможно вы просто хотите скрывать и вновь отображать одно и то же главное окно, а что на нем отображается можно менять как вам угодно.
Если же вы действительно хотите то о чем просите, то вам просто необходимо использовать метод destroy экземпляра Tk (root в вашем случае). Но мне кажется что вы ставите задачу не совсем правильно.



Офлайн

#3 Апрель 2, 2013 00:11:09

4kpt
От: Харьков
Зарегистрирован: 2010-11-03
Сообщения: 998
Репутация: +  63  -
Профиль   Отправить e-mail  

Скрыть окно Tkinter

Griffon Вы абсолютно правы. Вопрос поставлен неккоректно.
Вопрос должен быть следующим:
“Каким образом удалить корневое окно, вывод которого скрыт методом .withdraw()?”
В результате имеет то, что окна размножаются при каждом вызове и естественно, обращение к ним блокируется.
Ну так удаляйте их. Кто за Вас это будет делать? Пример кода:

import Tkinter
import tkMessageBox
root = Tkinter.Tk()
root.withdraw()
mes = tkMessageBox.askyesno(message = "first question")
print mes
root.destroy()
root = Tkinter.Tk()
root.withdraw()
mes2 = tkMessageBox.askyesno(message = "second question")
print mes2
root.destroy()
root.mainloop()

P.S. Подход, построенный на удалении корневых окон изначально ущербен. Легче удалять не окна (а потом их заново создавать), а рамки в которые покуются все виджеты данного сеанса или страницы программы (как Вам будет удобно). Таким образом, корневое окно не будет мучаться, а виджеты будут скрываться. Кстати, есть еще альтернативный механизм - метод _forget() который скрывает рассположение рамки с упакованными виджетами. Если снова понадобиться, можно заново ее разместить :)

P.S.S. Надеюсь это оно…



Отредактировано 4kpt (Апрель 2, 2013 01:09:16)

Офлайн

#4 Апрель 2, 2013 00:59:50

vanvanov
Зарегистрирован: 2013-03-31
Сообщения: 252
Репутация: +  4  -
Профиль   Отправить e-mail  

Скрыть окно Tkinter

4kpt
Ну так удаляйте их. Кто за Вас это будет делать?
Дело в следующем. У меня есть следующий код.
def ok_cancel(message):
	root=Tk()
	# Иначе будет показываться лишнее пустое окно
	root.withdraw()
	if messagebox.askokcancel('Подтвердите:',message):
		return True
	else:
		return False
	root.mainloop()
	root.destroy()
# Вернуть отредактированный текст 
def text_field_edit(title,array):
	root, res = Tk(), [None]
	def callback(): res[0] = txt.get(1.0,END); root.destroy()
	root.title(title)
	scrollbar = Scrollbar(root,jump=0)
	txt = Text(root,font="14",wrap=WORD,yscrollcommand=scrollbar.set)
	txt.insert(END,array)
	# Позволяет использовать мышь для управления скроллбаром
	scrollbar.config(command=txt.yview)
	scrollbar.pack(side=RIGHT,fill=Y)
	txt.pack()
	# Выход по клику кнопки
	ok = Button(root, text='Запомнить и выйти',command=callback)
	ok.pack()
	# Выход по нажатию Enter и Пробел на кнопке (навигация по Shift+Tab)
	ok.bind('<Return>', lambda e:callback())
	txt.focus_set()
	root.mainloop()
	if str(res[0])=='None' or str(res[0])==default_line_break:
		my_error(empty_field_error_msg)
	return res[0]
Я попеременно выполняю то ok_cancel, то text_field_edit. ok_cancel завершается нормально, но после text_field_edit остается пустое окно (в случае root.iconify()), а в случае withdraw скрипт перестает что-то делать. Где ошибка, я же делаю root.destroy() в text_field_edit тоже?

Отредактировано vanvanov (Апрель 2, 2013 01:04:14)

Офлайн

#5 Апрель 2, 2013 01:10:28

4kpt
От: Харьков
Зарегистрирован: 2010-11-03
Сообщения: 998
Репутация: +  63  -
Профиль   Отправить e-mail  

Скрыть окно Tkinter

Ответьте на один вопрос.
Зачем нужна эта строчка?

root.mainloop()



Офлайн

#6 Апрель 2, 2013 01:40:02

vanvanov
Зарегистрирован: 2013-03-31
Сообщения: 252
Репутация: +  4  -
Профиль   Отправить e-mail  

Скрыть окно Tkinter

4kpt
Ответьте на один вопрос.Зачем нужна эта строчка?
Показывает окно?

Офлайн

#7 Апрель 2, 2013 02:03:23

4kpt
От: Харьков
Зарегистрирован: 2010-11-03
Сообщения: 998
Репутация: +  63  -
Профиль   Отправить e-mail  

Скрыть окно Tkinter

Неверно…
Разберитесь…
По Вашему коду. Поменяйте местами эти две строки:

root.mainloop()
root.destroy()

P.S. Я настоятельно не рекомендую использовать инструкцию from tkinter import*



Отредактировано 4kpt (Апрель 2, 2013 02:07:31)

Офлайн

#8 Апрель 2, 2013 03:25:19

vanvanov
Зарегистрирован: 2013-03-31
Сообщения: 252
Репутация: +  4  -
Профиль   Отправить e-mail  

Скрыть окно Tkinter

4kpt
Неверно…Разберитесь…По Вашему коду. Поменяйте местами эти две строки:
Поменял. Осталось как раньше - окна messagebox нормально убиваются, а после text_field_edit остается пустое root-окно, хотя если использовать только text_field_edit, все завершается нормально. Куда в этой функции (text_field_edit) я могу поместить mainloop? Если до кнопок - кнопки не отображаются, если последней строкой - скрипт не сможет вернуть тот текст, который пользователь вводит в окно. Вырубаю в терминале
File "/usr/local/bin/main.py", line 785, in text_field_edit
root.mainloop()
File "/usr/lib/python3.1/tkinter/__init__.py", line 1012, in mainloop
self.tk.mainloop(n)
KeyboardInterrupt
Похоже да, какие-то проблемы именно с mainloop. Но где тогда он должен стоять? Разве где-то в другом месте?

Отвечая на ваш вопрос, mainloop - метод, запускающий цикл обработки событий.

Отредактировано vanvanov (Апрель 2, 2013 03:26:15)

Офлайн

#9 Апрель 2, 2013 09:39:30

Griffon
От: Ukrain, Zaporozhie
Зарегистрирован: 2009-03-04
Сообщения: 324
Репутация: +  11  -
Профиль   Отправить e-mail  

Скрыть окно Tkinter

Подумайте об архитектуре вашего приложения.
Нет смысла десять раз создавать обьект Tk.

Разберитесь вот с этим:

# -*- coding: UTF-8 -*-
from Tkinter import *
import tkMessageBox as messagebox
from tkFont import Font
root = Tk()
root.withdraw()
yesno = messagebox.askokcancel("OMG", "Не нажмайте ОК!")
my_frame = Frame(root)
my_frame.pack()
my_label = Label(my_frame, text="Мы используем все то же главное окно!")
my_label.pack()
root.update_idletasks()
root.deiconify()
yesno = messagebox.askokcancel("OMG", "Удалить окно?")
root.withdraw()
my_frame.forget()
yesno = messagebox.askokcancel("OMG", "Новое окно?")
my_label.configure(text="Все тоже главное окно, тот же фрейм, та же надпись.")
my_frame.pack()
root.update_idletasks()
root.deiconify()
yesno = messagebox.askokcancel("OMG", "Может всетаки новое окно?")
my_frame.destroy()
my_frame = Frame(root)
my_frame.pack()
font = Font(family="Helvetica", size=16)
text = Text(my_frame, font=font)
text.pack()
text.insert(END, "Все новое - хорошо забытое старое.\n")
text.insert(END, "В нашем случае, это не пустые слова.")
Button(my_frame, text="Выход", command=root.destroy).pack()
root.mainloop()



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version