Как скрыть окно tkinter в python
Перейти к содержимому

Как скрыть окно tkinter в python

  • автор:

Скрыть окно консоли с помощью Tkinter и cx_Freeze

Я использую cx_freeze для замораживания приложения tkinter. Когда я запускаю exe, я получаю замечательное окно консоли USELESS вместе с моим GUI tkinter.

Я хотел бы удалить/скрыть это бесполезное черное окно.

Я видел потоки, которые предлагают следующее:

root = tkinter.Tk() root.withdraw() 

Вышеуказанный код делает обратное тому, что я хочу. Он скрывает мой GUI, в то время как бесполезное черное окно остается. Я хотел бы, чтобы это было наоборот.

Поделиться Источник 02 апреля 2011 в 14:55

7 ответов

Я помню, как читал где-то, что в Windows, если вы укажете расширение вашего файла как .pyw , оно запустится с помощью pythonw.exe (без окна консоли). Работает ли это для вас?

Поделиться 02 апреля 2011 в 15:04

Этот вопрос очень похож, но для wxPython и cx_Freeze. К счастью, оказывается, что внешний вид консоли можно настроить из скрипта сборки, а не из исходного кода. Заимствуя два лучших ответа, трюк заключается в установке переменной base в вашем скрипте сборки cx_Freeze:

import sys from cx_Freeze import setup, Executable base = None if (sys.platform == "win32"): base = "Win32GUI" # Tells the build script to hide the console. #

Вот соответствующая документация (хотя она явно не упоминает, что base контролирует опцию консоли).

Также, просто потому, что это интересно, ответ на другой вопрос решает проблему создания приложения GUI с опцией режима консоли или без нее, что, как я думал, было очень круто.

Поделиться 07 июля 2012 в 11:17

Сделайте точно так же, как сказал Гэри, тогда:

setup(name="ur package name", version="ur package version", description="as above", executables=[Executable("ur_script.py", base=base)] 

Это будет работать с cx_Freeze

Поделиться 11 декабря 2012 в 06:57

Для меня использование опции —base-name Win32GUI работает. Вот пример:

cxfreeze your_python_file.py —base-name Win32GUI —target-dir your_target_dir

Поделиться 11 марта 2015 в 07:52

Если вы используете pyinstaller, используйте pyinstaller-gui.py В командной строке Windows введите

Сначала будет сказано «Пожалуйста, используйте просто ‘pyinstaller.py’. Gui не поддерживается». Измените код немного и вы сможете запустить это.

Он покажет всплывающее окно для выбора вашего скрипта и некоторые флажки. Проверьте, нет консоли (только для окон)

Вот и все. Вы готовы!

Другой вариант: использовать опцию —noconsole при сборке. т.е.:

python pyinstaller.py —noconsole yourscript.py

Поделиться 13 июня 2013 в 16:35

Сегодня у меня была та же проблема

Что я использовал для компиляции своих программ на Python, это py2exe, и решением было очень просто изменить файл установки, как показано ниже. Мой интерфейс написан с помощью Tkinter

измените скрипт «setup.py» py2exe на:

Старый код Python:

from distutils.core import setup import py2exe setup(console=['app.py']) 

Новый код Python:

from distutils.core import setup import py2exe setup(windows=['app.py']) 

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

Поделиться 14 ноября 2011 в 18:11

Я предполагаю, что с помощью «черного окна» вы обращаетесь к окну терминала. Чтобы отключить это от всплывающего окна, сохраните ваш файл как расширение.pyw вместо.py

Как скрыть окно tkinter в python

На этом шаге мы рассмотрим процесс создания таких окон .

Модальное вторичное окно , в отличие от обычного, при открытии блокирует все остальные окна приложения, в результате чего пользователь теряет доступ к ним. Остальные окна становятся доступными только после закрытия модального окна. Такие окна обычно применяются в качестве диалоговых окон для запроса каких-либо данных, необходимых для дальнейшей работы приложения.

К сожалению, библиотека Tkinter не предоставляет никаких инструментов для вывода модальных окон. Однако мы можем превратить обычное вторичное окно в модальное, вызвав у его контейнера или у него самого метод grab_set() (см. 11 шаг). Этот метод задает для контейнера или окна режим перехвата событий, в результате чего остальные окна перестают реагировать на действия пользователя. Как только окно, для которого был установлен перехват событий, закрывается и удаляется из памяти, перехват событий перестает работать, и остальные окна приложения становятся доступными для пользователя.

Есть еще один неприятный момент, связанный с реализацией модальных окон. Если после запуска приложения и вывода модального вторичного окна мы посмотрим на панель задач Windows , то увидим, что там присутствуют оба окна: и главное, и вторичное. Но присутствие модального окна на панели задач говорит о плохом стиле программирования. Чтобы скрыть вторичное окно, следует вызвать у него метод transient() (см. 21 шаг), передав ему ссылку на главное окно. Этот метод, в частности, отменит представление вторичного окна на панели задач.

Вот фрагмент кода контейнера, который превратит окно, в котором выведен, в модальное:

class Secondary(tkinter.ttk.Frame): def __init__(self, master=None): . . . . . self.master.transient(parent) self.grab_set()

В качестве примера давайте модифицируем приложение из предыдущего шага таким образом, чтобы выводимое им вторичное окно стало модальным. Текст ниже показывает исправленный код класса контейнера вторичного окна.

import tkinter import tkinter.ttk # Объявляем класс контейнера для вторичного окна class Secondary(tkinter.ttk.Frame): # Конструктор этого класса поддерживает дополнительный параметр # parent, с которым передается ссылка на главное окно. Она # понадобится нам, чтобы вывести занесенное значение в главном окне def __init__(self, master=None, parent=None): super().__init__(master) # Сохраним ссылку на главное окно в атрибуте self.parent = parent self.pack() self.create_widgets() self.master.title("Вторичное окно") self.master.transient(parent) self.grab_set() def create_widgets(self): self.varValue = tkinter.StringVar() self.varValue.set("Значение") entValue = tkinter.ttk.Entry(self, textvariable=self.varValue) entValue.pack() btnOK = tkinter.ttk.Button(self, text="OK", command=self.ok) btnOK.pack(side="left") btnCancel = tkinter.ttk.Button(self, text="Отмена", command=self.master.destroy) btnCancel.pack(side="right") def ok(self): self.parent.lblValue["text"] = self.varValue.get() self.master.destroy() def show_value(self): self.parent.lblValue["text"] = self.varValue.get() class Application(tkinter.ttk.Frame): def __init__(self, master=None): super().__init__(master) self.pack() self.create_widgets() self.master.title("Модальное вторичное окно") self.master.resizable(False, False) def create_widgets(self): btnShowWindow = tkinter.ttk.Button(self, text="Вывести окно", command=self.show_window) btnShowWindow.pack() # Опция width компонента Label задает ширину надписи # в символах текста self.lblValue = tkinter.ttk.Label(self, text="", width=50) self.lblValue.pack() def show_window(self): # Выводим вторичное окно, не забыв указать в параметре parent # конструктора ссыпку на главное окно Secondary(master=tkinter.Toplevel(), parent=self) root = tkinter.Tk() app = Application(master=root) root.mainloop()

Архив с файлом можно взять здесь.

Результат работы приложения приведен на рисунке 1.

Рис.1. Результат работы приложения

На следующем шаге мы рассмотрим управление жизненным циклом приложения .

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

Проблема следующая. Пользуюсь модулем 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
01.04.13 06:05:21 MSK

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

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

silver-bullet-bfg ★★
( 01.04.13 08:05:07 MSK )

Второй путь: забить на Tk и юзать Gtk 🙂

Novator ★★★★★
( 01.04.13 10:34:18 MSK )
Ответ на: комментарий от Novator 01.04.13 10:34:18 MSK

А смысл? Для маленьких скриптов — tk самое оно. Тем более, что Tkinter — гвидоугодный.

silver-bullet-bfg ★★
( 01.04.13 13:03:24 MSK )
Ответ на: комментарий от silver-bullet-bfg 01.04.13 08:05:07 MSK

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

Deleted
( 01.04.13 13:28:31 MSK )
Ответ на: комментарий от silver-bullet-bfg 01.04.13 08:05:07 MSK

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

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

Deleted
( 01.04.13 13:30:22 MSK )

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

wm withdraw .
Bad_ptr ★★★★★
( 01.04.13 13:32:36 MSK )

Bad_ptr ★★★★★
( 01.04.13 13:34:29 MSK )
Ответ на: комментарий от silver-bullet-bfg 01.04.13 13:03:24 MSK

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

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

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

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

Novator ★★★★★
( 01.04.13 13:59:36 MSK )
Ответ на: комментарий от Novator 01.04.13 13:59:36 MSK

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

Deleted
( 01.04.13 14:38:04 MSK )
Ответ на: комментарий от Deleted 01.04.13 13:30:22 MSK

Ну да, что тут сложного? Сделаете за 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 ★★
( 01.04.13 14:53:51 MSK )
Ответ на: комментарий от silver-bullet-bfg 01.04.13 14:53:51 MSK

* self.bntOk=ttk.Button (root, text=«Hello, world», command=self.cmdOk).grid()

silver-bullet-bfg ★★
( 01.04.13 14:55:04 MSK )
Ответ на: комментарий от Deleted 01.04.13 14:38:04 MSK

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

silver-bullet-bfg ★★
( 01.04.13 14:55:51 MSK )
Ответ на: комментарий от silver-bullet-bfg 01.04.13 14:55:04 MSK

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

Deleted
( 02.04.13 00:40:42 MSK )
Ответ на: комментарий от Novator 01.04.13 10:34:18 MSK

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

Deleted
( 02.04.13 00:53:31 MSK )
Ответ на: комментарий от Deleted 02.04.13 00:40:42 MSK

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

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 ★★
( 02.04.13 09:26:40 MSK )
Ответ на: комментарий от silver-bullet-bfg 01.04.13 14:53:51 MSK

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

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 ★★★★★
( 02.04.13 09:27:11 MSK )
Ответ на: комментарий от Novator 01.04.13 13:59:36 MSK

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

silver-bullet-bfg ★★
( 02.04.13 09:30:47 MSK )
Ответ на: комментарий от AIv 02.04.13 09:27:11 MSK

Ваше решение красивее:) Эх. Привык я уже все делать через ООП-извращения 🙁

silver-bullet-bfg ★★
( 02.04.13 09:33:26 MSK )
Ответ на: комментарий от silver-bullet-bfg 02.04.13 09:26:40 MSK

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

AIv ★★★★★
( 02.04.13 09:34:09 MSK )
Ответ на: комментарий от silver-bullet-bfg 02.04.13 09:33:26 MSK

Дык переходите на ФП! Даже для гуйни оно иногда бывает весьма полезно;-)

AIv ★★★★★
( 02.04.13 09:35:02 MSK )
Ответ на: комментарий от AIv 02.04.13 09:35:02 MSK

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

silver-bullet-bfg ★★
( 02.04.13 10:11:52 MSK )
Ответ на: комментарий от AIv 02.04.13 09:34:09 MSK

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

silver-bullet-bfg ★★
( 02.04.13 10:13:17 MSK )
Ответ на: комментарий от silver-bullet-bfg 02.04.13 10:11:52 MSK

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

Как скрыть виджеты после их нажатия и выполнения действия?

На главном окне у меня будут: кнопка, поля ввода и несколько label. Как сделать так, чтобы после нажатия кнопки она исчезала(скрывалась), а затем появлялись остальные объекты.
То есть как авторизация: вводим логин, пароль, нажимаем «войти», всё скрывается и появляются другие компоненты, то есть будто вход выполнен.

Искал в интернете, но нашел только скрыть кнопку по нажатию или скрыть/показать label по нажатию на кнопку.
Можно ли, когда нажму на кнопку, сначала выполниться действие(показ всех остальных элементов), а потом все компоненты авторизации исчезнут?(или наоборот, сначала все исчезает, а потом появляются компоненты). То есть можно ли как-то скрыть все компоненты по 1 нажатию кнопки и как это реализовать или есть какой-то другой способ?

Функция hide_me скрывает кнопку через bind(), если кнопка не привязана к координатам, а так ничего не происходит.
Попробовал через lambda сделать, чтобы выполнить 2 функции сразу, но появляется ошибка.

btn=Button(text=»Авторизация», command=lambda:(AUTO(),hide_me()))
TypeError: hide_me() missing 1 required positional argument: ‘event’

from tkinter import * def hide_me(event): event.widget.pack_forget() root = Tk() root.title("Авторизация") root.geometry("500x250") root.resizable(False, False) l = "admin" p = "password" LOGIN = "Введите логин:" LOGIN = Label(text=LOGIN, justify=LEFT) LOGIN.place(x=0, y=0) lineLOGIN = Entry() lineLOGIN.pack() lineLOGIN.place(x=80, y=30, anchor="c") PASS = "Введите пароль:" PASS = Label(text=PASS, justify=LEFT) PASS.place(x=0, y=60) linePASS = Entry() linePASS.pack() linePASS.place(x=80, y=90, anchor="c") def AUTO(): if lineLOGIN.get() == l and linePASS.get() == p: linePA = Entry() linePA.pack() linePA.place(x=200, y=70, anchor="c") else: print("Неверный логин/пароль") btn=Button(text="Авторизация", command=lambda:(AUTO(),hide_me())) #btn.bind('', hide_me) btn.pack() btn.place(x=60, y=120, anchor="c") root.mainloop()
  • Вопрос задан более двух лет назад
  • 705 просмотров

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *