【问题标题】:Display log lines on screen using parallel GUI使用并行 GUI 在屏幕上显示日志行
【发布时间】:2017-09-29 08:35:48
【问题描述】:

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

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 冻结)

【问题讨论】:

  • 您的意思是要同时打开 2 个窗口?忘记线程,只需使用tk.Toplevel 来制作第二个窗口。

标签: python python-3.x tkinter spyder


【解决方案1】:

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)

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

【讨论】:

  • 感谢您的回答,但您的脚本不起作用(在我的计算机上)。您不能制作 'Wait.txt.set(...)' 如果将其更改为 'Wait.txt = 'Log line %s' % t' 它不会更新,最后也不要关闭小部件.
  • 我测试了它,它对我有用。它会给你一个错误信息吗?如果您想更改语法以使用 Wait.txt = 'Log line %s' % t',您将需要创建一个属性设置器。
  • 第一次使用 Spyder+IPython 时,第二次运行时报错:RuntimeError: main thread is not in main loop
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-13
  • 2013-12-13
  • 1970-01-01
  • 1970-01-01
  • 2021-04-20
  • 2011-09-02
  • 2019-08-08
相关资源
最近更新 更多