SOLVED: wx Correct way to alter GUI on the fly

  • Context: Python 
  • Thread starter Thread starter cpscdave
  • Start date Start date
  • Tags Tags
    Gui
Click For Summary

Discussion Overview

The discussion revolves around the challenges of dynamically altering a graphical user interface (GUI) in a program that pulls information from an RSS XML feed. Participants explore issues related to updating the GUI in response to changes in the feed, handling threading, and ensuring proper memory management.

Discussion Character

  • Technical explanation
  • Debate/contested
  • Exploratory

Main Points Raised

  • One participant describes the need to add and remove GUI elements based on RSS feed updates and mentions issues with missing information and program crashes on different operating systems.
  • Another participant suggests the possibility of a memory leak and recommends monitoring tools to diagnose the issue, as well as ensuring that connections and files are properly managed.
  • A different participant claims to have resolved their issues by switching from wx to PyQt, emphasizing the importance of updating the GUI only from the main GUI thread and triggering custom events from other threads.
  • Another suggestion involves using wx.CallAfter() to safely update the GUI from worker threads by calling a dedicated function for GUI changes.
  • One participant proposes a design pattern approach, suggesting the use of a single timer to manage RSS feed updates and caching data before updating the GUI.

Areas of Agreement / Disagreement

Participants express various approaches and solutions to the problem, but there is no consensus on a single method or resolution to the issues raised. Multiple competing views on how to manage GUI updates and threading remain present.

Contextual Notes

Participants mention potential limitations related to memory management, threading issues, and the specific frameworks being used (wx vs. PyQt), but these aspects remain unresolved.

cpscdave
Messages
402
Reaction score
120
Happy Monday folks!

I've been working on a program where I need to change the GUI on the fly. Specifically I need to do 2 things.
This program pulls information from an RSS xml feed and displays it.
As information is added (or removed) from the RSS feed I need to add or remove the information from the GUI. I have written this right now to add little panel objects (which contain a static text), and when they are removed I call object.destroy() on them.
Secondly I'd like to set it up to inform the user that new information is available in some manner. I have set this up now to change the taskbar icon of the program back and forth basically causing a flashing.

Both of these events are triggered using Threading.timers

Now the big issue. The program runs great for a random amount of time and then messes up in one way or another.
With dealing with the Panels eventually the program will have the correct number of panels, but some of them will be missing their information (the static text appears blank)

With the flashing on linux it eventually throws an xwindows error and crashes, on windows the program stops responding to any further inputs.

Both timers don't actually make the changes, they acquire a thread lock shared through the entire program, queue up an event and return.
The event when handled sets up the subsequent timer. Based on that this isn't working I'm guessing that I'm not doing this in a the correct manner (obviously) any suggestions on how I should be doing this or what might be going on with the program??

thanks :smile:
 
Technology news on Phys.org
My guess would be you have a memory leak somewhere. You could test this by using a process monitor like on top on linux or the windows monitor and see if that's what's happening.

Next, you'll have to see that any open connections or files are properly closed and not left dangling around.

One common mistake that programmers make is to create a database connection and to read in results and then keep the connection open while they do other things with the data like populate a gui list and then forget to close it.

Often the better approach is to open the connection, get all the data and place it in an array, close the connection (ie connection is opened for a minimal amount of time) and then iterate the array populating the gui. Even with a small amount of the data this is still better.

You mentioned that you have network connections with multi-threading and that may be where things are getting lost.

Here's a reference on python memory leaks:

http://pympler.readthedocs.io/en/latest/tutorials/muppy_tutorial.html

I saw during my search that some folks have issues with TKinter and its canvas component having memory leaks so you might want to check around.

http://stackoverflow.com/questions/13519811/what-is-causing-this-memory-leak-with-tkinter-canvas

mentions things about update loops and multiple threads being needlessly created.
 
Last edited:
  • Like
Likes   Reactions: cpscdave
Thanks for the response Jedishrfu

I think I solved it, ironically by trying to rewrite the dammed thing in PyQt instead of WX.

For anyone who stumbles on this in the future, what I've discovered is it is not safe to alter the GUI from any thread other than the actual GUI thread. I had been aware of this, but apparently the method I was using to ensure this wasn't actually working the way I intended.

What you need to do is have whatever thread that you want trigger an custom event that the gui thread has binded.

Fun 3 days chasing my tail on this one...
 
  • Like
Likes   Reactions: jedishrfu
It's been a while since I used wx, but something you might want to look into is wx.CallAfter(). (Specifically, I used wxPython - but I think this is a wx feature rather than wxPython specific). You write a function or method called (e.g.) changeGUI() and put all your Panel adding and destroying there. Then your "work" thread updates the data and calls wx.CallAfter(changeGUI), and the GUI thread calls your change function at its convenience.

I think you can have arguments if you want - changeGUI(x,y,z) would be called as wx.CallAfter(changeGUI,x,y,z).
 
You could use one timer to get RSS feeds then 1. store or cache them and 2. push them up to your GUI
After some time you only need to get the latest news then compare it with the cached value, renew the cache and update your GUI.
You may need to think of your software solution in terms of a design pattern, e.g MVC or the likes.
For example,
your Feeds and your cache = model
all your methods to get data from your model as well as to dispatch messages to or update your GUI = controller
and your GUI = view
 

Similar threads

  • · Replies 5 ·
Replies
5
Views
2K
  • · Replies 27 ·
Replies
27
Views
24K
Replies
2
Views
3K
  • · Replies 15 ·
Replies
15
Views
4K
  • · Replies 25 ·
Replies
25
Views
6K
  • · Replies 6 ·
Replies
6
Views
6K
  • · Replies 3 ·
Replies
3
Views
13K
  • · Replies 5 ·
Replies
5
Views
12K
  • · Replies 1 ·
Replies
1
Views
1K