I just had this problem and based on the answer here I came up with the solution below. This was tested using wxPython 4.1.0 and python 3.8.5.
In essence, all wx.EVT_BUTTON
events in the wx.Dialog
window are bound to a method in the wx.Dialog
window. In the method, the ID of the clicked button is compared to the IDs used to create the buttons in the wx.Dialog
and actions are taken accordingly.
In the example below, clicking the OK button generates a random number. The wx.Dialog
only closes if the random number is > 0.5.
import random
import wx
class Example(wx.Frame):
"""Main window """
def __init__(self, parent):
super().__init__(
parent,
title = 'Intercept wx.Dialog button events',
size = (260, 180),
)
self.btn = wx.Button(self, label = 'Show Dialog Window')
self.Sizer = wx.BoxSizer()
self.Sizer.Add(self.btn, 0, wx.ALIGN_CENTER|wx.ALL, 5)
self.SetSizer(self.Sizer)
self.btn.Bind(wx.EVT_BUTTON, self.OnDialog)
self.Centre()
self.Show()
def OnDialog(self, event):
with MyDialog(self) as dlg:
if dlg.ShowModal() == wx.ID_OK:
print("Dialog closed with OK - Message from Main Window")
print("")
else:
print("Dialog closed with Cancel - Message from Main Window")
print("")
class MyDialog(wx.Dialog):
def __init__(self, parent):
super().__init__(
parent,
title = 'My Dialog',
size = (220, 90),
)
self.btnSizer = self.CreateStdDialogButtonSizer(
wx.OK|wx.CANCEL
)
self.Sizer = wx.BoxSizer()
self.Sizer.Add(self.btnSizer, 0, wx.ALIGN_CENTER|wx.ALL, 5)
self.SetSizer(self.Sizer)
self.CentreOnParent()
# HERE IS THE TRICK, Get all Button events
self.Bind(wx.EVT_BUTTON, self.OnButton)
def OnButton(self, event):
"""Process the OK button click"""
clicked_button_id = event.GetEventObject().GetId()
if clicked_button_id == wx.ID_OK:
print("Processing OK button click")
if (n := random.random()) > 0.5:
#--> Everything fine, window will close
print(n, "> 0.5. Ok, closing window")
pass
else:
#--> Error, window will remain open
print(n, "< 0.5. Not Ok, window remains open")
return False
else:
print("Processing Cancel button click")
# Skip event to make sure default behavior is executed
event.Skip()
if __name__ == '__main__':
app = wx.App()
Example(None)
app.MainLoop()