Button events in poll mode?

Hi all,

1st time here so bear with me as I settle in :slight_smile: Also please cut me some slack as I am fairly new to (wx)Python.

My program is on a PC (and hopefully, eventually, to a tablet) and connects to external microp-based h/w thru a Bluetooth serial interface. The nature of the program is that I’m defining 7 or 8 main functions and a number of subfunctions (mainly configuration) with a subset defined for each main function.

Both the main functions and subfunctions are basically “infinite loops” (“while” statements) in that changing main functions and/or getting into/out of subfunctions will be done by button events. The problem is that if I use “while” and depend on button events for (sub)function switching, pressing a button does not seem to get serviced (i.e. generate an event to process).

I have the following code at the end of my main, defining/init class:

if name == ‘main’:
app = wx.App()
frame = FreqCntrWindow()
app.MainLoop()

FreqCntrWindow is my main class def. My sense is that wx.App is where the button events are acknowledged and directed to the callback function for processing. The problem is that’s not happening because of the catch-22 of my “while”-conditioned code never allowing wx.App to deal with any button events.

Is there a way I can “poll” for button events from within my code (define a function and return a Boolean and maybe a button name)? Or am I approaching this wrong.

Thanks in advance and appreciate any help or insight…cheers…

Hi,

From what you described, your application needs to use threads/processes. With Python, all threads run on the same processor core. If your want to use more than one core, you need to use processes. Using processes is more complicated since processes do not share memory. You have to use specific IPC to make processes talk together.
Thread library : https://docs.python.org/3/library/threading.html
Process library : https://docs.python.org/3/library/multiprocessing.html
Be careful with threads : The thread that creates the GUI is the only one that calls wxPython API. If other threads call wxPython API, you will think it works until your app behave abnormally or crashes. A working thread can interact with the GUI by calling wx.CallAfter().
I also recommend to use pyPubSub.
The above is useful when a working thread needs to update the GUI.
When the GUI needs to send command to working thread, you can use standard inter thread communication methods.

Nicolas

1 Like

Nicolas,

I really appreciate your informative response. I have a nephew who does Python programming for AWS, and when I presented this to him, he also mentioned about threading. Guess I have some more to learn.

So, other than threads (or processes…eeeek), there is no easy way to do this in Python, huh? OK. I love a challenge :slight_smile:

Thank you again for the help and for the links so I can find out how much trouble I will get myself into :wink:

Regards and…Cheers…

Hi,

Don’t be afraid by threads. Implementing threads is really easy with Python. You just have to take care of basic rules when dealing with threads.
You can read an introduction to threads here.

On the wxPython wiki, there is this example. Please notice the use of wx.CallAfter() that is used to update the GUI from the working thread.

Nicolas

1 Like

Nicolas,

I appreciate your encouragement and the additional links. I guess I’ll just have to see what kind of damage I can inflict on my code :slight_smile: At least I know where to go if I unfortunately reach that point…hopefully not.

Thanks again and cheers…Steph

If you can reorganize things to be able to work in an event-driven manner then that would be the best approach, at least for things in the user interface. Compared to non-GUI procedural programming this can sometimes seem a little inside-out but it works.

For those parts of your application that must run in a continuous loop or polling mode (like watching for input on a USB port or something) then using a thread for those is usually a good approach, and they can toss things over to the UI thread as needed using the wx.CallAfter function.

If your long-running task can be segmented into chunks, or be done in a periodic polling mode, then there are some other approaches for handling long-running tasks described here that may be a little simpler than threads, like using EVT_IDLE events or timers.

Appreciate the suggestion and additional link. Offers me more to consider.

I do have a number of “functions” that need to be run in a “while” or similar loop for my design to work. Essentially, these are long-running tasks in that they execute…typically until a button event occurs to change to a new event (main or subfunction) or exit a called subfunction and return to the function inside from where an event called the subfunction.

This Python part is essentially emulating a display and numerous buttons that were part of a h/w design where assembly code could poll the buttons consistently for a function change request. Doing this in a high-level language AND and having to communicate function change requests over a serial port has certainly changed the way I look at implementing the system.

Always appreciate new challenges :slight_smile:

Thanks again for the help…cheers and regards…

I’ve been reading abt threads and they look like they would work. I’ll have to do some coding and see how well.

I also came across something called Async IO which seems to serve a function similar to threading. Any input on why that would be better, or worse, than threads?

@Robin

I just jumped into a thread ([WxPython Install Issue on MacOS 10.14 with pyenv and python 3.8.0](http://WxPython Install Issue on MacOS 10.14 with pyenv and python 3.8.0) abt Python 3.8.0 and wxPython issues that you’ve responded to.

Be interested to hear where things are on that. Thx.

See https://github.com/wxWidgets/Phoenix/pull/1103 for an example integration of asyncio and wxPython. Google will probably find one or two others.

In general, an asyncio model of programming can have big benefits for certain kinds of programming problems. However, it can be complex and it would likely require a major rearchitecture of your existing code to be able to work well in that kind of framework. if you are already having trouble wrapping your head around event-driven programming and threads, then I would avoid asyncio for now. You need to walk before you can run.

I understand event-driven programming and threads, just not familiar with how it gets implemented in Python. Once I actually get into it, then I’ll have a better idea of what I don’t know that I don’t know.

However, your advice is appreciated and duly noted. Thx.