Когда мне нужно вызвать mainloop в приложении Tkinter? - PullRequest
40 голосов
/ 30 декабря 2011

В каждом уроке tkinter, который я видел, утверждается, что tkinter.mainloop должен вызываться для рисования окон и обработки событий, и они всегда вызывают эту функцию, даже в программах hello world.Тем не менее, когда я пробую это в интерактивной оболочке, окна отображаются правильно, без вызова mainloop. Этот пример встраивания графики Matplotlib в tkinter создает довольно сложное приложение с кнопками для панорамирования, масштабирования и изменения размера графика в окне tkinter, и опять же, все это работает, если вы удалите вызов mainloop и запуститекод в интерактивной оболочке.Конечно, если я запускаю скрипт (с удаленным mainloop) за пределами интерактивной оболочки, программа слишком быстро завершает работу, чтобы увидеть, что происходит, но если я добавлю вызов к input, чтобы держать программу открытой, все работает правильно (язапуск python 3.2.2 в Linux).

Так что же делает mainloop и когда необходимо его вызывать?

EDIT: чтобы уточнить, открываю ли я терминал GNOME ивведите

$python3
>>> import tkinter
>>> root = tkinter.Tk()

, окно немедленно появляется без необходимости вызывать mainloop, и более сложные функции tkinter, кажется, также работают (например, добавление кнопок в окно).В IDLE вызов mainloop необходим.Насколько я понимаю, ничто не должно быть нарисовано, и никакие события не должны обрабатываться, пока не будет вызван mainloop.

Ответы [ 4 ]

45 голосов
/ 31 декабря 2011

Ответ на ваш главный вопрос: вы должны вызывать mainloop один раз и только один раз, когда будете готовы к запуску приложения.

mainloop - это не что иное, как бесконечный цикл, который выглядит примерно так (это не настоящие имена методов, а только названия, иллюстрирующие эту точку):

while True:
    event=wait_for_event()
    event.process()
    if main_window_has_been_destroyed(): 
        break

В этом контексте «событие» означает как пользовательские взаимодействия (щелчки мыши, нажатия клавиш и т. Д.), Так и запросы из набора инструментов или диспетчера ОС / окна для рисования или перерисовки виджета.Если этот цикл не выполняется, события не обрабатываются.Если события не будут обработаны, на экране ничего не появится, и ваша программа, вероятно, завершится, если у вас не работает собственный бесконечный цикл.

Итак, почему бы вам не позвонить в интерактивном режиме?Это просто удобство, потому что в противном случае было бы невозможно вводить какие-либо команды после вызова mainloop, поскольку mainloop работает до тех пор, пока главное окно не будет уничтожено.

7 голосов
/ 31 декабря 2011

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

Но программа с графическим интерфейсом отличается: в любой момент она должна иметь возможность обрабатывать всевозможные события и взаимодействия. Это требование часто реализуется с использованием программной конструкции, называемой циклом событий. Цикл событий - это центральная управляющая структура программы. Он ожидает события, а затем отправляет соответствующий обработчик.

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

0 голосов
/ 11 марта 2016

следующим образом:

from tkinter import *

tk = Tk()
canvas = Canvas(tk, width=500, height=500)
canvas.pack()
canvas.create_line(0, 0, 500, 500)

mainloop()
0 голосов
/ 16 января 2016

Я решил, что вместо того, чтобы прикреплять вызов напрямую к mainloop в любом месте моего скрипта, я просто добавлю его как часть atexit - то есть, когда интерпретатор Python решит, что пора начинать закрываться, это войдет в основную петлю Тк. Это затем предотвращает завершение последовательности выключения до тех пор, пока пользователь фактически не скажет Tk выйти (IE, с помощью команды Q на Mac или щелкнув красный крестик в Windows).

from Tkinter import Tk
root = Tk()

import atexit
atexit.register(root.mainloop)

Кажется, нет необходимости вызывать mainloop из командной строки системы. Интерпретатор Python будет продолжать работать без него, потому что он ожидает от вас дальнейших действий (пока вы не запустите exit()).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...