#python #tkinter #python-2to3
#python #tkinter #python-2to3
Вопрос:
У меня есть графический интерфейс Python 2.7, использующий Tkinter и переносящий его на 3.7. Он передает стандартный вывод подпроцесса в виджет scrolledtext и отлично работает с 2.7, но с 3.7 он постоянно обновляет виджет, и я не могу прокручивать. Фрагмент кода:
#lauch main
proc = subprocess.Popen(["python", testPath, filePath] script_list, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=0)
#clear the text box widget
text.delete("1.0", END)
#check for alternate main.py
if (alt_main_flag == True):
text.insert(END, "Using alternate MAIN script in " filePath 'n')
#send the scripts output to the GUI text box
# for 3.x, had to use bytes() conversion prior to 'in'
for line in iter(proc.stdout.readline,''):
if (bytes("Starting ", 'ascii') in line):
line = line.strip()
statusvar.set(line)
else:
text.insert(END, line)
if (bytes("end of program", 'ascii') in line):
statusvar.set("Ready")
#update in "real time"
text.see(END)
root.update()
text.update_idletasks()
Предложения?
Отметить
Комментарии:
1. Когда я удаляю строку text.see (END), все становится «лучше»… Я могу прокручивать, когда подпроцесс завершается… но, конечно, текст не обновляется / не прокручивается в «реальном времени»… он остается наверху. Должен быть лучший способ!
2. Заметил, что когда я отключаю графический интерфейс, python выдает эту ошибку: File «Z:ProjectsPython_Test_ScriptsGui_Test3_8_GUIGUI_2.py «, строка 675, в файле startMain text.update_idletasks() «C:Python37libtkinter_init_.py «, строка 1182, в update_idletasks self.tk.call(‘update’, ‘idletasks’) _tkinter. TclError: не удается вызвать команду «обновить»: приложение было уничтожено — как будто цикл for все еще выполняется! ПОЧЕМУ??? Это объяснило бы все, что я вижу.
3. Это ИМЕННО то, что не так! Цикл for никогда не завершается. Что за черт?
Ответ №1:
Найден обходной путь: добавлен разрыв в цикл for.
for line in iter(proc.stdout.readline,''):
if (bytes("Starting ", 'ascii') in line):
line = line.strip()
statusvar.set(line)
else:
text.insert(END, line)
if (bytes("end of program", 'ascii') in line):
statusvar.set("Ready")
if (len(line) == 0):
break
#update in "real time"
text.see(END)
root.update()
text.update_idletasks()
Комментарии:
1. Вы можете установить
text=True
subprocess.Popen(...)
, тогда вам не нужно использоватьbytes(...)
. Также вы можете просто использоватьfor line in proc.stdout:
вместо этого. И вам не нужно вызыватьroot.update()
.