how to bind events with CreateButtonSizer

In a wx.Dialog.__init__ I create buttons and connect event handlers
like this

    self.CreateButtonSizer(wx.OK | wx.CANCEL)
    self.Bind(wx.EVT_BUTTON, self._OnOk, id=wx.ID_OK)
    self.Bind(wx.EVT_BUTTON, self._OnCancel, id=wx.ID_CANCEL)

Clicking the buttons work. But Closing the dialog with the X-Button in
the titlebar doesn't work. It always come into self._OnCancel. Why?

What happen there in the background?
Pressing the Cancel-Button and using the close-X-button in the titlebar
are definitly differnt things. Latter should create a OnClose or
something like that - not a OnCancel.

I tried to create the buttons myself and call their own Bind().
Now the OnCancel is called twice when clicking the window-x.

I am totaly confused now.

···

On 2015-02-17 01:26 <moonkid@posteo.org> wrote:

    self.CreateButtonSizer(wx.OK | wx.CANCEL)

Sorry, I am in nightshift and that is the primary reason for my
confusion. :wink:

This (simplified) code work well.

class PersParamDlg(wx.Dialog):
    def __init__(self, parent):
        super(PersParamDlg, self).__init__(parent)
        self.Bind(wx.EVT_CLOSE, self._OnClose)
        self.Bind(wx.EVT_BUTTON, self._OnOk, id=wx.ID_OK)
        self.Bind(wx.EVT_BUTTON, self._OnCancel, id=wx.ID_CANCEL)
        self.CreateButtonSizer(wx.OK | wx.CANCEL)
        self.ShowModal()

    def _OnClose(self, event):
        self.Destroy()

    def _OnOk(self, event):
        print("ok")
        self.Close()

    def _OnCancel(self, event):
        print("cancel")
        self.Close()

In this example, in your __init__ routine, the button sizer is created and lost immediately.
I think you need something like:

self.SetSizer(self.CreateButtonSizer(wx.OK | wx.CANCEL))

···

On 2/16/2015 8:00 PM, moonkid@posteo.org wrote:

Sorry, I am in nightshift and that is the primary reason for my
confusion. :wink:

This (simplified) code work well.

class PersParamDlg(wx.Dialog):
     def __init__(self, parent):
         super(PersParamDlg, self).__init__(parent)
         self.Bind(wx.EVT_CLOSE, self._OnClose)
         self.Bind(wx.EVT_BUTTON, self._OnOk, id=wx.ID_OK)
         self.Bind(wx.EVT_BUTTON, self._OnCancel, id=wx.ID_CANCEL)
         self.CreateButtonSizer(wx.OK | wx.CANCEL)
         self.ShowModal()

     def _OnClose(self, event):
         self.Destroy()

     def _OnOk(self, event):
         print("ok")
         self.Close()

     def _OnCancel(self, event):
         print("cancel")
         self.Close()

moonkid@posteo.org wrote:

In a wx.Dialog.__init__ I create buttons and connect event handlers
like this

     self.CreateButtonSizer(wx.OK | wx.CANCEL)
     self.Bind(wx.EVT_BUTTON, self._OnOk, id=wx.ID_OK)
     self.Bind(wx.EVT_BUTTON, self._OnCancel, id=wx.ID_CANCEL)

Clicking the buttons work. But Closing the dialog with the X-Button in
the titlebar doesn't work. It always come into self._OnCancel. Why?

What happen there in the background?
Pressing the Cancel-Button and using the close-X-button in the titlebar
are definitly differnt things. Latter should create a OnClose or
something like that - not a OnCancel.

The default EVT_CLOSE handler in dialogs sends a button event with an id of wx.ID_CANCEL. This is because 99% of the time you want the close to be the same as a cancel. When you don't then you can catch the EVT_CLOSE yourself, as you figured out.

There are also default handlers for the EVT_BUTTON events from the Cancel and Ok buttons. They will do some dialog things like calling the validators if there are any, and finally calling EndModal. This is something else that most of the time you want dialogs to do, at least for modal dialogs. Calling self.Close is the wrong thing for modal dialogs, and if you're not going to be using the dialogs modally then IMO you may as well just use a Frame with a Panel instead.

···

--
Robin Dunn
Software Craftsman