繁体   English   中英

Tkinter:如何使用多线程在后台保持监控 function 处于活动状态

[英]Tkinter: How use multithreading to keep a monitoring function active in the background

我正在制作一个用于在超级计算机上可视化 SLURM 队列的 GUI。 我想通过定期通过 ssh(使用 paramiko)发送命令来持续监控队列中正在运行和挂起的作业的数量,以获取队列、分析它并更新一些与 tk 标签相关的 tk 变量。

到目前为止,我一直在使用self.after()语法来执行此操作,并确保不要过于频繁地进行后台 SSH 调用(以免导致界面中令人讨厌的冻结)。 但是,我正在重写我的代码,并且我还想监控其他几个方面,但这会大大降低界面速度。

我认为这可以通过使用threading模块来解决,但我不确定如何正确设置它。 对于这个问题,请考虑以下 MWE:

import tkinter as tk


class GUI(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)

        Home(self)


class Home(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        self.parent = parent
        self.counter = tk.IntVar()
        self.counter2 = tk.IntVar()
        self.grid(row=0, column=0)

        tk.Label(self, text='Counter 1:').grid(row=0, column=0)
        tk.Label(self, textvar=self.counter).grid(row=0, column=1)

        tk.Label(self, text='Counter 2:').grid(row=1, column=0)
        tk.Label(self, textvar=self.counter2).grid(row=1, column=1)

        self.monitor_counter()
        self.monitor_counter2()

    def monitor_counter(self, end=100, delay=1000):
        time.sleep(0.2)
        if self.counter.get() < 0:
            self.parent.destroy()
        self.counter.set(end)
        self.after(int(delay), lambda: self.monitor_counter(end-1))

    def monitor_counter2(self, start=0, delay=1000):
        time.sleep(0.2)
        self.counter2.set(start)
        self.after(int(delay), lambda: self.monitor_counter2(start+1))


if __name__ == '__main__':
    GUI().mainloop()

它只是跟踪连接到某些标签的变化的IntVar ,并使用 sleep 语句来模拟 SSH 调用。 按照现在的设置方式,尽管更新了计数器,但 GUI 不会显示。

如何修改上面的程序以将监控功能生成为自己的线程? 假设监控应该始终处于活动状态,并且用户无法在不退出程序的情况下停用它们。 此外,当退出程序时调用root.destroy()时,当然应该终止线程。

以下是基于您使用线程的更新代码:

import tkinter as tk
import time
import threading

class GUI(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        Home(self)

class Home(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        self.parent = parent
        self.counter = tk.IntVar()
        self.counter2 = tk.IntVar()
        self.grid(row=0, column=0)

        tk.Label(self, text='Counter 1:').grid(row=0, column=0)
        tk.Label(self, textvar=self.counter).grid(row=0, column=1)

        tk.Label(self, text='Counter 2:').grid(row=1, column=0)
        tk.Label(self, textvar=self.counter2).grid(row=1, column=1)

        # start the monitor tasks
        threading.Thread(target=self.monitor_counter, daemon=True).start()
        threading.Thread(target=self.monitor_counter2, daemon=True).start()

    def monitor_counter(self, end=100, delay=1):
        while True:
            time.sleep(0.2) # simulate SSH call
            if self.counter.get() < 0:
                self.parent.destroy()
            end -= 1
            self.counter.set(end)
            time.sleep(delay)

    def monitor_counter2(self, start=0, delay=1):
        while True:
            time.sleep(0.2) # simulate SSH call
            self.counter2.set(start)
            start += 1
            time.sleep(delay)

if __name__ == '__main__':
    GUI().mainloop()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM