2016-11-02 15 views
2

Здравствуйте, я нашел небольшую проблему с использованием библиотеки черепах и IDLE питона. Обратите внимание на следующий код, написанный на Python 3.5.2:Tkinter не отвечает при запуске ввода(), хуже в IDLE

import turtle 
turtle.Turtle() 
input("Try moving/resizing the window in IDLE. Press enter than try again.") 

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

Если пробег через IDLE, после нажатия пользователем ввести окно может , то будет свободно перемещаться и изменять размер без проблем. Это связано с тем недостатком, что мы больше не внутри скрипта, а обратно в оболочку python. Конечно, мы все еще можем взаимодействовать с черепахой через оболочку, но это не то, что я хочу в своем фактическом приложении. Моя основная программа использует input(), чтобы спросить пользователя, хотят ли они перемещаться/вращаться и на сколько. Это остается в бесконечном цикле, пока пользователь не вводит такую ​​фразу, как «quit», чтобы закончить программу. Отмечу, что даже с IDLE черепаха все еще движется и рисуется правильно. Проблема в том, что само окно становится невосприимчивым. Содержимое все правильно.

Мне очень любопытно, почему только IDLE дает мне такое поведение ... Не только это, есть ли способ, которым я могу держать окно черепахи от того, чтобы быть невосприимчивым и все еще использовать input() и тому подобное ? Или, может быть, есть альтернатива, о которой я не думал? Мое исследование побудило меня поверить, что это имеет отношение к TkInter. Это объясняет, почему это работает только за пределами IDLE.

Ниже изображение, которое показывает мое затруднительное положение.

Unresponsive turtle window

+0

FYI, нет никакой разницы между запуском python.exe из оболочки cmd или powershell. В обоих случаях python.exe наследует консольный дескриптор (для общего IPC к приложенному экземпляру conhost.exe) и стандартные дескрипторы для входных и экранных буферов консоли (если стандартный ввод-вывод не перенаправлен на канал или файл). Оболочка ждет своего дескриптора процесса для python.exe, поэтому он не взаимодействует с консолью до выхода Python. – eryksun

+0

При вводе в консоль Windows - для ввода REPL или ввода строки в 'input()' - окно черепахи должно перестать реагировать, потому что основной поток заблокирован и 'PyOS_InputHook' не работает для обновления Окно Tk. Если на самом деле все еще обновляется окно черепахи, то наиболее вероятным объяснением является то, что у вас установлена ​​пиковая линия. Он не использует приготовленное чтение, которое блокируется до тех пор, пока пользователь не нажимает кнопку ввода, а вместо этого считывает необработанные события ввода в консоль и может продолжить вызов крюка ввода для обновления Tk, когда пользователь вводит текст. – eryksun

ответ

1

Как вы подозревали, основной вопрос с Tkinter, а не конкретно с приложением черепахи, которая использует Tkinter. Сначала я воспроизвел в IDLE с открытым окном tk.

Затем я выполнил приведенную выше строку за раз в 3.5.2, запущенную интерактивно в командной строке на Win10. Во второй строке отображается пустое окно, добавляется запись в TaskManager и добавляется значок Python на панель задач. Щелчок назад и вперед между CP и Tk вызывает соответствующее окно и значок, чтобы получить «активный» вид. Граница окна смещается от серого к черному, тогда как фон значка смещается от черного к серому.

При вводе инструкции ввода, но перед возвратом, окно Tk показывает «не отвечает» (через пару секунд) как в строке заголовка, так и в TaskManager. Мышь над внутренней частью окна становится синим занятым кругом. Окно становится «активным», как описано выше, и может быть перемещено, но не может быть изменено и не может быть нормально закрыто (нажатие на [X] вызывает окно «Не отвечает, закрывает или ждет?».

Когда оператор вводится, окно tk становится нормально реагирующим снова. Как только «пользователь» вводит что-либо, окно tk перестает отвечать так, как описано выше, до тех пор, пока запись не будет завершена с помощью Enter.

Если вы повторите попытку в CP и введите некоторые символы, не нажав Enter, вы видите ту же самую невосприимчивость?

Различия в оболочке IDLE: создание корня помещает новую запись в TaskManager, но новое окно прикрепляется к IDLE значок. Пока вводится инструкция ввода, окно Tk остается нормально реагирующим. Итак, на этом этапе, IDLE лучше. Когда введен вход(), окно Tk становится, как вы заметили, полностью не отвечает (не может двигаться) даже перед любой записью. Эта часть хуже.

Я пробовал еще один эксперимент: работает IDLE с параметром -n ('no subprocess').

C:\Users\Terry>python -m idlelib -n 

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

Комментарий 1: IDLE предназначен для разработки и обучения, а не для производственного исполнения. Но он может быть использован для последнего, если есть преимущество для этого. Вам просто нужно проверить, что использование -n не представляет никаких других проблем, точнее, что черепаха и ваш код не мешают IDLE при запуске в том же процессе.

Комментарий 2: Программы GUI обычно не используют ввод и печать. Обычно они запускаются без консоли для взаимодействия. Если используется input(), даже в консоли Windows пользователь не должен касаться окна перед ответом на подсказку.

Комментарий 3: Программы GUI обычно используют виджеты GUI вместо того, чтобы извлекать и отображать информацию. Черепаха делает это более трудным, но не невозможным, о чем свидетельствует черепаха. Вы можете упростить и адаптировать код в turtledemo/main .py.

+0

tkinter регистрирует ['EventHook'] (https://hg.python.org/cpython/file/v3.5.2/Modules/_tkinter.c#l3381) как функцию« PyOS_InputHook ». Этот крючок вызывается ['my_fgets'] (https://hg.python.org/cpython/file/v3.5.2/Parser/myreadline.c#l26) при чтении через' PyOS_ReadLine' в консоли REPL и 'input '. Крюк выходит из цикла обновления, как только '_kbhit' возвращает true. Затем строка ввода считывается с помощью 'ReadFile' или' ReadConsole'. Виджеты Tk не обновляются повторно, пока этот вызов не вернется. Кстати, вам не нужно 'input', чтобы это увидеть; просто введите REPL. – eryksun

+0

В настоящее время в версии 3.6 beta 'PyOS_Readline' не вызывается функция' PyOS_InputHook'. Это ошибка, о которой я упомянул Стив Дауэр, но я все время забываю создать для нее проблему. – eryksun

+0

IDLE полностью отличается. Он не использует REPL и 'input' читает с помощью простого вызова' PyFile_GetLine'. «Readline» проксируется через сокет из рабочего процесса в оболочку IDLE. Пока он ждет строки ввода, основной цикл в рабочем процессе, очевидно, не вызывает ['handle_tk_events'] (https://hg.python.org/cpython/file/v3.5.2/Lib/idlelib/run .py # L58). – eryksun