Catching key press events while model wx.MessageDialog(...) is shown?

"[email protected]" <[email protected]> Mon, 31 May 2021 13:15:55 -0700 (PDT)
Newsgroups gmane.comp.python.wxpython
Message-ID <[email protected]>
I have a program that runs a long task in a background thread, and shows a 
modal wx.MessageDialog(...) in the foreground with a "Stop" button to stop 
the background thread. The long task is a sequence of work cycles, and the 
"Stop" button stops the sequence after completing the currently running 
cycle. So far, all is good (as in the attached example code).

I would like to add a mechanism that allows stopping the background thread 
immediately (without waiting to complete the current cycle) by pressing a 
key or key combination on the keyboard. For example, pressing the 'K' key 
on the keyboard should trigger a call to worker_thread.kill() in the 
attached example code. What would be a good appraoch to make this work? Is 
there a way to hook into the event loop of the wx.MessageDialog(...) to 
check for key press events? Of is there another way to check for key 
presses?

-- 
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
To view this discussion on the web visit https://groups.google.com/d/msgid/wxpython-users/7eaaf026-4c98-4389-8c2a-cd2d6b1f8c6en%40googlegroups.com.
longtask.py (text/x-python, 1.7 KB)
import time
from threading import *
import wx



class worker_thread(Thread):
	def __init__(self, notify_window):
		Thread.__init__(self)
		self._notify_window = notify_window
		self._want_abort = False
		self._want_kill  = False
		self.start()

	def run(self):
		num_cycles = 0
		while not self._want_abort:
			wx.CallAfter(self._notify_window.log_result,num_cycles)
			for i in range(50):
				time.sleep(0.1)
				if self._want_kill:
					self._want_abort = True
					break
			num_cycles += 1
		wx.CallAfter(self._notify_window.log_done)

	def abort(self):
		self._want_abort = True

	def kill(self):
		self._want_kill  = True



class my_frame(wx.Frame):
	
	def __init__(self):
		wx.Frame.__init__(self, parent=None, title='Main Window', size=(500,300))
		self.status_text = wx.StaticText(self, -1, 'Startin up...', pos=(100,100))
		self.Show(True)
		self.dialog = wx.MessageDialog(self, 'Stop after completing current work cycle?', 'Running cycles...', wx.OK)
		self.dialog.SetOKLabel('Stop')

	def log_result(self, data):
		self.status_text.SetLabel('Working! Number of completed cycles: %s' % data)

	def log_abort(self):
		self.status_text.SetLabel('User wants to abort work. Finishing the current work cycle...')

	def log_done(self):
		self.status_text.SetLabel('Finished working. You can close this window now.')



# Main program:

# set up App and main frame:
app = wx.App(False)
frame = my_frame()

# set up long-running taks:
work = worker_thread(frame)

# show modal MessageDialog to abort the work cleanly:
frame.dialog.ShowModal()

# Tell thread to stop running after completing the current cycle:
work.abort()

# Log to my_frame
frame.log_abort()

# do whatever the app is supposed to do after the long-running task:
app.MainLoop()