WxPython in Windows, button won't change states

I’m having a strange problem specific to WxPython 2.9.4.0 in Windows. The code works fine in Mac and Ubuntu. I posted to StackOverflow with no luck, so I thought I’d try here.

Basically, the problem boils down to this – how could the assertion on the second line ever fail?

self.next_button.Enable(self.__next_enabled)
assert(self.next_button.Enabled == self.__next_enabled)

I checked the type of next_button and everything else I could think of, and as I said, it works fine on Mac and Ubuntu. In fact, if I execute the function containing this code with a slight delay using a Timer, it also works. Somehow Windows accepts the Enable() call but doesn’t actually execute it.

Any ideas?

http://stackoverflow.com/questions/14794862/wxpython-2-9-in-windows-button-will-not-enable

-John

This can fail because the set method queues a change for the next
GUI update which has not necessarily take place when the next line
of code is reached - my only question is why anybody would have such
an assert in the first place? In general GUI events do not change
the state of things immediately as there may be several, sometimes
contradictory, such events happening in a very short space of time
and redrawing all the screen elements every time would cause a
bottleneck - e.g. if you are dragging the position of a window the
position may move by one pixel at a time in the mouse update
routine, called at USB speeds, but the actual drawing of the screen
needs to be done at screen refresh rates, typically 50-75 Hz - if
what you are dragging is 300x300 pixels then that is 90000 pixels to
recompute for each update, i.e. a lot of work.
If you REALLY need to make sure that your Enable worked then have a
function that checks it and is called from a wx.CallAfter this will
allow the GUI to finish updating before the check is done.
Gadget/Steve

···

On 31/03/13 06:03, John Bender wrote:

  I'm having a strange problem specific to WxPython

2.9.4.0 in Windows. The code works fine in Mac and Ubuntu. I
posted to StackOverflow with no luck, so I thought I’d try here.

  Basically, the problem boils down to this -- how could the

assertion on the second line ever fail?

    self.next_button.Enable(self.__next_enabled)
      assert(self.next_button.Enabled == self.__next_enabled)




      I checked the type of next_button and everything else I could

think of, and as I said, it works fine on Mac and Ubuntu. In
fact, if I execute the function containing this code with a
slight delay using a Timer, it also works. Somehow Windows
accepts the Enable() call but doesn’t actually execute it.

Any ideas?

  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 .
For more options, visit .


Steve Gadget Barnes

http://stackoverflow.com/questions/14794862/wxpython-2-9-in-windows-button-will-not-enable

-John

wxpython-users+unsubscribe@googlegroups.com
https://groups.google.com/groups/opt_out

I put the assertion in to debug - I don’t find assertions generally useful in production code. The assertion passes in Linux and Mac. I assume it’s testing an internal state, not the GUI rendering of that state, but that’s not really important to me. The point is that I shouldn’t EVER need to double-check that my Enable call worked!

I’ve found that inserting a wx.Yield call usually solves any scheduling/update problems, but not here. Here, the button’s state never changes at all, and I’m trying to figure out why. The Enable function gets called on the correct object with the correct argument, but has no effect. The assertion is just a way to demonstrate that.

Could it be that the Windows event handlers get overwhelmed and drop a call? I am running lots of other things in this same event loop. I haven’t yet found a minimal example that has this problem. But I don’t think I’m doing anything wrong, because it works on the other two systems I’ve tried. How could Enable ever be ignored?

JB

···

On Saturday, March 30, 2013, Steve Barnes wrote:

On 31/03/13 06:03, John Bender wrote:

  I'm having a strange problem specific to WxPython

2.9.4.0 in Windows. The code works fine in Mac and Ubuntu. I
posted to StackOverflow with no luck, so I thought I’d try here.

  Basically, the problem boils down to this -- how could the

assertion on the second line ever fail?

    self.next_button.Enable(self.__next_enabled)
      assert(self.next_button.Enabled == self.__next_enabled)




      I checked the type of next_button and everything else I could

think of, and as I said, it works fine on Mac and Ubuntu. In
fact, if I execute the function containing this code with a
slight delay using a Timer, it also works. Somehow Windows
accepts the Enable() call but doesn’t actually execute it.

Any ideas?

http://stackoverflow.com/questions/14794862/wxpython-2-9-in-windows-button-will-not-enable

-John

  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 wxpython-users+unsubscribe@googlegroups.com.

  For more options, visit [https://groups.google.com/groups/opt_out](https://groups.google.com/groups/opt_out).
This can fail because the set method queues a change for the next

GUI update which has not necessarily take place when the next line
of code is reached - my only question is why anybody would have such
an assert in the first place? In general GUI events do not change
the state of things immediately as there may be several, sometimes
contradictory, such events happening in a very short space of time
and redrawing all the screen elements every time would cause a
bottleneck - e.g. if you are dragging the position of a window the
position may move by one pixel at a time in the mouse update
routine, called at USB speeds, but the actual drawing of the screen
needs to be done at screen refresh rates, typically 50-75 Hz - if
what you are dragging is 300x300 pixels then that is 90000 pixels to
recompute for each update, i.e. a lot of work.

If you REALLY need to make sure that your Enable worked then have a

function that checks it and is called from a wx.CallAfter this will
allow the GUI to finish updating before the check is done.

John Bender wrote:

I'm having a strange problem specific to WxPython 2.9.4.0 in Windows.
The code works fine in Mac and Ubuntu. I posted to StackOverflow with no
luck, so I thought I'd try here.

Basically, the problem boils down to this -- how could the assertion on
the second line ever fail?

self.next_button.Enable(self.__next_enabled)
assert(self.next_button.Enabled == self.__next_enabled)

I checked the type of next_button and everything else I could think of,
and as I said, it works fine on Mac and Ubuntu. In fact, if I execute
the function containing this code with a slight delay using a Timer, it
also works. Somehow Windows accepts the Enable() call but doesn't
actually execute it.

Any ideas?

I suppose that it's possible on Windows for the widget to reject the change in enabled state in certain conditions, but we would really need to see a runnable example of this problem to even guess what might be causing it in your case.

···

--
Robin Dunn
Software Craftsman

Attached is a demo app. Apparently what's happening is that in Windows,
opening a ProgressDialog disables the buttons in my main window, even
though I set the dialog's parent to None and its style to 0. This is not
the case in Linux or Mac, and I believe it's also different from Wx 2.8 in
Windows.

I'm not certain that this is precisely what's happening in my application,
but it's very similar. In the attached app, the buttons re-enable
themselves after some period of time (0.1 < t < 0.5 on my machine).

button-test.zip (2.18 KB)

···

On Sun, Mar 31, 2013 at 3:16 PM, Robin Dunn <robin@alldunn.com> wrote:

John Bender wrote:

I'm having a strange problem specific to WxPython 2.9.4.0 in Windows.
The code works fine in Mac and Ubuntu. I posted to StackOverflow with no
luck, so I thought I'd try here.

Basically, the problem boils down to this -- how could the assertion on
the second line ever fail?

self.next_button.Enable(self._**_next_enabled)
assert(self.next_button.**Enabled == self.__next_enabled)

I checked the type of next_button and everything else I could think of,
and as I said, it works fine on Mac and Ubuntu. In fact, if I execute
the function containing this code with a slight delay using a Timer, it
also works. Somehow Windows accepts the Enable() call but doesn't
actually execute it.

Any ideas?

I suppose that it's possible on Windows for the widget to reject the
change in enabled state in certain conditions, but we would really need to
see a runnable example of this problem to even guess what might be causing
it in your case.

John Bender wrote:

    John Bender wrote:

        I'm having a strange problem specific to WxPython 2.9.4.0 in
        Windows.
        The code works fine in Mac and Ubuntu. I posted to StackOverflow
        with no
        luck, so I thought I'd try here.

        Basically, the problem boils down to this -- how could the
        assertion on
        the second line ever fail?

        self.next_button.Enable(self.____next_enabled)
        assert(self.next_button.__Enabled == self.__next_enabled)

        I checked the type of next_button and everything else I could
        think of,
        and as I said, it works fine on Mac and Ubuntu. In fact, if I
        execute
        the function containing this code with a slight delay using a
        Timer, it
        also works. Somehow Windows accepts the Enable() call but doesn't
        actually execute it.

        Any ideas?

    I suppose that it's possible on Windows for the widget to reject the
    change in enabled state in certain conditions, but we would really
    need to see a runnable example of this problem to even guess what
    might be causing it in your case.

Attached is a demo app. Apparently what's happening is that in Windows,
opening a ProgressDialog disables the buttons in my main window, even
though I set the dialog's parent to None and its style to 0. This is not
the case in Linux or Mac, and I believe it's also different from Wx 2.8
in Windows.

In 2.9 the ProgressDialog on Windows was switched to a native dialog implementation instead of the generic one that was being used before, so that is probably the source of the differences. The old class is now available as wx.GenericProgressDialog.

I'm not certain that this is precisely what's happening in my
application, but it's very similar. In the attached app, the buttons
re-enable themselves after some period of time (0.1 < t < 0.5 on my
machine).

The dialog's Destroy method doesn't actually destroy anything, it just adds the dialog to a list of items to be destroyed later when all pending events have been processed. So in your example control has to first return to the event loop, and the event queue has to become empty, and then the dialog will be destroyed, triggering it to enable any widgets that it had disabled before.

BTW, using a threading.Timer to call a function that deals with the UI is a bad idea. You can use wx.CallLater instead and it will use a wx.Timer and the callable will be invoked in the context of the UI thread.

···

On Sun, Mar 31, 2013 at 3:16 PM, Robin Dunn <robin@alldunn.com > <mailto:robin@alldunn.com>> wrote:

--
Robin Dunn
Software Craftsman