问题
I have an interface that I am writing using tkinter. Inside that interface, I have a matplotlib plot. In the background, I have zmq connecting to a server to get data. I am using python's multiprocessing module with a Queue sharing data and a Process running for all of the zmq communication.
In the GUI, I can set up a button to update the plot with the following function:
def addData(self):
if not self.data.empty():
print "Have Data!"
self.hist.addQueue(self.data)
self.hist.updatePlot()
else:
print "No Data"
However, if I try to create another process that basically puts this inside of a while True
, I get the following error:
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)
I can't find anything about this error that seems to be related to anything that I'm doing.
I can provide other parts of my code if needed, but there's a good bit of code that I didn't want to floood the question with.
回答1:
Excuse me for not following your post-mortem trails
STEP 0: (re)-align the concept of components
motto: while debugging a mis-directed architecture is possible, the resulting efficiency is rather low compared to a better and a more straightforward design
Component Inventory:
Tkinter
is a very smart framework that works around .mainloop()
( a central scheduler ) and allows for a soft-real-time scheduling of additional tasks / incl. a planned/scheduled querying of a pool of messaging agents.
Queue
is a mediator-service that on one endpoint receives any message(s) and delivers (all of such messages ) to the opposite endpoint. Due to the unmanaged context-less delivery of all messages to the receiving point, the Queue-based automation is not feasible for the GUI-refresh functionality agent in a distributed system with soft-scheduling. ( ref. remarks below on a state-full-GraphModelAGENT, that is better equipped for the task of co-integration with Tkinter.mainloop()
Process
allow to run separate sub-processes and distribute roles not only via Tkinter tasks ( called in pre-scribed time slots via time-triggered .mainloop()
and/or event-triggered callback(s) ) but also to run a fully self-contained <<_aStateFullGraphAGENT_>>
, that will have two responsibilities:
[a] communicate with Tkinter to update in-sync with Tkinter's SIGRTU_aRequestToUpdate
+
[b] communicate with "server" to update AGENT's internal GUI-ModelPART ( without any push thereof to any third-party, the less to (over)load the GUI-VisualPART via a FIFO-Queue
( GUI-VisualPART does not have to suffer from having to handle and repaint all the "past" states of the GUI-Model, but becomes a lightweight Repaint-On-Demand
process, dealing with just the most recent state of the graph ( already assembled and continuously ( async from Tkinter ... ) maintained in aStateFullGraphAGENT
)
STEP 1: Solution approach
-- 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-associated messaging overhead is in the order of microseconds, which does not adversely impact any Repaint-On-Demand
GUI-related operations, so there is a lot of freedom to arrange the Tkinter refresh-rate, be it the .mainloop()
-scheduled or event-driven.
Ref.: >>> https://stackoverflow.com/a/25769600/3666197
STEP 2: Validate / adjust feasibility of GUI-repaint latency / overheads
Ref.: Processing times in Item 2 >>> https://stackoverflow.com/a/25530099/3666197
来源:https://stackoverflow.com/questions/27893905/updating-matplotlib-plot-in-tkinter-gui-via-another-process