остановить окно tkinter от зависания во время сна программы - PullRequest
1 голос
/ 12 февраля 2012

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

Моя программа состоит из трех модулей, которые импортируются друг в друга.Один модуль состоит из моего пользовательского интерфейса, для которого я использую tkinter.Пользователь вводит данные на холст, который отправляется во вторую обрабатываемую программу, а затем отправляется в третий модуль, содержащий алгоритм, который я намерен выполнить с пользователем.

«Первый» и«третьи» модули могут взаимодействовать друг с другом, и в определенные моменты при объяснении алгоритма я меняю внешний вид холста и некоторый текст на интерфейсе.Затем третий модуль должен сделать паузу (для которой я в настоящее время использую основной метод сна) и подождать (в идеале он будет ждать, пока пользователь нажмет кнопку «Следующий шаг» в пользовательском интерфейсе).Именно на этом этапе мой интерфейс решает, что он хочет заморозить.

Можно ли как-нибудь это остановить?

Заранее большое спасибо.

Редактировать: IЯ нашел способ исправить это.Спасибо за все предложения!

Ответы [ 3 ]

4 голосов
/ 12 февраля 2012

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

Для этого поместите следующую часть вашего кода в отдельную функцию и заставьте Tkinter вызывать ее, когда она будет готова. Как правило, вы хотите, чтобы это происходило, когда пользователь запускает его (например, нажатием кнопки), поэтому вам необходимо привязать его к событию ( docs ). Если вы действительно хотите, чтобы это произошло через определенное время, вы можете использовать метод .after() в любом виджете tkinter ( docs ).

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

Примечание по терминологии: если ваши файлы Python импортируют друг друга, у вас есть три модуля , но это все еще одна программа . Разговоры о «первой программе» сбивают людей с толку.

1 голос
/ 13 февраля 2012

H.E.P - Традиционный способ сделать это действительно включает использование отдельного потока и координацию работы между «рабочим» потоком и потоком GUI с использованием какого-либо механизма опроса или обработки событий.

Но, как отмечает Томас К., это может стать очень сложным и хитрым, особенно в том, что касается использования в Python глобальной блокировки интерпретатора (GIL) и т. Д., А также в случае необходимости бороться с циклом обработки Tkinter.

(Единственная веская причина для использования многопоточного GUI - это если вы абсолютно ДОЛЖНЫ гарантировать, что GUI останется отзывчивым во время потенциально длительной фоновой задачи, что, я не думаю, является проблемой в этом случае.)

Вместо этого я бы предложил основанную на генераторе «параллельную» архитектуру. Как отмечено в «Справочнике по языку Python (2.7)», раздел 6.8, [оператор yield »используется при определении функции генератора и используется только в теле функции генератора. Использование оператора yield в определении функции достаточно для того, чтобы это определение создало функцию генератора вместо нормальной функции.]

(Это фактически составляет основу сопутствующей архитектуры. (Ред.))

[Когда вызывается функция генератора, она возвращает итератор, известный как итератор генератора, или, более часто, генератор. Тело функции генератора выполняется путем многократного вызова метода next () генератора, пока он не вызовет исключение.

Когда выполняется оператор yield, состояние генератора блокируется, и значение expression_list возвращается вызывающей стороне next (). Под «замороженным» мы подразумеваем, что сохраняется все локальное состояние, включая текущие привязки локальных переменных, указатель инструкций и внутренний стек оценки: достаточно информации сохраняется, чтобы в следующий раз вызываться next (), Функция может работать точно так же, как если бы оператор yield был просто еще одним внешним вызовом. ] (Также см. «PEP 0342 - сопрограммы через расширенные генераторы» для получения дополнительной информации и общей информации.)

Это должно позволить вашему графическому интерфейсу вызывать следующую часть вашего генератора спецификации алгоритма, по требованию, без необходимости переводить его в спящий режим до тех пор, пока оператор не нажмет кнопку «Далее». Вы бы просто создали небольшой «предметно-ориентированный язык» (DSL), состоящий из списка шагов для представления этого конкретного алгоритма, а генератор (итератор) просто выполнял бы каждый следующий шаг при вызове (on спрос).

Гораздо проще и проще в обслуживании.

0 голосов
/ 13 февраля 2012

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

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