Skip to main content
 首页 » 编程设计

python之通过另一个过程更新 tkinter gui 中的 matplotlib 图

2025年05月04日28lyj

我有一个使用 tkinter 编写的界面。在该界面内,我有一个 matplotlib 图。在后台,我让 zmq 连接到服务器以获取数据。我正在使用 python 的多处理模块,其中有一个队列共享数据和一个为所有 zmq 通信运行的进程。

在 GUI 中,我可以设置一个按钮来使用以下函数更新绘图:

def addData(self): 
    if not self.data.empty(): 
        print "Have Data!" 
        self.hist.addQueue(self.data) 
        self.hist.updatePlot() 
    else: 
        print "No Data" 

但是,如果我尝试创建另一个基本上将其放入 while True 中的进程,我会收到以下错误:

X Error of failed request:  RenderBadPicture (invalid Picture parameter) 
  Major opcode of failed request:  139 (RENDER) 
  Minor opcode of failed request:  7 (RenderFreePicture) 
  Picture id in failed request: 0x160000a 
  Serial number of failed request:  2686 
  Current serial number in output stream:  2690 
[xcb] Unknown sequence number while processing queue 
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called 
[xcb] Aborting, sorry about that. 
python: ../../src/xcb_io.c:274: poll_for_event: Assertion `!xcb_xlib_threads_sequence_lost' failed. 
fish: Job 1, “python clientGUI.py ” terminated by signal SIGABRT (Abort) 

我找不到关于此错误的任何信息,似乎与我正在做的任何事情有关。

如果需要,我可以提供我的代码的其他部分,但有很多代码我不想用它来淹没这个问题。

请您参考如下方法:

Excuse me for not following your post-mortem trails


第 0 步:(重新)调整组件的概念

座右铭:虽然调试错误导向的架构是可能的,但与更好、更直接的设计相比,由此产生的效率相当低

Component Inventory:

Tkinter 是一个非常智能的框架,围绕 .mainloop() (中央调度程序)工作,并允许软实时调度其他任务/包括。消息代理池的计划/预定查询。

Queue 是一种中介服务,它在一个端点上接收任何消息并将(所有 此类消息)传送到相对端点。由于所有消息到接收点的非托管无上下文传递,基于队列的自动化对于具有软调度的分布式系统中的 GUI 刷新功能代理是不可行的。 (引用下面关于全状态 GraphModelAGENT 的评论,它更适合与 Tkinter.mainloop()

的协同集成任务

Process 允许运行单独的子进程并分配角色,不仅通过 Tkinter 任务(通过时间触发的 .mainloop() 和/或事件触发的回调在预定的时间段中调用)还要运行一个完全独立的 <<_aStateFullGraphAGENT_>> ,它有两个职责:

[a] 与 Tkinter 通信以与 Tkinter 的 SIGRTU_aRequestToUpdate

同步更新

+

[b] 与“服务器”通信以更新 AGENT 的内部 GUI-ModelPART(无需向任何第三方推送,通过 FIFO-Queue(过载)加载 GUI-VisualPART 的次数越少(GUI-VisualPART 不必处理和重新绘制 GUI 模型的所有“过去”状态,而是成为一个轻量级的 Repaint-On-Demand 进程,只处理最近的状态图(已经组装并连续(来自 Tkinter 的异步...)在 aStateFullGraphAGENT 中维护)


第 1 步:解决方法

-- avoid FIFO-Queue that has to deliver all "GUI-states", that 've become obsolete

++ add aStateFullGraphAGENT to maintain the "recent" GUI-state

++ use ZeroMQ intelligent process-to-process messaging layer without any inter-thread blocking

ZeroMQ 相关的消息传递开销是微秒级的,这不会对任何 Repaint-On-DemandGUI 相关操作产生不利影响,因此安排 Tkinter 刷新率有很大的自由度,是它是 .mainloop() - 计划的或事件驱动的。

引用:>>> https://stackoverflow.com/a/25769600/3666197


第 2 步:验证/调整 GUI 重绘延迟/开销的可行性

引用:项目 2 中的处理时间 >>> https://stackoverflow.com/a/25530099/3666197