Консоль Tkinter GUI не обновляется при запуске пакета - PullRequest
0 голосов
/ 31 мая 2019

Я разработал графический интерфейс, отображающий некоторый контент conf-файла, позволяющий изменить его и затем запустить какой-то большой пакетный процесс.

import tkinter as Tk
from tkinter import ttk,messagebox
from sorter import Sorter

class GUI():

def __init__(self,logger) :
    self.window = Tk.Tk()
    self.window.resizable(False,False)
    self.window.title('BestArcade')
    self.logger = logger

def draw(self) :
    self.root = Tk.Frame(self.window,padx=10,pady=5)
    self.root.grid(column=0,row=0)
    self.drawConsole()
    self.window.mainloop()

def clickProceed(self) :
    self.logger.log('\n<--------- Starting Process --------->')
    sorter = Sorter(self.logger)
    # Big batch processes start here, from now on logs are not displayed
    sorter.prepare()
    self.logger.log('\n<--------- Create Sets --------->')
    sorter.createSets(sorter.allTests,sorter.dats)
    # Logs from the process are displayed all together here
    self.logger.log("\n<--------- Detecting errors ----------->")
    self.logger.log('<--------- Process finished ----------->')

def drawConsole(self) :
    self.consoleFrame = Tk.Frame(self.root, padx=10)
    self.consoleFrame.grid(column=0,row=4,sticky="EW",pady=5)
    self.consoleFrame.grid_columnconfigure(0, weight=1)
    self.logTest = Tk.Text(self.consoleFrame, height=20, state='disabled', wrap='word',background='black',foreground='yellow')
    self.logTest.grid(column=0,row=0,sticky="EW")
    self.scrollbar = Tk.Scrollbar(self.consoleFrame, orient=Tk.VERTICAL,command=self.logTest.yview)
    self.scrollbar.grid(column=1,row=0,sticky=(Tk.N,Tk.S))
    self.logTest['yscrollcommand'] = self.scrollbar.set
    self.logTest.after(10,self.updateConsoleFromQueue)

def updateConsoleFromQueue(self):
    while not self.logger.log_queue.empty():
        line = self.logger.log_queue.get()
        print('WRITECONSOLE')
        self.writeToConsole(line)
    self.logTest.after(10,self.updateConsoleFromQueue)

def writeToConsole(self, msg):
    numlines = self.logTest.index('end - 1 line').split('.')[0]
    self.logTest['state'] = 'normal'
    if numlines==24:
        self.logTest.delete(1.0, 2.0)
    if self.logTest.index('end-1c')!='1.0':
        self.logTest.insert('end', '\n')
    self.logTest.insert('end', msg)
    self.logTest.see(Tk.END)
    self.logTest['state'] = 'disabled'

В графическом интерфейсе пользователя есть консольная часть, отображающая запись всех событий, которые происходят, используя очередь, в которой push-логгер и консольный виджет Text получают

import queue

class Logger() :

def __init__(self) :
    self.log_queue = queue.Queue()

def log(self,msg) :
    self.log_queue.put(msg.rstrip('\n'))
    print(msg.rstrip('\n'))

Основной лаунчер довольно прост:

from gui import GUI
from logger import Logger

if __name__ == "__main__":
   logger = Logger()
   logger.log('Start')
   gui = GUI(logger)
   logger.log('\n<--------- Load Configuration File --------->')
   gui.draw()

Проблема в том, что каждая зарегистрированная часть изнутри GUI (или до mainloop) появляется немедленно, тогда как многие журналы процесса большой партии появляются все вместе в конце процесса, когда он закончен. Большой пакетный процесс находится в классе Sorter, который регистрирует строки наподобие:

self.logger.log('\n<--------- Load Favorites Ini Files --------->')

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

Очевидно, что это проблема многопоточности, журналы прекрасно добавляются в очередь из регистратора в режиме реального времени, но функция GUI updateConsoleFromQueue вообще не доступна во время пакетного процесса, даже используя after (), фактически всю печать ( 'WRITECONSOLE') появляется и после окончания процесса большой партии

Я понимаю, что это как-то связано с протеканием основной петли окна и / или потока большого пакета процессов / регистратора, не позволяющего консоли освободить место для текста. Текст для обновления

Я в большей степени Java-парень, поэтому, я думаю, мне следует периодически выдавать поток обработчика / регистратора, чтобы позволить потоку графического интерфейса пользователя запускать updateConsoleFromQueue, но не понимает, как это сделать в Python .. .

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