Open cbeytas opened 11 months ago
Very interesting. I don't think the issue is quite as you stated - really, it seems that in the C++ API, skip
is both an output and an input, and wxPython doesn't let you supply it as an input. This is a pretty strange C++ API.
That's the crux of the problem. The C++ API only sets skip
to True if its current value is False.
So the behavior depends on what skip
is initialized to:
msw/progdlg.cpp
generic/progdlg.cpp
I think the fix would be to initialize skip
to False before making the call. That would guarantee behavior 1. It would also be good to add a note to the documentation that a call to Update() where skip returns True resets the skip state of the dialog and WasSkipped() will return False again.
wxPython v4.2.1, wxWidgets 3.2.2.1, Python 3.11 - Affects Windows10 and Linux/GTK3
The
ProgressDialog
returns its Cancel/Skip state on each call toUpdate()
. You can also check the current state with theWasSkipped()
method.proceed, skip = dialog.Update(percent)
Behavior 1: (Correct, as expected from the wxWidgets source msw/progdlg.cpp and generic/progdlg.cpp)
Behavior 2: (Incorrect)
Sometimes when stuck in behavior 2, it will randomly switch back to behavior 1.
The problem seems to be in the auto-generated file
sip/cpp/sip_corewxProgressDialog.cpp
.This passes a pointer to an uninitialized boolean value
skip
. Its value is indeterminate. A pointer to skip is passed to the sipCpp->Update method which inspects its value before passing the skip state. If, by chance, skip is initialized to False the method will set it to True and reset its internal state. If, by chance, skip is initialized to True, then the skip state will never get passed properly.Code Example (click to expand)
```python import locale import time import wx class TestPanel(wx.Panel): def __init__(self, parent): wx.Panel.__init__(self, parent) button = wx.Button(self, label="Show ProgressDialog") button.Bind(wx.EVT_BUTTON, self.OnButton) def OnButton(self, event): progress = wx.ProgressDialog("Skip Test", message="Attempt to skip me", style=wx.PD_APP_MODAL | wx.PD_AUTO_HIDE | wx.PD_CAN_SKIP) progress.Show() for num in range(100): proceed, skip = progress.Update(num) if skip is True: print("Skip==True") if progress.WasSkipped() is True: print("WasSkipped==True") break time.sleep(0.1) progress.Update(100) progress.Destroy() class TestFrame(wx.Frame): def __init__(self): wx.Frame.__init__(self, parent=None, title="ProgressDialog Skip Test") panel = TestPanel(self) self.Show() if __name__ == "__main__": app = wx.App() locale.setlocale(locale.LC_ALL, 'C') frame = TestFrame() app.MainLoop() ```