Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python中执行线程期间更新Tkinter标签_Python_Multithreading_Tkinter_Label - Fatal编程技术网

在Python中执行线程期间更新Tkinter标签

在Python中执行线程期间更新Tkinter标签,python,multithreading,tkinter,label,Python,Multithreading,Tkinter,Label,我目前正在尝试编程一个由树莓Pi控制的机器人手臂 到目前为止,一切正常,除了一件事,我已经在谷歌上搜索并尝试了好几个小时,但找不到有效的解决方案 对于机械臂的移动,有必要使用螺纹“同时”运行所有电机(工作正常) 我遇到的问题是,我需要更新一个标签,该标签显示轴(电机)在完成移动后的当前角度,但其他电机仍在运行(螺纹) 经过大量研究,我认为我通过使用队列和Tkinters After方法找到了解决方案。但它仍然不起作用,因为标签文本只有在所有线程终止后才会更新 我编写了一个示例代码,其中我希望获得

我目前正在尝试编程一个由树莓Pi控制的机器人手臂

到目前为止,一切正常,除了一件事,我已经在谷歌上搜索并尝试了好几个小时,但找不到有效的解决方案

对于机械臂的移动,有必要使用螺纹“同时”运行所有电机(工作正常)

我遇到的问题是,我需要更新一个标签,该标签显示轴(电机)在完成移动后的当前角度,但其他电机仍在运行(螺纹)

经过大量研究,我认为我通过使用队列和Tkinters After方法找到了解决方案。但它仍然不起作用,因为标签文本只有在所有线程终止后才会更新

我编写了一个示例代码,其中我希望获得马达“一”的标签更新,它将在马达“二”(500次迭代)之前完成for循环(100次迭代)。我希望在二号发动机仍在运行时,一号发动机一达到目标,标签就会更新

但是,尽管我使用了after方法,它仍然要等到马达2完成后才能更新标签

希望你能帮助我

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


class StepperMotors:

    def __init__(self, root):
        self.root = root

        self.start_btn = Button(root, text="Start", command=lambda:self.start_movement())
        self.start_btn.config(width = 10)
        self.start_btn.grid(row=1,column=1)

        self.label_one = Label(root, text='')
        self.label_one.config(width = 10)
        self.label_one.grid(row=2, column=1)

        self.label_two = Label(root, text='')
        self.label_two.config(width = 10)
        self.label_two.grid(row=3, column=1)

    def start_movement(self):
        self.thread_queue = Queue()
        self.root.after(100, self.wait_for_finish) 

        thread_one = threading.Thread(target=self.motor_actuation, args=(1,100))
        thread_two = threading.Thread(target=self.motor_actuation, args=(2,500))

        thread_one.start()
        thread_two.start()

        thread_one.join()
        thread_two.join()

    def motor_actuation(self, motor, iterations):  
        for i in range(iterations):
            i = i+1  
            update_text = str(motor) + " " + str(i) + "\n"
            print(update_text)
            time.sleep(0.01)

        self.thread_queue.put(update_text)

    def wait_for_finish(self):
        try:      
            self.text = self.thread_queue.get()  
            self.label_one.config(text=self.text)  

        except self.thread_queue.empty():
            self.root.after(100, self.wait_for_finish)

if __name__ == "__main__":
    root = Tk()
    root.title("test")
    stepper = StepperMotors(root)
    root.mainloop()

最好使用非阻塞的守护进程线程

另外,最好有一个:机器人(或机器人手臂)可以是一个有自己生命周期的对象:守护进程线程。您可以定义一个“LabelUpdater”,用于读取机器人的状态并更新标签

让我们定义一个机器人:

  • 它在应用程序初始化时创建,并在用户单击“开始”按钮时运行
  • 机器人在应用程序级多线程队列中移动并报告其角度
类机器人(threading.Thread):
def uuu init uuuu(self,name:str,label_queue:queue.queue,end_pos:int):
super()
self.daemon=True
self.label\u queue=label\u queue
self.end\u pos=end\u pos
def运行(自)->无:
对于范围内的角度(自结束位置):
self.label_queue.put(角度)
睡眠时间(0.01)
让我们定义一个LabelUpdater:

  • 它是在应用程序初始化时创建的,并且永远运行(它可以观察机器人,即使它没有运行)
  • 它读取机器人队列(例如,每秒读取一次以避免闪烁)并更新标签
class LabelUpdater(threading.Thread):
def_uuuinit_uuuu(self,name:str,label_queue:queue.queue,root_app:tkinter.Tk,变量:tkinter.variable):
super()
self.daemon=True
self.label\u queue=label\u queue
self.root\u app=root\u app
self.variable=变量
def运行(自)->无:
#长跑
尽管如此:
#请稍等
时间。睡眠(1)
#使用所有队列并仅保留最后一条消息
最后消息=无
尽管如此:
尝试:
msg=self.label\u queue.get(block=False)
队列除外。空:
打破
last_msg=msg
self.label\u queue.task\u done()
如果最后一个消息:
self.variable.set(最后一个消息)
然后,主应用程序应定义:

  • 2个多线程队列:每个标签一个
  • 2
    tkinter.StringVar
    将被更新的变量
  • 机器人和标签更新程序
  • 这两个更新程序将启动,并将永远运行
类步进电机:
定义初始化(自,根):
self.root=根
self.label\u one\u queue=queue.queue()
self.label\u two\u queue=queue.queue()
self.start\u btn=tkinter.Button(root,text=“start”,command=lambda:self.start\u movement())
self.start\u btn.config(宽度=10)
自启动网格(行=1,列=1)
self.text_one=tkinter.StringVar()
self.text_one.set(“一个”)
self.label\u one=tkinter.label(根,textvariable=self.text\u one)
self.label\u one.config(宽度=10)
self.label\u one.grid(行=2,列=1)
self.text_two=tkinter.StringVar()
self.text_two.set(“两个”)
self.label\u two=tkinter.label(根,textvariable=self.text\u two)
self.label_two.config(宽度=10)
self.label\u two.grid(行=3,列=1)
self.robot\u one=机器人(“robot\u one”,self.label\u one\u队列,100)
self.robot\u two=机器人(“robot\u two”,self.label\u two\u队列,500)
self.updater\u one=LabelUpdater(“updater\u one”、self.label\u one\u队列、self.root、self.text\u one)
self.updater\u two=LabelUpdater(“updater\u two”,self.label\u two\u队列,self.root,self.text\u two)
self.updater_one.start()
self.updater_two.start()
def启动_移动(自):
self.robot_one.start()
self.robot_two.start()

当然,您需要一个标志或一些东西来检查每个robot是否还没有运行。

最好使用非阻塞的守护进程线程

另外,最好有一个:机器人(或机器人手臂)可以是一个有自己生命周期的对象:守护进程线程。您可以定义一个“LabelUpdater”,用于读取机器人的状态并更新标签

让我们定义一个机器人:

  • 它在应用程序初始化时创建,并在用户单击“开始”按钮时运行
  • 机器人在应用程序级多线程队列中移动并报告其角度
类机器人(threading.Thread):
def uuu init uuuu(self,name:str,label_queue:queue.queue,end_pos:int):
super()
self.daemon=True
self.label\u queue=label\u queue
self.end\u pos=end\u pos
def运行(自)->无:
对于范围内的角度(自结束位置):
self.label_queue.put(角度)
睡眠时间(0.01)
让我们定义一个LabelUpdater:

  • 它在应用程序初始化时创建并永远运行(它可以