phkahler
phkahler

Reputation: 5767

Prevent wxPython event from hitting multiple windows?

My wxPython application uses a wx.ScrolledWindow for the main drawing area - taken straight out of the demo and hacked to my needs. When the user double clicks in the scrolled area, I want to pop up a (possibly modal) dialog to edit parameters of things they've drawn. So I popped up a dialog via code from another demo:

    def OnLeftDoubleClickEvent(self, event):
    dlg = TestDialog(self, -1, "Sample Dialog", size=(350, 200),
                     #style=wx.CAPTION | wx.SYSTEM_MENU | wx.THICK_FRAME,
                     style=wx.DEFAULT_DIALOG_STYLE, # & ~wx.CLOSE_BOX
                     )
    dlg.CenterOnScreen()

    # this does not return until the dialog is closed.
    val = dlg.ShowModal()

That's just a test of course. The dialog itself was competely defined in one of the demos. Anyway, upon closing the popup the ScrolledArea jumps to a new position, and on Windows the mouse events no longer map to the correct coordinates. The displacement only happens if you move the popup such that you mouse click outside the area of the Scrolled Area to close it. Keep in mind that "OK" and "Cancel" are on a completely different dialog than the scrolled area. On Linux, the scrolled area appears to move based on how far outside the area the mouse was clicked - and in the same direction. On Windows, the scrolled area moves and get confused - further mouse clicks will displace it as well and (because?) the click is recorded in the wrong place.

So the Linux version of the problem seem to indicate that the click event on the popup is actually being processed by the scrolled area in the original window.

Does that sound like what's happening?

If so, how do I prevent that from happening?

EDIT: more info. I tried closing the popup by tabbing to the OK or Cancel button. Each time focus move to another control, the scrolled area in the other window moves. This depends on where the popup is in relation to the other window. I'm totally confused now.

EDIT2: I've added an option in the menu of the main window to trigger the popup dialog. When activated this way, there does not seem to be any problem. I'm thinking the issue is somehow due to creating the popup in the double-click event of the scrolled area causing some events to be processed by both. Does that make sense? When I have time, I'm going to try sending an event (custom?) to the parent dialog and have it map to the same function that the new menu item does. This will cause my popup to come from the main window and will hopefully eliminate the problem. We'll see.

EDIT3 TEST CASE

To see this, take the file: ScrolledWindow.py from the demo, add the following:

from Dialog import *

Then in the mouse events area of the MyCanvas class, bind a double click with this:

self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDoubleClickEvent)

Then add the following function to the same class (taken from the Dialog demo):

    def OnLeftDoubleClickEvent(self, event):
    useMetal = False
    if 'wxMac' in wx.PlatformInfo:
        useMetal = self.cb.IsChecked()

    dlg = TestDialog(self, -1, "Sample Dialog", size=(350, 200),
                     #style=wx.CAPTION | wx.SYSTEM_MENU | wx.THICK_FRAME,
                     style=wx.DEFAULT_DIALOG_STYLE, # & ~wx.CLOSE_BOX,
                     useMetal=useMetal,
                     )
    dlg.CenterOnScreen()

    # this does not return until the dialog is closed.
    val = dlg.ShowModal()

    if val == wx.ID_OK:
        self.log.WriteText("You pressed OK\n")
    else:
        self.log.WriteText("You pressed Cancel\n")

    dlg.Destroy()

Now run the demo and choose Core Windows/Controls and the "ScrolledWindow". You'll be able to scribble on the scrolled area as usual, but now you can double click in there and it will pop up a dialog. Please move that new dialog outside the drawing area and then tab around the input boxes or click OK. Activity in this dialog will cause the scrollable drawing in the other window to change positions.

And there you have it. What is causing this? I've adapted the demo to draw my own custom objects and I want to be able to double click to bring up an object properties dialog. Is this a bug, or the wrong way to go about it? Is my plan from Edit2 more like "the right way"?

Upvotes: 3

Views: 540

Answers (1)

phkahler
phkahler

Reputation: 5767

The solution turns out to be what I proposed in Edit2. I'm not sure why, but doing the pop-up from inside the ScrolledArea DoubleClick event was causing problems. The solution is to create a custom message and send it to self inside the double-click event. The custom event is handled by the top level window, not the scrolled area. This works fine, but now I have to store the ID of the selected object somewhere so the top level window can pass it to the dialog. This is slightly more work, but it feels more "correct" than popping up a window inside the double-click event of the drawing area. However, the window is still being popped up inside an event handler, it's just a different object handling it with a different event. The specifics of why this works still elude me.

I'm sure there is a way of thinking about this that makes this solution obviously correct. I'll still up-vote an answer that offers insight into why one method works and not the other, or what the "correct" way to do this type of thing is.

In other news, I'm posting this after a +50 bounty expired on this question. Yeah, I posted a bounty before trying my own idea - silly me. Next time I will try the wxPython mailing list before offering a bounty, although I don't like mailing lists.

Upvotes: 0

Related Questions