python-3.x 如何在button命令之外启动一个线程?

jc3wubiy  于 2023-05-19  发布在  Python
关注(0)|答案(1)|浏览(109)

我用Tkinter做了一个简单的GUI来订阅和接收来自mqtt代理的消息。我自己写的,因为一些消息解压缩问题,应该没关系。问题是,当我连接并订阅一个主题时,客户端需要保持运行,所以我在一个线程中运行它,以避免冻结GUI。但是因为线程一直在运行,所以我不能重新运行订阅操作。
如果你尝试一次,它就可以正常工作(请注意,它最初是在一个类中,但我只尝试发布相关的方法):

def main_window(self):
        self.root.title("MQTT Subscriber Test")
        self.root.geometry("350x150")

        # Topic subscription
        title = tk.Label(self.root, text="Enter topic to subscribe:")
        title.pack(**self.padding, anchor=tk.W)

        topic_entry = tk.Entry(self.root, textvariable=self.topic)
        self.root.update()
        topic_entry.pack(**self.padding, **self.ipadding, anchor=tk.W, fill=tk.X)

        # subscribe button
        subscribe_button = tk.Button(self.root, text="Connect", 
                                     command=threading.Thread(target=self.subscribe_to_topic).start)
        subscribe_button.pack(**self.padding, anchor=tk.W)

    def subscribe_to_topic(self):
        # ToDo: better condition for unsubscribe action
        if self.subbed_topic != "":
            self.client.unsubscribe_from_topic(self.subbed_topic)
            self.client.disconnect_from_broker()
        self.subbed_topic = self.get_topic
        self.open_output_window()
        self.client.operate(self.subbed_topic)

main_window()设置接口,按下订阅按钮时调用subscribe_to_topic()
这一次运行正常,但我不能重新按下按钮,我得到错误:
RuntimeError: threads can only be started once
所以我试着将线程的启动切换到方法本身,如下所示:

def main_window(self):
        self.root.title("MQTT Subscriber Test")
        self.root.geometry("350x150")

        # Topic subscription
        title = tk.Label(self.root, text="Enter topic to subscribe:")
        title.pack(**self.padding, anchor=tk.W)

        topic_entry = tk.Entry(self.root, textvariable=self.topic)
        self.root.update()
        topic_entry.pack(**self.padding, **self.ipadding, anchor=tk.W, fill=tk.X)

        # subscribe button
        subscribe_button = tk.Button(self.root, text="Connect", 
                                     command=self.subscribe_to_topic))
        subscribe_button.pack(**self.padding, anchor=tk.W)

    def subscribe_to_topic(self):
        # ToDo: better condition for unsubscribe action
        if self.subbed_topic != "":
            self.client.unsubscribe_from_topic(self.subbed_topic)
            self.client.disconnect_from_broker()
        self.subbed_topic = self.get_topic
        self.open_output_window()
        threading.Thread(target=self.client.operate(self.subbed_topic).start()

但这会再次冻结GUI。从这一点上,我找不到任何其他线程来解决我的问题。

uoifb46i

uoifb46i1#

我注意到的一件事是,您正在调用函数,而不是将函数传递给线程。
在本例中,该函数被调用target=self.client.operate(self.subbed_topic),但没有传递给线程
试着像这样重构最后一行,然后再试一次?

threading.Thread(target=self.client.operate, args=(self.subbed_topic,)).start()

相关问题