LINUX.ORG.RU

Спрятать окно tkinter

 


0

1

Проблема следующая. Пользуюсь модулем messagebox, который, помимо окна диалога, создает пустое окно root. Чтобы спрятать это окно, на форумах советуют использовать root.withdraw(). Однако мой скрипт создает много разнообразных окон tkinter, и после того, как я что-нибудь нажал в диалоге messagebox, tkinter не может создать новое окно (терминал просто висит) - видимо, ждет, когда я закрою пустое окно root (оно, напомню, спрятано, т.е. мне остается только Ctrl+C). root_destroy() в конце таких процедур как ниже не помогает. Если же withdraw убрать, tkinter начинает плодить сущности: 1, 2 - некрасиво. Как можно решить этот вопрос?

from tkinter import *
from tkinter import filedialog
from tkinter import messagebox
# Диалог "Вы уверены?..."
def ok_cancel(message):
        root=Tk()
        # Иначе будет показываться лишнее пустое окно
        #root.withdraw()
        if messagebox.askokcancel('Подтвердите:',message):
                return True;
        else:
                return False
        #root.destroy()

Deleted

Никак. В Tk обязательно есть root-окно. Цикл wm (основной цикл для Windows Manager'a Tk) обязательно должен содержать рутовое окно (иначе просто не к чему привязать цикл). Ну, и для Tk использование диалоговых окон вне цикла - просто не возможно. Дело в том, что исходя из архитектуры Tk, элемент message box - это просто дочернее окно (следовательно, оно должно быть привязано к root'овому), у которого заранее заданы определенные параметры.

Я такую проблему обходил просто - сделал класс, который описывал нужный мне диалог и создавал/убивал окно по мере надобности (каждый раз это было просто заново создаваемое root'овое окно). Для Tk это более правильный подход, нежели скрывать корневое окно, а потом плодить мессадж-боксы.

silver-bullet-bfg ★★
()
Ответ на: комментарий от silver-bullet-bfg

Пример класса можете привести?

Deleted
()
Ответ на: комментарий от silver-bullet-bfg

Для Tk это более правильный подход, нежели скрывать корневое окно, а потом плодить мессадж-боксы.

Т.е. предлагаете написать свой messagebox?

Deleted
()

не знаю как оно на питоне, но в tcl так:


wm withdraw .

Bad_ptr ★★★★★
()

терминал просто висит

exit же

Bad_ptr ★★★★★
()
Ответ на: комментарий от silver-bullet-bfg

А смысл? Для маленьких скриптов - tk самое оно.

Gtk в любом линуксе есть всегда. А вот tk не всегда.
В виндовс Gtk (без туфты) занимает 14Мб в распакованном виде. В архиве того меньше. Сколько tk в винде занимает - не знаю.

А смысл в том, что Gtk выглядит поприятнее, более популярно и лучше документировано. Еще в том, что описанной проблемы можно избежать без выкрутасов.

Ни в коем случае не уговариваю. Решать топикстартеру.

Novator ★★★★★
()
Ответ на: комментарий от Novator

Согласен, что GTK-диалоги приятнее, но очень обломно изучать Tkinter ради простого скрипта, и в итоге из-за маленькой проблемы разучивать что-то другое.

Deleted
()
Ответ на: комментарий от Deleted

Ну да, что тут сложного? Сделаете за 3 минуты. Python очень плохо помню, но что-то вроде:

class WmDialog
        def __init__(self):   
                self.root=Tk()
                self.bntOk=ttk.Button (root, text="Hello, world", ).grid()
        def cmdOk(self):
                return "ok"
        def liveWnd (self,isLive): 
                self.root.mainloop()
        def deadWnd (self):
                self.root.destroy()

silver-bullet-bfg ★★
()
Ответ на: комментарий от Deleted

Tkinter гвидоугоден зато ^_^. На нем можно не только для скриптов гуй рисовать.

silver-bullet-bfg ★★
()
Ответ на: комментарий от silver-bullet-bfg

Я Питон недавно начал изучать. Можете объяснить, как применить этот класс, чтобы не было пустых окон?

Deleted
()
Ответ на: комментарий от Novator

А есть какой-нибудь простой конструктор типа zenity, вместо того, чтобы кучу непонятных функций писать?

Deleted
()
Ответ на: комментарий от Deleted

Там все просто, вот смотри какая идея:

from Tkinter import *

class WmDialog:
        def __init__(self):
                self.root=Tk()
                self.bntOk=Button (self.root, text="Kill Dialog",command=self.root.destroy).grid()
		self.bntCancel=Button (self.root, text="Exit from Script", command=exit).grid()        
        def liveWnd (self): 
                self.root.mainloop()
	

dlg=WmDialog()
dlg.liveWnd()

print "I am destroy 1-st window"

dlg=WmDialog()
dlg.liveWnd()

print "I am destroy 2-st window"
print "Exit"
Что тут происходит: ты создаешь класс с именем WmDialog (как раз аналог диалог-бокса, я его настраивать не стал - сам сделаешь, тут не сложно), который позволяет либо продолжить выполнение скрипта дальше (если нажмешь bntOk), либо вырубит скрипт (если нажмешь btnCancel). Когда ты нажимаешь bntOk вызывается метод destroy для окна dlg.root, которое и является корневым для цикла Tk(). После вывода первой надписи («I am destroy 1-st window»), мы снова создаем объект-окно. Ну и так далее :). Дальше сам придумаешь, я думаю.

silver-bullet-bfg ★★
()
Ответ на: комментарий от silver-bullet-bfg

Какими местом для опроса диалога Вы хотите присобачить класс О_О?

from Tkinter import *
from tkMessageBox import *


def dialog(f, *L, **D):
    root=Tk(); root.withdraw()
    try: return f(*L, **D)
    finally: root.destroy()

print dialog( askokcancel, '111', '222')
print dialog( askokcancel, '333', '444')

dialog подходит для вызова любого dialog-а. Для питона3 ТС думаю сможет адаптировать сам.

ЗЫ: ТС destroy вызывал ПОСЛЕ return, ясно что рут не закрывался;-) Ну и конструкции вида

if True: return True
else: return False
доставляют;-)

AIv ★★★★★
()
Ответ на: комментарий от Novator

В винде Tk будет ставится вместе в Python (а вот Gtk придется отдельно доставлять), да и лучше документации чем по Tk в принципе не видел. Просто надо смотреть не только Tkinter доки, но и Tk чистого доки.

silver-bullet-bfg ★★
()
Ответ на: комментарий от silver-bullet-bfg

И даже если делать диалог ручками - накой там класс то? По дизайну это ф-я, вызвал - она все нарисовала - висит ждет решения юзера - закрылась и вернула результат. Классы тут актуальны либо когда есть несколько вызовов для работы с одними и теми же данными, либо когда нужно сделать какой то полуфабрикат (сложный виджет) для повторного испольщования.

AIv ★★★★★
()
Ответ на: комментарий от AIv

Вот и хочу на ФП перейти, только пока не получается. А вы случайно не подскажите, какой ФП язык наиболее хорошо работает с гуйней? Сейчас как раз пишу «домашний» проект на C#+Gtk, но честно - уже воротит от этой дряни (C#/ООП).

silver-bullet-bfg ★★
()
Ответ на: комментарий от AIv

Ну по привычке я бы загнал вообще весь скрипт в объект, сделал бы не только диалоги как классы, но и саму программу как класс, который работает с объектами других классов..

silver-bullet-bfg ★★
()
Ответ на: комментарий от silver-bullet-bfg

Ну я пишу на питоне, ФП там есть, и в гуйне оно вполне актуально

AIv ★★★★★
()
Ответ на: комментарий от AIv

Ну и конструкции вида

if True: return True
else: return False

доставляют;-)

В Python AFAIK все NoneType, если не инициализировать, поэтому пишу.

Deleted
()
Ответ на: комментарий от AIv

def ok_cancel(message): root=Tk() # Иначе будет показываться лишнее пустое окно #root.withdraw() if messagebox.askokcancel('Подтвердите:',message): return True; else: return False #root.destroy() Где вы увидели if true: true?

Deleted
()
Ответ на: комментарий от Deleted

messagebox.askokcancel('Подтвердите:',message) возвращает True или False. На крайняк можно привести к bool. А так Ваш код эквивалентен тому что я выше написал, с if True:...

В Python AFAIK все NoneType, если не инициализировать,

Нет, это не так.

AIv ★★★★★
()
Ответ на: комментарий от Deleted

Если я правильно понял задачу:

#!/usr/bin/env python

import gtk

md = gtk.MessageDialog(None, gtk.DIALOG_DESTROY_WITH_PARENT,
  gtk.MESSAGE_WARNING, gtk.BUTTONS_OK_CANCEL, "Message")
md.set_title('Title')
if md.run() == gtk.RESPONSE_OK:
  res = True
md.destroy()

Novator ★★★★★
()
Последнее исправление: Novator (всего исправлений: 2)
Ответ на: комментарий от AIv

Понимаю, я просто создал еще одну процедуру, куда впихнул root.withdraw() и root.destroy(), думал, что это поможет...

Deleted
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.