0

I am trying to update an old app that was written for Python 2.7 with wxWidgets/wxPython 2.8. I am trying to make it compatible with my current system's versions of Python (3.10) & wxPython (4.0).

I have come across an error trying to call a super/parent method. The class is derived from wx.ScrolledWindow.

The old code snippet is (ui/panel.py starting at line 74):

def SetScrollbars(window):
  if isinstance(window, wx.ScrolledWindow):
    window.SetScrollbars(20, 20, 0, 0)

## A wx.ScrolledWindow that sets scrollbars by default
class ScrolledPanel(wx.ScrolledWindow, PanelBase):
  def __init__(self, parent, win_id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize,
      style=wx.HSCROLL|wx.VSCROLL, name="scrolledPanel"):
    wx.ScrolledWindow.__init__(self, parent, win_id, pos, size, style, name)
    SetScrollbars(self)

  ## Override inherited method to also update the scrollbars
  def Layout(self):
    layout = wx.ScrolledWindow.Layout(self)
    self.UpdateScrollbars()
    return layout

The error is:

  File "ui/panel.py", line 87, in Layout
    layout = wx.ScrolledWindow.Layout(self)
wx._core.wxAssertionError: C++ assertion "m_widget" failed at ../src/gtk/window.cpp(2888) in DoSetSize(): invalid window

I searched for how to call parent/super methods in Python & found from this question that Python has a super() function.

So I changed line 87:

-    layout = wx.ScrolledWindow.Layout(self)
+    layout = super().Layout()

The same error is reported:

  File "/home/jordan/Development/Debreate/code/ui/panel.py", line 87, in Layout
    layout = super().Layout()
wx._core.wxAssertionError: C++ assertion "m_widget" failed at ../src/gtk/window.cpp(2888) in DoSetSize(): invalid window

I suppose calling the parent/super method either way is correct. So that must not be the issue.

My system's version of wxWidgets is 3.0.5.1. I found the assertion check line in the wxWidgets source code. The checking function, wxCHECK_RET, "Checks that the condition is true, and returns if not". So the window is invalid. I just don't understand why as this worked with older versions of wxWidgets/wxPython.

AntumDeluge
  • 490
  • 1
  • 5
  • 13

2 Answers2

1

wx.ScrolledWindow is an alias for ScrolledPanel since version 2.9.0. In older versions, it was a standalone class.
Try reading up on https://docs.wxpython.org/wx.lib.scrolledpanel.html as its replacement.

Rolf of Saxony
  • 21,661
  • 5
  • 39
  • 60
  • Thanks. Switching to `ScrolledPanel` does work. Though I am curious why `wx.ScrolledWindow.SetupScrolling` doesn't work if it is an alias? – AntumDeluge Aug 31 '22 at 12:42
0

As was suggesting by Rolf of Saxony, switching to wx.lib.scrolledpanel.ScrolledPanel solves the problem:

from wx.lib.scrolledpanel import ScrolledPanel as sp

class ScrolledPanel(sp, PanelBase):
  def __init__(self, parent, win_id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize,
      style=wx.HSCROLL|wx.VSCROLL, name="scrolledPanel"):
    sp.__init__(self, parent, win_id, pos, size, style, name)
    sp.SetupScrolling(self)

But I also want to note that I was able to work around the problem by calling Layout on the parent window:

  ## Override inherited method to also update the scrollbars
  def Layout(self):
    layout = self.GetParent().Layout(self)
    self.UpdateScrollbars()
    return layout

But using wx.lib.scrolledpanel.ScrolledPanel is probably the proper way to upgrade.

AntumDeluge
  • 490
  • 1
  • 5
  • 13