简体   繁体   中英

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

I am making a GUI for visualizing a SLURM queue on a supercomputer. I would like to continuously monitor the number of running and pending jobs in the queue by sending commands over ssh (with paramiko) regularly to fetch the queue, analyze it, and update some tk variables connected with tk labels.

I have been up until now been using the self.after() syntax for doing this, and making sure not to make background SSH calls too often (so as to not lead to annoying freezes in the interface). However, I am rewriting my code and I would like to monitor several other aspects as well, but this slows down the interface too much.

I think this can be solved by using the threading module, but I am unsure how to set it up properly. For the sake of this question, consider the following 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()

It just keeps track of the changing IntVar s connected to some labels, with a sleep statement to simulate the SSH call. The way it is set up now, the GUI does not show up despite the counters being updated.

How can I modify the program above to spawn the monitoring functions as their own threads? Assume the monitoring should always be active, and that the user cannot deactivate them without exiting the program. Also, the threads should of course be terminated when root.destroy() is called when exiting the program.

Below is updated code based on yours using threads:

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()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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