Search code examples
pythonwxpython

WxPython, buttons in Scrolled Panel inactive (not clickable)


I have this program that creates buttons in a scrolled panel:

import wx
import wx.lib.scrolledpanel as scrolled


class EditWindow(wx.Frame):

    def __init__(self, *args, **kwargs):
        self.width = 400
        self.height = 370
        wx.Frame.__init__(self, size=(self.width, self.height), style=wx.MINIMIZE_BOX | wx.CLOSE_BOX | wx.CAPTION,
                      *args, **kwargs)
        self.GUI()
        self.Show(True)

    def GUI(self):
        button_dict = {}
        global button_dict

        divisor = 120

        panel = wx.Panel(self, -1, pos=(0, 0), size=(self.width, 400))

        ok_button = wx.Button(panel, -1, label='Ok', pos=((self.width - 80) / 2, 80))
        ok_button.SetSize((80, 25))
        ok_button.Bind(wx.EVT_BUTTON, self.period_select)

        scrolled_panel = scrolled.ScrolledPanel(self, -1, pos=(140, divisor),
                                            size=(self.width - 285, 200),
                                            style=wx.TAB_TRAVERSAL | wx.SUNKEN_BORDER, name='')
        scrolled_panel.SetupScrolling()

        spSizer = wx.BoxSizer(wx.VERTICAL)
        scrolled_panel.SetSizer(spSizer)
        global spSizer

        panelSizer = wx.BoxSizer(wx.VERTICAL)

        global panel, panelSizer, scrolled_panel, spSizer

    def period_select(self, event):
        global scrolled_panel, spSizer, button_dict
        button_dict = {}

        for i in range(1, 4):
            button_dict[str(i)] = wx.Button(scrolled_panel,
                                             label='{0}'.format(i))
            button_dict[str(i)].Bind(wx.EVT_BUTTON, self.printa)
            spSizer.Add(button_dict[str(i)])

        scrolled_panel.Layout()
        scrolled_panel.SetupScrolling()
        panel.SetSizer(panelSizer)

    def printa(self, event):
        print('a')


def main():
    app = wx.App()
    EditWindow(None)
    app.MainLoop()

main()

The problem is: this code correctly creates the Frame and the buttons in the scrolled panel, but when I try to click on the buttons they don't seem to work at all. Also, the scroll bar appears correctly but I cannot use it (either with mousewheel or clicking on it and dragging). What am I doing wrong?

--EDIT--

This is the message i get when I run the code in PyCharm:

C:\Python34\python.exe C:/Users/USER/PycharmProjects/PokerissimoStats/SE.py
C:/Users/USER/PycharmProjects/PokerissimoStats/SE.py:17: SyntaxWarning: name 'button_dict' is assigned to before global declaration
  global button_dict
C:/Users/USER/PycharmProjects/PokerissimoStats/SE.py:34: SyntaxWarning: name 'spSizer' is assigned to before global declaration
  global spSizer
C:/Users/USER/PycharmProjects/PokerissimoStats/SE.py:38: SyntaxWarning: name 'panel' is assigned to before global declaration
  global panel, panelSizer, scrolled_panel, spSizer
C:/Users/USER/PycharmProjects/PokerissimoStats/SE.py:38: SyntaxWarning: name 'panelSizer' is assigned to before global declaration
  global panel, panelSizer, scrolled_panel, spSizer
C:/Users/USER/PycharmProjects/PokerissimoStats/SE.py:38: SyntaxWarning: name 'scrolled_panel' is assigned to before global declaration
  global panel, panelSizer, scrolled_panel, spSizer
C:/Users/USER/PycharmProjects/PokerissimoStats/SE.py:38: SyntaxWarning: name 'spSizer' is assigned to before global declaration
  global panel, panelSizer, scrolled_panel, spSizer

--EDIT 2--

I have rewritten the code to get rid of SyntaxWarnings, but the problem is still there

import wx
import wx.lib.scrolledpanel as scrolled


class EditWindow(wx.Frame):

    def __init__(self, *args, **kwargs):
        self.width = 400
        self.height = 370
        wx.Frame.__init__(self, size=(self.width, self.height), style=wx.MINIMIZE_BOX | wx.CLOSE_BOX | wx.CAPTION,
                      *args, **kwargs)
        self.GUI()
        self.Show(True)

    def GUI(self):

        global button_dict, spSizer, panel, panelSizer, scrolled_panel
        button_dict = {}

        divisor = 120

        panel = wx.Panel(self, -1, pos=(0, 0), size=(self.width, 400))

        ok_button = wx.Button(panel, -1, label='Ok', pos=((self.width - 80) / 2, 80))
        ok_button.SetSize((80, 25))
        ok_button.Bind(wx.EVT_BUTTON, self.period_select)

        scrolled_panel = scrolled.ScrolledPanel(self, -1, pos=(140, divisor),
                                            size=(self.width - 285, 200),
                                            style=wx.TAB_TRAVERSAL | wx.SUNKEN_BORDER, name='')
        scrolled_panel.SetupScrolling()

        spSizer = wx.BoxSizer(wx.VERTICAL)
        scrolled_panel.SetSizer(spSizer)

        panelSizer = wx.BoxSizer(wx.VERTICAL)

    def period_select(self, event):
        global scrolled_panel, spSizer, button_dict
        button_dict = {}

        for i in range(1, 4):
            button_dict[str(i)] = wx.Button(scrolled_panel,
                                             label='{0}'.format(i))
            button_dict[str(i)].Bind(wx.EVT_BUTTON, self.printa)
            spSizer.Add(button_dict[str(i)])

        scrolled_panel.Layout()
        scrolled_panel.SetupScrolling()
        panel.SetSizer(panelSizer)

    def printa(self, event):
        print('a')


def main():
    app = wx.App()
    EditWindow(None)
    app.MainLoop()

main()

Solution

  • Dump all the globals and use self instead. This isn't really an answer at all but I've cleaned up your code a bit, so that it runs from the command line (Linux wxpython 3.0)

    import wx
    import wx.lib.scrolledpanel as scrolled
    
    
    class EditWindow(wx.Frame):
    
        def __init__(self, *args, **kwargs):
            self.width = 400
            self.height = 370
            wx.Frame.__init__(self, size=(self.width, self.height), style=wx.MINIMIZE_BOX | wx.CLOSE_BOX | wx.CAPTION,
                          *args, **kwargs)
            divisor = 120
    
            self.panel = wx.Panel(self, -1, pos=(0, 0), size=(self.width, 400))
    
            ok_button = wx.Button(self.panel, -1, label='Ok', pos=((self.width - 80) / 2, 80))
            ok_button.SetSize((80, 25))
            ok_button.Bind(wx.EVT_BUTTON, self.period_select)
    
            self.scrolled_panel = scrolled.ScrolledPanel(self.panel, -1, pos=(140, divisor),
                                                size=(self.width - 285, 200),
                                                style=wx.TAB_TRAVERSAL | wx.SUNKEN_BORDER, name='')
            self.spSizer = wx.BoxSizer(wx.VERTICAL)
            self.scrolled_panel.SetSizer(self.spSizer)
            self.panelSizer = wx.BoxSizer(wx.VERTICAL)
            self.panel.SetSizer(self.panelSizer)
    
            self.Show()
    
        def period_select(self, event):
            button_dict = {}
    
            for i in range(1, 4):
                button_dict[str(i)] = wx.Button(self.scrolled_panel,label='{0}'.format(i))
                button_dict[str(i)].Bind(wx.EVT_BUTTON, self.printa)
                self.spSizer.Add(button_dict[str(i)])
            self.scrolled_panel.SetupScrolling()
            self.scrolled_panel.Layout()
    
        def printa(self, event):
            print('a')
    
    
    def main():
        app = wx.App()
        EditWindow(None)
        app.MainLoop()
    
    main()