• 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏吧

tkinter画布颜色不变

python 来源:kar 4次浏览

我有一个两个tkinter画布,需要根据我从其他模块收到的数据更改颜色。基本上为0,1 例如:如果接收到1,则将canvas1设置为黑色,将canvas2设置为绿色,如果接收到0,则反之亦然。tkinter画布颜色不变

我已经使用多处理队列技术来接收数据,但是当我尝试应用更改时,它并未更新?我假设有self

这里是我的代码片段: main.py

import multiprocessing 
from udpsocket import * 
from ui import * 

if __name__ == "__main__": 
    queue = multiprocessing.Queue() 
    ui = multiprocessing.Process(target=uiMain, args=(queue,)) 

    ui.daemon = True 
    ui.start() 
    udpMain(queue) 

udpsocket.py:

import time 
import struct 
import socket 
import ui 

MYPORT = 51506 
MYGROUP_4 = '225.0.0.1' 
MYTTL = 1 # Increase to reach other networks 

def udpMain(queue): 
app = udpsocket(queue) 

class udpsocket(): 
    def __init__(self,queue): 
     print('UDP Socket started') 
     group = MYGROUP_4 
     self.receiver('225.0.0.1',queue) 

    def receiver(self,group,queue): 
     print('Receiver') 
     addrinfo = socket.getaddrinfo(group, None)[0] 

     # Create a socket 
     s = socket.socket(addrinfo[0], socket.SOCK_DGRAM) 
     #.... reuse address, binding, add membership 
     # loop, send data to ui 
       while True: 
     data, sender = s.recvfrom(1500) 
     while data[-1:] == '\0': data = data[:-1] # Strip trailing \0's 
     print (str(sender) + ' ' + str(ord(data))) 
     queue.put(ord(data)) 
     ui.do_something(queue) 

ui.py:

from tkinter import * 
from tkinter import ttk 
import multiprocessing 

def uiMain(queue): 
    app = MainWindow() 
    app.mainloop() 

class MainWindow(Frame): 
    def __init__(self): 
     Frame.__init__(self) 
     self.master.title("Test") 
     self.master.minsize(330, 400) 
     self.grid(sticky=E+W+N+S) 

     modeFrame = Frame(self) 
     modeFrame.pack(side="top", fill="x") 
     self.canvas1 = Canvas(modeFrame, height=25, width=25) 
     self.canvas1.create_oval(5, 5, 20, 20, fill="black", tags="SetupLight") 
     self.canvas1.pack(side="left") 

     self.canvas2 = Canvas(modeFrame, height=25, width=25) 
     self.canvas2.create_oval(5, 5, 20, 20, fill="black", tags="RunLight") 
     self.canvas2.pack(side="left") 

    def changeLight(self,value): 
     print('change light ' + str(value)) 
     if(value): 
      self.canvas1.itemconfig("SetupLight", fill="black") 
      self.canvas2.itemconfig("RunLight", fill="green") 
     else: 
      self.canvas1.itemconfig("SetupLight", fill="green") 
      self.canvas2.itemconfig("RunLight", fill="black") 

def do_something(queue): 
     t = MainWindow() 
     MainWindow.changeLight(t,queue.get()) #is this way of calling is correct?? 

注:我试图修改modeFrameself wh ile创建Canvas,但没有什么可能发生

我明白从下面的链接tkinter canvas not updating color我一次又一次地创建MainWindow(),这是帆布没有改变颜色的原因。我需要一个实现,它可以帮助我通过用例改变颜色


===========解决方案如下:

正如您已经提到过自己,您正在do_something中创建MainWindow类的实例。

其次,do_something函数调用对我来说有点奇怪。 我宁愿

def do_something(queue): 
    t = MainWindow() 
    t.changeLight(queue.get()) 

,如果这是一个更Python的方式或没有,但我认为,在几乎所有的教程,怎么对的和示例代码,你会看到它就像我提到这可能是值得商榷的。

上次我实现了这样的东西,我采取了不同的方法。

我从GUI启动了线程,向它传递了一个队列,让线程处理流量。

GUI更新了循环(每100ms)检查项目的队列,并基于它更新GUI中的队列内的内容。

每次更新完成后再次启动的线程。 (应用程序本身就是一个会话看门狗为包括线程内的用户的本地化服务器)

所以一些实施意见,我会开始像下面这样:

import Tkinter as tk 
import Queue 

class MainWindow(tk.Frame): 
    """ This is the GUI 
     It starts threads and updates the GUI 
     this is needed as tkinter GUI updates inside the Main Thread 
    """ 
    def __init__(self, *args, **kwargs): 
     # Here some initial action takes place 
     # ... 
     self.queue = Queue() 
     self.start_threads() 
     self.__running = True 
     self.update_gui() 

    def start_threads(self): 
     """ Here we start the threads 
      for ease of reading only one right now 
      thread_handler_class is a class performing 
      tasks and appending results to a queue 
     """ 
     thread = thread_handler_class(self.queue) 

    def update_gui(self): 
     """ Update the UI with Information from the queue """ 
     if not self.queue.empty(): 
      # we need to check for emptiness first 
      # otherwise we get exceptions if empty 
      while self.queue.qsize() > 0: 
       # handle the data 
       # self.queue.get() automatically reduces 
       # qsize return value next round so if no 
       # new elements are added to the queue, 
       # it will go to zero 
       data = self.queue.get() 
       # do stuff here 
       # ... 

     # Set up the cyclic task 
     if self.__running: 
      self.after(100, self.update_gui) 
      # if neccessary we can also restart the threads 
      # if they have a determined runtime 
      # self.after(100, self.start_threads)   

if __name__ == "__main__": 
    APP = MainWindow() 
    APP.mainloop() 

版权声明:本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系管理员进行删除。
喜欢 (0)