Python 从单独的类配置tkinter对象
我有一个简单的程序,有两个类,一个通过串行连接控制继电器板。另一个类用于GUI,它将向继电器类发送命令,然后显示继电器板的状态 我在从中继类向tkinter类发送消息时遇到问题。这些消息仅在中继命令完成后显示。我已经把我的程序删减到下面。Test.Test()表示中继类中的一个函数,其中作为主窗口类的函数是我的GUI 已指出用于处理类之间传递的消息。这是我唯一的选择吗?我还没有深入研究线程Python 从单独的类配置tkinter对象,python,python-2.7,tkinter,tk,tkinter-canvas,Python,Python 2.7,Tkinter,Tk,Tkinter Canvas,我有一个简单的程序,有两个类,一个通过串行连接控制继电器板。另一个类用于GUI,它将向继电器类发送命令,然后显示继电器板的状态 我在从中继类向tkinter类发送消息时遇到问题。这些消息仅在中继命令完成后显示。我已经把我的程序删减到下面。Test.Test()表示中继类中的一个函数,其中作为主窗口类的函数是我的GUI 已指出用于处理类之间传递的消息。这是我唯一的选择吗?我还没有深入研究线程 from Tkinter import * import time import ScrolledText
from Tkinter import *
import time
import ScrolledText
class Test():
def test(self):
main.textboxupdate(" test start ")
time.sleep(2)
main.textboxupdate(" test middle ")
time.sleep(2)
main.textboxupdate(" test end ")
class MainWindow(Frame):
def __init__(self, *args, **kwargs):
Frame.__init__(self, *args, **kwargs)
self.canvas = Canvas(width=1200,height=700)
self.canvas.pack(expand=YES,fill=BOTH)
self.frame = Frame(self.canvas)
self.TextBox = ScrolledText.ScrolledText(self.frame)
self.open = Button(self.frame, text="Open Cover",
command=test.test)
def createtextbox(self, statusmsg):
self.frame.place(x=0,y=0)
self.TextBox.config(state = NORMAL)
self.TextBox.insert(END, statusmsg,('error'))
self.TextBox.config(state = 'disabled', height = 2, width = 35)
self.TextBox.see(END)
self.TextBox.grid(columnspan=2, rowspan = 1)
self.open.grid()
def textboxupdate(self, statusmsg):
statusmsg = statusmsg +'\n'
self.TextBox.config(state = NORMAL)
self.TextBox.insert(END, statusmsg,('error'))
self.TextBox.config(state = 'disabled', height = 10, width = 50)
self.TextBox.see(END)
test = Test()
root = Tk()
main = MainWindow(root)
main.createtextbox('Startup\n')
root.mainloop()
这里有一个选择:
from Tkinter import *
import time
import ScrolledText
import threading, Queue
class Test():
def __init__(self):
self.msg_queue = Queue.Queue()
def test(self):
self.msg_queue.put(" test start ")
time.sleep(2)
self.msg_queue.put(" test middle ")
time.sleep(2)
self.msg_queue.put(" test end ")
class MainWindow(Frame):
def __init__(self, *args, **kwargs):
Frame.__init__(self, *args, **kwargs)
self.canvas = Canvas(width=1200,height=700)
self.canvas.pack(expand=YES,fill=BOTH)
self.frame = Frame(self.canvas)
self.TextBox = ScrolledText.ScrolledText(self.frame)
self.open = Button(self.frame, text="Open Cover",
command=self.create_thread)
self.test_thread = None
self.createtextbox("")
def create_thread(self):
self.test_thread = threading.Thread(target=test.test)
self.test_thread.start()
self.after(10, self.update_textbox)
def update_textbox(self):
while not test.msg_queue.empty():
self.textboxupdate(test.msg_queue.get())
if self.test_thread.is_alive():
self.after(10, self.update_textbox)
else:
self.test_thread = None
def createtextbox(self, statusmsg):
self.frame.place(x=0,y=0)
self.TextBox.config(state = NORMAL)
self.TextBox.insert(END, statusmsg,('error'))
self.TextBox.config(state = 'disabled', height = 2, width = 35)
self.TextBox.see(END)
self.TextBox.grid(columnspan=2, rowspan = 1)
self.open.grid()
def textboxupdate(self, statusmsg):
statusmsg = statusmsg +'\n'
self.TextBox.config(state = NORMAL)
self.TextBox.insert(END, statusmsg,('error'))
self.TextBox.config(state = 'disabled', height = 10, width = 50)
self.TextBox.see(END)
self.update_idletasks()
test = Test()
main = MainWindow()
main.pack()
main.mainloop()
第一个变化是,
Test.Test
将消息放入队列,而不是调用函数<代码>测试。测试通过main窗口在单独的线程中启动。启动线程
Main Window.start\u thread
还通过要求tkinter在10毫秒后调用update\u textbox
(self.after(10,self.update\u textbox)
)来安排对线程的检查。此函数用于将所有新消息从队列中移除并显示它们。然后,如果线程仍在运行,它会重新调度自己,否则它会重置主窗口
,所以一位朋友刚刚为我解决了这个问题。我需要在main window.textboxupdate()函数的末尾使用self.update\u idletasks()。这不是修复方法,这是一种解决方法。在gui中调用sleep
从根本上讲是有缺陷的。