【问题标题】:configure tkinter object from separate class从单独的类配置 tkinter 对象
【发布时间】:2015-04-09 14:01:44
【问题描述】:

我有一个包含两个类的简单程序,一个通过 serial.serial 连接控制继电器板。另一个类是一个 GUI,它将向继电器类发送命令,然后显示继电器板的状态。

我在将消息从中继类发送到 tkinter 类时遇到问题。消息仅在中继命令完成后出现。我在下面减少了我的程序。 Test.test() 代表我的中继类中的一个函数,其中 MainWindow 类是我的 GUI。

Someone 指出使用threading 来处理在类之间传递的消息。那是我唯一的选择吗?我还没有深入研究线程。

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

【问题讨论】:

  • 所以一位朋友刚刚为我解决了这个问题。我在 MainWindow.textboxupdate() 函数的末尾需要 self.update_idletasks()。
  • 这不是解决方法,而是解决方法。在 gui 中调用 sleep 存在根本缺陷。

标签: python python-2.7 tkinter tk tkinter-canvas


【解决方案1】:

这是一种选择:

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 不是调用函数,而是将消息放入队列。 Test.testMainWindow.start_thread 在单独的线程中启动。 MainWindow.start_thread 还通过要求 tkinter 在 10 毫秒 (self.after(10, self.update_textbox)) 后调用 update_textbox 来安排对线程的检查。此函数将所有新消息从队列中取出,并显示它们。然后,如果线程仍在运行,它会重新调度自己,否则会重置MainWindow

【讨论】:

    猜你喜欢
    • 2011-09-11
    • 2011-06-04
    • 1970-01-01
    • 2017-04-20
    • 2015-11-17
    • 2014-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多