使用并行GUI在屏幕上显示日志行

时间:2017-05-01 22:24:51

标签: python python-3.x tkinter spyder

我正在寻找在脚本运行时在屏幕上显示日志行的优雅方式。

from time import sleep
from threading import Thread
import tkinter as tk


class WaitGuiPrallel(Thread):
    def __init__(self, TXT='Wait!', ttl='Logs'):
        self.txt = TXT
        Thread.__init__(self)
        self.ttl = ttl
        self.start()  # This is starting the self.run()

    def run(self):
        self.root = tk.Tk()
        self.root.attributes("-topmost", True)
        self.root.title(self.ttl)
        self.label = tk.Label(self.root, text=self.txt, font=("Helvetica", 20))
        self.label.pack()
        self.Location()
        self.root.mainloop()

    def Exit(self):
        self.root.quit()

    def Location(self):
        w = 500  # width for the Tk root
        h = 150  # height for the Tk root
        ws = self.root.winfo_screenwidth()  # width of the screen
        self.root.geometry('%dx%d+%d+%d' % (w, h, ws - w - 20, 10))

    def Update(self, newText):
        self.txt1 = newText
        self.label.destroy()
        self.label = tk.Label(self.root, text=self.txt1,
                              font=("Helvetica", 12))
        self.label.pack()
        self.root.update()

Wait = WaitGuiPrallel(TXT='Wait! Do not touch mouse or keyboard')
sleep(2)
for t in range(5):
    sleep(1)
    Wait.Update(newText='Log line %s' % t)
Wait.Update(newText='Done!')
sleep(1)
Wait.Exit()

目前的脚本几乎没有问题:

  1. 它不优雅 - 必须有更好的方式

  2. 从不同的主题更新时出现问题

  3. 有时从Spyder + IPython运行两次是不可能的(IPython冻结)

1 个答案:

答案 0 :(得分:0)

Tkinter在线程方面表现不佳。使用StringVar比其他方法(根据我的经验)更加线程友好。以下是如何做到这一点以及其他一些修复:

from time import sleep
from threading import Thread
import tkinter as tk

class WaitGuiPrallel(Thread):
    def __init__(self, TXT='Wait!', ttl='Logs'):
        Thread.__init__(self)
        self.txt = TXT
        self.ttl = ttl # what's this for?
        self.daemon = True # this thread will terminate when the main thread terminates
        self.start()  # This is starting the self.run()

    def run(self):
        self.root = tk.Tk()
        self.root.attributes("-topmost", True)
        self.root.title(self.ttl)
        self.txt = tk.StringVar(value=self.txt)
        self.label = tk.Label(self.root, textvariable=self.txt, font=("Helvetica", 20))
        self.label.pack()
        self.Location()
        self.root.mainloop()

    def Location(self):
        w = 500  # width for the Tk root
        h = 150  # height for the Tk root
        ws = self.root.winfo_screenwidth()  # width of the screen
        self.root.geometry('%dx%d+%d+%d' % (w, h, ws - w - 20, 10))

Wait = WaitGuiPrallel(TXT='Wait! Do not touch mouse or keyboard')
sleep(2)
for t in range(5):
    sleep(1)
    Wait.txt.set('Log line %s' % t)
Wait.txt.set('Done!')
sleep(1)

如果你有多个线程调用它,那么我会考虑使用Queue和第三个线程来监视队列。