2015-04-09 1 views
0

У меня есть простая программа с двумя классами, одна управляет релейной платой через serial.serial соединение. Другой класс предназначен для графического интерфейса, который будет отправлять команды классу реле, а затем отображать состояние платы реле.настроить объект tkinter из отдельного класса

У меня возникла проблема с отправкой сообщений из класса реле классу tkinter. Сообщения появляются только после завершения команды реле. Я сократил свою программу ниже. Test.test() представляет функцию в моем классе ретрансляции, где в качестве класса MainWindow используется мой графический интерфейс.

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

Так что друг просто решил это для меня. Мне нужно self.update_idletasks() в конце функции MainWindow.textboxupdate(). – Oman

+0

Это не исправление, это обходное решение. Вызов 'sleep' в gui в корне ошибочен. –

ответ

0

Вот один вариант:

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.test запускается в отдельной теме на MainWindow.start_thread. MainWindow.start_thread также планирует проверку потока, попросив tkinter позвонить update_textbox через 10 миллисекунд (self.after(10, self.update_textbox)). Эта функция выводит все новые сообщения из очереди и отображает их. Затем, если поток все еще запущен, он регрессирует сам, иначе он сбрасывает MainWindow.

Смежные вопросы