【问题标题】:How to thread with tkinter in python3 using queue?如何使用队列在python3中使用tkinter线程?
【发布时间】:2026-01-26 20:40:02
【问题描述】:

我正在尝试使用专门在 python3 中的队列在 tkinter 中对定义进行线程化

我在 python2 中有类似的代码,在没有队列的情况下使用类似的方法工作得很好,但在 python3 中,从我读过的内容来看,tkinter 不允许使用 gui 进行多线程。我发现了一些使用队列过程的例子。他们概述了我想创建一个队列对象,一个可以访问该队列的新线程并检查主线程中的输入

#!/usr/bin/python3

from tkinter import *
import time
import threading
import queue
import subprocess

def temp_sensor(queue_list):
    warning = 0
    while True:
        var = "cat /sys/class/thermal/thermal_zone*/temp"
        temp_control = subprocess.check_output([var], shell=True)
        temp_length = len(temp_control)
        temp_control = temp_control[35:]
        temp_control = temp_control[:-4]
        temp_control = int(temp_control)
        degree_sign= u'\N{DEGREE SIGN}'
        displayed_temp = "Tempature: " + str(temp_control) + degree_sign + "C"

        if temp_control > 79:
            warning = warning + 1
            if warning == 3:
                print ("Warning Core Tempature HOT!")
                warning = 0

        if temp_control > 90:
                time.sleep(3)
                print ("Warning EXTREMLY to HOT!!!")

        queue_list.put(displayed_temp)            
        time.sleep(1)

class Gui(object):
    def __init__(self, queue_list):
        self.queue_list = queue_list
        self.root = Tk()
        self.root.geometry("485x100+750+475")
        main_tempature_status = StringVar(self.root)

        Ts = Entry(self.root, textvariable=main_tempature_status)
        Ts.pack()
        Ts.place(x=331, y=70, width=160, height=25)
        Ts.config(state=DISABLED, disabledforeground="Black")

        self.root.after(1000, self.read_queue)

    def read_queue(self):
        try:
            temp = self.queue.get_nowait()
            self.main_tempature_status.set(temp)
        except queue_list.Empty:
            pass

        self.root.after(1000, self.read_queue)

if __name__ == "__main__":
    queue_list = queue.Queue()

    gui = Gui(queue_list)
    t1 = threading.Thread(target=temp_sensor, args=(queue_list,))
    t1.start()

    gui.root.mainloop()

我想要的结果是运行其中一些定义来执行各种任务并使用 python3 在 tkinter 条目中显示它们的变量。 当我运行我的代码时,它会给我队列中的变量,但它不会发布到 GUI。请原谅我的 Python 代码。

【问题讨论】:

  • 尝试将gui.root.mainloop 更改为gui.root.mainloop()
  • 很好,谢谢你的 gui 现在加载了。但是有了这个改变和我自己的 def read_queue(self):.. 我通过队列获取变量,但我现在可以让它发布到 gui
  • Gui.__init__() 中将 main_tempature_status 更改为 self.main_tempature_status。还要在Gui.read_queue() 中将self.queue.get_nowait() 更改为self.queue_list.get_nowait()queue_list.Emptyqueue.Empty

标签: python-3.x multithreading tkinter queue


【解决方案1】:

把你的Gui类改成这个:

class Gui(object):
    def __init__(self, queue_list):
        self.queue_list = queue_list
        self.root = Tk()
        self.root.geometry("485x100+750+475")
        self.main_tempature_status = StringVar(self.root)

        self.Ts = Entry(self.root, textvariable=self.main_tempature_status)
        self.Ts.pack()
        self.Ts.place(x=331, y=70, width=160, height=25)
        self.Ts.config(state=DISABLED, disabledforeground="Black")

        self.root.after(1000, self.read_queue)

    def read_queue(self):
        try:
            temp = self.queue_list.get_nowait()
            self.Ts.config(state=NORMAL)
            self.main_tempature_status.set(temp)
            self.Ts.config(state=DISABLED)
        except queue.Empty:
            pass

        self.root.after(1000, self.read_queue)

解释

  1. 变量main_temperature_status在函数read_queue中用作类变量,但未定义为类变量。
  2. 如果 Entry 小部件始终处于禁用状态,您将无法显示其值的变化,因此请在 read_queue 的值变化之前启用它。

【讨论】:

  • 感谢您的解释并帮助代码按预期工作。非常感谢。