Подтвердить что ты не робот

Когда мне нужно вызвать mainloop в приложении Tkinter?

В каждом учебнике tkinter я видел утверждения, что tkinter.mainloop должен быть вызван для окон, которые нужно рисовать, и событий, которые нужно обработать, и они всегда называют эту функцию даже в приветственных программах мира. Однако, когда я пытаюсь выполнить их в интерактивной оболочке, окна рисуются правильно, без вызова mainloop. Этот пример встраивания графики matplotlib в tkinter создает относительно сложное приложение с кнопками для панорамирования, масштабирования и изменения размера графика в окне tkinter и снова, это все работает, если вы удалите вызов mainloop и запустите код в интерактивной оболочке. Конечно, если я запустил script (с удалением mainloop) вне интерактивной оболочки, программа закончится слишком быстро, чтобы узнать, что произойдет, но если я добавлю вызов input, чтобы открыть программу, все работает правильно (I 'm запускает python 3.2.2 на linux).

Итак, что именно делает mainloop, и когда нужно называть его?

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

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

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

4b9b3361

Ответ 1

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

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

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

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

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

Ответ 2

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

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

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

Ответ 3

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

from Tkinter import Tk
root = Tk()

import atexit
atexit.register(root.mainloop)

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

Ответ 4

Как следует:

from tkinter import *

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

mainloop()