Как закрыть окно программы python

Как мне обрабатывать событие закрытия окна (нажатие кнопки «X» ) в программе Python Tkinter?

ОТВЕТЫ

Ответ 1

Tkinter поддерживает механизм, называемый обработчики протоколов. Здесь термин «протокол» относится к взаимодействию между приложением и диспетчером окон. Наиболее часто используемый протокол называется WM_DELETE_WINDOW и используется для определения того, что происходит, когда пользователь явно закрывает окно с помощью диспетчера окон.

Вы можете использовать метод protocol для установки обработчика для этого протокола (виджет должен быть виджем Tk или Toplevel ):

Здесь у вас есть конкретный пример:

import tkinter as tk from tkinter import messagebox root = tk.Tk() def on_closing(): if messagebox.askokcancel(«Quit», «Do you want to quit?»): root.destroy() root.protocol(«WM_DELETE_WINDOW», on_closing) root.mainloop()

Ответ 2

Мэтт показал одну классическую модификацию кнопки закрытия.

Всплывающее окно в python #short


Другой заключается в том, чтобы закрыть кнопку закрытия окна.
Вы можете воспроизвести это поведение, используя метод iconify protocol второй аргумент.

Вот рабочий пример, протестированный в Windows 7:

# Python 3 import tkinter import tkinter.scrolledtext as scrolledtext class GUI(object): def __init__(self): root = self.root = tkinter.Tk() root.title(‘Test’) # make the top right close button minimize (iconify) the main window root.protocol(«WM_DELETE_WINDOW», root.iconify) # make Esc exit the program root.bind(», lambda e: root.destroy()) # create a menu bar with an Exit command menubar = tkinter.Menu(root) filemenu = tkinter.Menu(menubar, tearoff=0) filemenu.add_command(label=»Exit», command=root.destroy) menubar.add_cascade(label=»File», menu=filemenu) root.config(menu=menubar) # create a Text widget with a Scrollbar attached txt = scrolledtext.ScrolledText(root, undo=True) txt[‘font’] = (‘consolas’, ’12’) txt.pack(expand=True, fill=’both’) gui = GUI() gui.root.mainloop()

В этом примере мы даем пользователю два новых варианта выхода:
классическое меню файлов → Выход, а также кнопку Esc .

Ответ 3

В зависимости от активности Tkinter, и особенно при использовании Tkinter.after, остановка этой активности с помощью destroy() — даже с использованием protocol(), кнопки и т.д. — будет нарушать эту активность (ошибка «во время выполнения»), а не просто прекратить это. Лучшее решение почти в каждом случае — использовать флаг. Вот простой, глупый пример того, как его использовать (хотя я уверен, что большинству из вас это не нужно! 🙂

from Tkinter import * def close_window(): global running running = False print «Window closed» root = Tk() root.protocol(«WM_DELETE_WINDOW», close_window) cv = Canvas(root, width=200, height=200); cv.pack() running = True; # This is an endless loop stopped only by setting ‘running’ to ‘False’ while running: for i in range(200): if not running: break cv.create_oval(i,i,i+1,i+1); root.update()

Это хорошо завершает графическую активность. Вам нужно только проверить running в нужном месте (ах).

Как скрыть окно в Tkinter на Python

Ответ 4

Попробуйте простую версию:

import tkinter window = Tk() closebutton = Button(window, text=’X’, command=window.destroy) closebutton.pack() window.mainloop()

Или, если вы хотите добавить больше команд:

import tkinter window = Tk() def close(): window.destroy() #More Functions closebutton = Button(window, text=’X’, command=close) closebutton.pack() window.mainloop()

Ответ 5

Я хотел бы поблагодарить ответ апостола за то, что он привлек мое внимание. Вот гораздо более подробный пример для Python 3 в 2019 году, с более ясным описанием и примером кода.

Читайте также:
Программа где подставляют к лицу прически

Остерегайтесь того факта, что destroy() (или вообще не имеющий собственного обработчика закрытия окна) уничтожит окно и все его текущие обратные вызовы мгновенно, когда пользователь закроет его.

Это может быть плохо для вас, в зависимости от текущей активности Tkinter, особенно при использовании tkinter.after (периодические обратные вызовы). Возможно, вы используете обратный вызов, который обрабатывает некоторые данные и записывает их на диск. в этом случае вы, очевидно, хотите, чтобы запись данных завершилась без внезапного уничтожения.

Лучшее решение для этого — использовать флаг. Поэтому, когда пользователь запрашивает закрытие окна, вы отмечаете это как флаг, а затем реагируете на него.

(Примечание: я обычно проектирую GUI как хорошо инкапсулированные классы и отдельные рабочие потоки, и я определенно не использую «глобальный» (вместо этого я использую переменные экземпляра класса), но это должен быть простой, урезанный пример для демонстрации как Tk внезапно убивает ваши периодические обратные вызовы, когда пользователь закрывает окно. )

from tkinter import * import time # Try setting this to False and look at the printed numbers (1 to 10) # during the work-loop, if you close the window while the periodic_call # worker is busy working (printing). It will abruptly end the numbers, # and kill the periodic callback!

That why you should design most # applications with a safe closing callback as described in this demo. safe_closing = True # ——— busy_processing = False close_requested = False def close_window(): global close_requested close_requested = True print(«User requested close at:», time.time(), «Was busy processing:», busy_processing) root = Tk() if safe_closing: root.protocol(«WM_DELETE_WINDOW», close_window) lbl = Label(root) lbl.pack() def periodic_call(): global busy_processing if not close_requested: busy_processing = True for i in range(10): print((i+1), «of 10») time.sleep(0.2) lbl[«text»] = str(time.time()) # Will error if force-closed. root.update() # Force redrawing since we change label multiple times in a row. busy_processing = False root.after(500, periodic_call) else: print(«Destroying GUI at:», time.time()) try: # «destroy()» can throw, so you should wrap it like this. root.destroy() except: # NOTE: In most code, you’ll wanna force a close here via # «exit» if the window failed to destroy. Just ensure that # you have no code after your ‘mainloop()’ call (at the # bottom of this file), since the exit call will cause the # process to terminate immediately without running any more # code. Of course, you should NEVER have code after your # ‘mainloop()’ call in well-designed code anyway. # exit(0) pass root.after_idle(periodic_call) root.mainloop()

Этот код покажет вам, что обработчик WM_DELETE_WINDOW работает, даже когда наш пользовательский periodic_call() занят посреди работы/циклов!

Создание окна по центру и кнопка выхода в Tkinter

Создание окна в Tkinter

В этой части обучения Tkinter мы познакомим Вас с инструментом Tkinter и создадим первые программы. Целью этого руководства является ознакомление с базой инструментария Tkinter. Я использовал несколько иконок из набора Tango от Gnome project.

Tkinter библиотека для создания графических интерфейсов

Tkinter – это графическая библиотека на основе Tk, которая входит в стандартную библиотеку Python. Tk является библиотекой базовых элементов графического интерфейса для языка Tcl. Tkinter реализован как оболочка Python для Tcl интерпретатора, встроенного в интерпретатор Python. Существует и несколько других популярных графических инструментов для Python. Наиболее популярными являются wxPython, PyQt5 и PyGTK.

Язык программирования Python

Python – это высокоуровневый, динамичный, объектно-ориентированный язык программирования. Он ориентирован на повышение производительности программиста и читаемости кода. Разработчиком кода является Гвидо ван Россум. Впервые язык увидел свет в 1991 году. При создании Python, автор вдохновлялся такими языками программирования как ABC, Haskell, Java, Lisp, Icon и Perl.

Читайте также:
Лучшая программа для печати фотографий на принтере epson

Python является высокоуровневым, кроссплатформенным, но в то же время минималистичным языком. Одним из его основных преимуществ является отсутствие скобок и точек с запятой. Вместо этого Python использует отступы. Сегодня существует две основные ветви языка: Python 2.7 и Python 3.x.

Стоит отметить, что Python 3 нарушает обратную совместимость с предыдущими версиями языка. Его разработали для того, чтобы исправить ряд недостатков конструкции уже существующего языка, упростить и очистить его от ненужных деталей. Последней версией Python 2.x является 2.7.17, а Python 3.x – 3.8.5. Данный учебник написан на Python 2.x, равно как и большая часть кода. Мы обновили учебник под Python 3.8.

Для перехода программного обеспечения и самих разработчиков на Python 3.x потребуется какое-то время. Уже перешли все на Python 3. Сегодня Python поддерживается большим количеством добровольцев со всего мира. Напомню, что язык имеет открытый исходный код.

Python – это идеальный язык для тех людей, которые хотят научиться программировать.

Язык программирования Python поддерживает несколько стилей программирования. Он не принуждает разработчика придерживаться определенной парадигмы. Python поддерживает объектно-ориентированное и процедурное программирование. Существует и ограниченная поддержка функционального программирования.

Создание обычного окна в Tkinter

В нашем первом примере мы покажем стандартное окно на экране.

Источник: python-scripts.com

Всплывающие окна / tkinter 11

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

Но есть в Tkinter и другой класс, который используется для создания дополнительных окон верхнего уровня. Он называется Toplevel . Этот класс можно использовать для отображения любого типа окна: от диалоговых до мастер форм.

Начнем с создания простого окна, которое открывается по нажатию кнопки в основном. Дополнительное окно будет включать кнопку, которая закрывает его и возвращает фокус в основное:

Открытие дополнительного окна

Класс виджета Toplevel создает новое окно верхнего уровня, которое выступает в качестве родительского контейнера по аналогии с экземпляром Tk . В отличие от класса Tk можно создавать неограниченное количество окон верхнего уровня:

import tkinter as tk

class About(tk.Toplevel):
def __init__(self, parent):
super().__init__(parent)
self.label = tk.Label(self, text=»Это всплывающее окно»)
self.button = tk.Button(self, text=»Закрыть», command=self.destroy)

self.label.pack(padx=20, pady=20)
self.button.pack(pady=5, ipadx=2, ipady=2)

class App(tk.Tk):
def __init__(self):
super().__init__()
self.btn = tk.Button(self, text=»Открыть новое окно»,
command=self.open_window)
self.btn.pack(padx=50, pady=20)

def open_window(self):
about = About(self)
about.grab_set()

if __name__ == «__main__»:
app = App()
app.mainloop()

Как работают всплывающие окна

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

class Window(tk.Toplevel):
def __init__(self, parent):
super().__init__(parent)

Окно открывается за счет создания нового экземпляра, но чтобы оно получало все события, нужно вызвать его метод grab_set . Благодаря этому пользователи не будут взаимодействовать с основным окном, пока дополнительное не закроется:

def open_window(self):
window = Window(self)
window.grab_set()

Обработка закрытия окна

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

Будем заново использовать класс App из прошлого примера, но изменим класс Window , чтобы он показывал диалоговое окно для подтверждения перед закрытием:

Обработка закрытия окна

В Tkinter можно определить, когда окно готовится закрыться с помощью функции-обработчика для протокола WM_DELETE_WINDOW . Его можно запустить, нажав на иконку «x» в верхней панели в большинстве настольных программ.

Читайте также:
Как в программе сбис уволить сотрудника

import tkinter as tk
import tkinter.messagebox as mb

class Window(tk.Toplevel):
def __init__(self, parent):
super().__init__(parent)
self.protocol(«WM_DELETE_WINDOW», self.confirm_delete)
self.label = tk.Label(self, text=»Это всплывающее окно»)
self.button = tk.Button(self, text=»Закрыть», command=self.destroy)
self.label.pack(padx=20, pady=20)
self.button.pack(pady=5, ipadx=2, ipady=2)

def confirm_delete(self):
message = «Вы уверены, что хотите закрыть это окно?»
if mb.askyesno(message=message, parent=self):
self.destroy()

class App(tk.Tk):
def __init__(self):
super().__init__()
self.btn = tk.Button(self, text=»Открыть новое окно»,
command=self.open_about)
self.btn.pack(padx=50, pady=20)

def open_about(self):
window = Window(self)
window.grab_set()

if __name__ == «__main__»:
app = App()
app.mainloop()

Этот метод-обработчик показывает диалоговое окно для подтверждения удаления окна. В более сложных программах логика обычно включает дополнительную валидацию.

Как работает проверка закрытия окна

Метод bind() используется для регистрации обработчиков событий виджетов, а метод protocol делает то же самое для протоколов менеджеров окна.

Обработчик WM_DELETE_WINDOW вызывается, когда окно верхнего уровня должно уже закрываться, и по умолчанию Tk уничтожает окно, для которого оно было получено. Поскольку это поведение перезаписывается с помощью обработчика confirm_delete , нужно явно уничтожить окно при подтверждении.

Еще один полезный протокол — WM_TAKE_FOCUS . Он вызывается, когда окно получает фокус.

Стоит запомнить, что для сохранения фокуса в дополнительном окне при открытом диалоговом нужно передать ссылку экземпляру верхнего уровня в параметре parent диалоговой функции:

if mb.askyesno(message=message, parent=self):
self.destroy()

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

Передача переменных между окнами

Два разных окна иногда нуждаются в том, чтобы передавать информацию прямо во время работы программы. Ее можно сохранять на диск и читать в нужном окне, но в определенных случаях удобнее обрабатывать ее в памяти и передавать в качестве переменных.

Основное окно будет включать три кнопки-переключателя для выбора типа пользователя, а второе — форму для заполнения его данных:

Передача переменных между окнами

Для сохранения пользовательских данных создаем namedtuple с полями, которые представляют собой экземпляр каждого пользователя. Эта функция из модуля collections получает имя типа и последовательность имен полей, а возвращает подкласс кортежа для создания простого объекта с заданными полями:

import tkinter as tk
from collections import namedtuple

User = namedtuple(«User», [«username», «password», «user_type»])

class UserForm(tk.Toplevel):
def __init__(self, parent, user_type):
super().__init__(parent)
self.username = tk.StringVar()
self.password = tk.StringVar()
self.user_type = user_type

label = tk.Label(self, text=»Создать пользователя » + user_type.lower())
entry_name = tk.Entry(self, textvariable=self.username)
entry_pass = tk.Entry(self, textvariable=self.password, show=»*»)
btn = tk.Button(self, text=»Submit», command=self.destroy)

label.grid(row=0, columnspan=2)
tk.Label(self, text=»Логин:»).grid(row=1, column=0)
tk.Label(self, text=»Пароль:»).grid(row=2, column=0)
entry_name.grid(row=1, column=1)
entry_pass.grid(row=2, column=1)
btn.grid(row=3, columnspan=2)

def open(self):
self.grab_set()
self.wait_window()
username = self.username.get()
password = self.password.get()
return User(username, password, self.user_type)

class App(tk.Tk):
def __init__(self):
super().__init__()
user_types = («Админ», «Менеджер», «Клиент»)
self.user_type = tk.StringVar()
self.user_type.set(user_types[0])

label = tk.Label(self, text=»Пожалуйста, выберите роль пользователя»)
radios = [tk.Radiobutton(self, text=t, value=t,
variable=self.user_type) for t in user_types]
btn = tk.Button(self, text=»Создать», command=self.open_window)

label.pack(padx=10, pady=10)
for radio in radios:
radio.pack(padx=10, anchor=tk.W)
btn.pack(pady=10)

def open_window(self):
window = UserForm(self, self.user_type.get())
user = window.open()
print(user)

if __name__ == «__main__»:
app = App()
app.mainloop()

Когда поток выполнения возвращается в основное окно, пользовательские данные выводятся в консоль.

Как работает передача данных между окнами

Большая часть кода в этом примере рассматривалась и ранее, а основное отличие — в методе open() класса UserForm , куда перемещен вызов grab_set() . Однако именно метод wait_windows() отвечает за остановку исполнения и гарантирует, что данные не вернутся, пока форма не будет изменена:

Источник: pythonru.com

Рейтинг
( Пока оценок нет )
Загрузка ...
EFT-Soft.ru