Search code examples
python-3.xwxpythonwxwidgets

Inner Panel doesnt respond


So my goal is do create a settings Window. On the left side you have the different categories. Which you can switch by clicking on them. On the right side is the panel that will switch the content based on what thing you clicked on.

I implemented it by creating a class for every content panel, instantiate it from the frame and Hide all the panels except the one that was choosen.

My problem is that i cant interact with anything inside the panels that i hide and show. Here is a minimum example that you should be able to run.

# -*- coding: utf-8 -*-
"""
Created on Tue Jul 13 15:54:51 2021

@author: Odatas
"""

import wx
import wx.lib.scrolledpanel as scrolled

#First Panel
class settingsConnection(wx.ScrolledWindow):

    def __init__(self,parent,size):
        wx.ScrolledWindow.__init__(self,parent=parent,size=size)
        self.topLevelSizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(self.topLevelSizer)
        self.infoText = wx.StaticText(self
                                      ,label="I'm Panel settingsConnection\n\nUnder construction."
                                      ,style=wx.ALIGN_CENTRE_HORIZONTAL)
        self.topLevelSizer.Add(self.infoText)

#Second Panel
class settingsGeneral(wx.ScrolledWindow):

    def __init__(self,parent,size):
        wx.ScrolledWindow.__init__(self,parent=parent,size=size)
        self.topLevelSizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(self.topLevelSizer)
        self.infoText = wx.StaticText(self
                                      ,label="I'm  Panel settingsGeneral\n\nUnder construction."
                                      ,style=wx.ALIGN_CENTRE_HORIZONTAL)
        self.topLevelSizer.Add(self.infoText)

#Third Panel
class settingsABC(scrolled.ScrolledPanel):

    def __init__(self,parent,size):
        scrolled.ScrolledPanel.__init__(self,parent=parent,size=size)
        self.topLevelSizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(self.topLevelSizer)

        self.firstSizer = wx.BoxSizer(wx.VERTICAL)
        self.secondSizer = wx.BoxSizer(wx.VERTICAL)
        self.thridSizer = wx.BoxSizer(wx.VERTICAL)
        self.SetupScrolling()
        self.SetAutoLayout(1)

        self.autoStartCheckBox=wx.CheckBox(self, label="Button")
        self.autoStartCheckBox.SetValue(True)

        self.testButton = wx.Button(self,label="Test")

        self.topLevelSizer.Add(self.autoStartCheckBox)
        self.topLevelSizer.Add(self.testButton)

        self.topLevelSizer.Layout()
        self.Fit()

#The main frame that holds all the panels
class settingsWindow(wx.Frame):

    FLAG_KILL_ME = False


    def __init__(self,parent):
        wx.Frame.__init__(self,parent=parent.frame,size=(1000,800),style= wx.CAPTION | wx.CLOSE_BOX |wx.STAY_ON_TOP|wx.FRAME_NO_TASKBAR)
        
        #Event for Closing window
        self.Bind(wx.EVT_CLOSE,self.onQuit)
        #Event for changing the focus
        self.Bind(wx.EVT_LIST_ITEM_FOCUSED,self.onFocusChange)
        self.parent=parent
        self.panel = wx.Panel(self)
        self.panelSize=(800,700)
        self.panel.SetBackgroundColour(wx.Colour(255,255,255))
        #Contains Everything Level 0
        self.topLevelSizer = wx.BoxSizer(wx.VERTICAL)
        #Contains Top Part Level 01
        self.windowSizer=wx.BoxSizer(wx.HORIZONTAL)
        #Contains Bottom part Level 01
        self.buttonSizer = wx.BoxSizer(wx.HORIZONTAL)
        #Contains Widgets for Mainpart
        self.widgetSizer = wx.BoxSizer(wx.HORIZONTAL)

        self.panel.SetSizer(self.topLevelSizer)
        self.topLevelSizer.Add(self.windowSizer)
        self.topLevelSizer.Add(self.buttonSizer)
        
        self.settingsChooser=wx.ListCtrl(self.panel, id=wx.ID_ANY,style=wx.LC_LIST|wx.LC_SINGLE_SEL,size=(100,700))
        self.settingsChooser.AppendColumn("Test")

        self.windowSizer.Add(self.settingsChooser)
        self.windowSizer.Add(self.widgetSizer)

        self.panelList=[]
        self.settingsChooser.InsertItem(0,"Allgemein")
        self.generalPanel=settingsGeneral(self,self.panelSize)
        self.panelList.append(self.generalPanel)
        self.widgetSizer.Add(self.generalPanel)


        self.settingsChooser.InsertItem(1,"Connection")
        self.connectionPanel=settingsConnection(self,self.panelSize)
        self.panelList.append(self.connectionPanel)
        self.widgetSizer.Add(self.connectionPanel)
        self.connectionPanel.Hide()

        self.settingsChooser.InsertItem(2,"DLT")
        self.dltPanel=settingsABC(self,self.panelSize)
        self.panelList.append(self.dltPanel)
        self.widgetSizer.Add(self.dltPanel)
        self.dltPanel.Hide()

        self.currentID=0
        self.panel.Fit()

        self.Centre()
        self.Show()
        #self.mythread = threading.Thread(target=self.downloadEndPackageMethod)
        #self.mythread.start()
        while self.FLAG_KILL_ME is False:
            wx.GetApp().Yield()


        try:
            self.Destroy()
        except Exception as e:
            pass
        
    #Shows the Selected Panel and hides the current shown.
    def onFocusChange(self,event=None):
        self.panelList[self.currentID].Hide()
        self.panelList[event.GetIndex()].Show()
        self.currentID=event.GetIndex()
        self.panel.Fit()
        self.panel.Layout()


    def onQuit(self,event=None):
        self.FLAG_KILL_ME = True
        self.Hide()
#Main wx.Python App        
class Testapp(wx.App): 
    
    def __init__(self,redirect=False,filename=None):


        wx.App.__init__(self,redirect,filename)
        self.frame=wx.Frame(None,title="Test")
        self.panel=wx.Panel(self.frame,size=(1000,1000))
        self.TopLevelSizer=wx.BoxSizer(wx.VERTICAL)
        self.panel.SetSizer(self.TopLevelSizer)
        self.settingsButton = wx.Button(self.panel,label="Settings")
        self.TopLevelSizer.Add(self.settingsButton)
        self.settingsButton.Bind(wx.EVT_BUTTON, self.openSettings)        
        self.frame.Show()
        
    def openSettings(self,event=None):
        settingsWindow(self)
           
        
        
if __name__=='__main__':
    app=Testapp()
    app.MainLoop()

Edit: Adjustest class "Settings Window" für use with wx.Listbook

class settingsWindow(wx.Frame):

FLAG_KILL_ME = False


def __init__(self,parent):
    wx.Frame.__init__(self,parent=parent.frame,size=(1000,800),style= wx.CAPTION | wx.CLOSE_BOX |wx.STAY_ON_TOP|wx.FRAME_NO_TASKBAR)

    self.Bind(wx.EVT_CLOSE,self.onQuit)
    # self.Bind(wx.EVT_LIST_ITEM_FOCUSED,self.onFocusChange)
    self.parent=parent
    self.panel = wx.Panel(self)
    self.panelSize=(800,700)
    self.panel.SetBackgroundColour(wx.Colour(255,255,255))
    #Contains Everything Level 0
    self.topLevelSizer = wx.BoxSizer(wx.VERTICAL)
    #Contains Top Part Level 01
    self.windowSizer=wx.BoxSizer(wx.HORIZONTAL)
    #Contains Bottom part Level 01
    self.buttonSizer = wx.BoxSizer(wx.HORIZONTAL)
    #Contains Widgets for Mainpart
    self.widgetSizer = wx.BoxSizer(wx.HORIZONTAL)

    self.panel.SetSizer(self.topLevelSizer)
    self.topLevelSizer.Add(self.windowSizer)
    self.topLevelSizer.Add(self.buttonSizer)
    self.windowSizer.Add(self.widgetSizer)

    self.settingsBook = wx.Listbook(self.panel)
    self.widgetSizer.Add(self.settingsBook)

    self.settingsBook.InsertPage(0, settingsGeneral(self,self.panelSize), "Settins")
    self.settingsBook.InsertPage(1, settingsConnection(self,self.panelSize), "Connections")
    self.settingsBook.InsertPage(2, settingsABC(self,self.panelSize), "ABC")
    self.panel.Fit()






    self.Centre()
    self.Show()

    while self.FLAG_KILL_ME is False:
        wx.GetApp().Yield()


    try:
        self.Destroy()
    except Exception as e:
        pass

def onQuit(self,event=None):
    self.FLAG_KILL_ME = True
    self.Hide()

Solution

  • Here is a standalone Listbook example taken from a working project.
    I've hacked out the meat and left the potatoes. :)

    Edit:

    I have added a simple main frame from where you activate the configuration code. The main frame contains a counter, in an attempt to convince you, that the MainLoop is still active, as you seem to believe it gets hijacked in some way.

    Hopefully, it will be of use.

    import wx
    import wx.lib.scrolledpanel as scrolled
    #from os.path import expanduser
    
    class Test(wx.Frame):
        def __init__(self, parent):
            wx.Frame.__init__(self, parent, -1, "Main Window", size=(300, 200))
            self.cnt = 0
            panel = wx.Panel(self)
            button = wx.Button(panel, label="Open Config", pos=(10, 10), size=(120, 30))
            text = wx.StaticText(panel, wx.ID_ANY, "Is the main loop still active", pos=(10, 50))
            self.counter = wx.TextCtrl(panel, wx.ID_ANY, "", pos=(10, 80), size=(120, 30))
            self.Bind(wx.EVT_BUTTON, self.OnConfig, button)
            self.timer = wx.Timer(self)
            self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
            self.Show()
            self.timer.Start(1000)
    
        def OnConfig(self, event):
            frame = Config(parent=self)
    
        def OnTimer(self, event):
            self.cnt += 1
            self.counter.SetValue(str(self.cnt))
    
    class Config(wx.Frame):
        def __init__(self,parent):
            wx.Frame.__init__(self,parent, wx.ID_ANY,"Configuration",size=(600,400))
    
            #self.home_dir = expanduser("~")
            #self.conf_dir = expanduser("~/fs2")
            #self.config_file = self.conf_dir+"/fs2.cfg"
            self.parent = parent
            # Create the first tab and add it to the listbook
            self.panel = wx.Panel(self)
            self.lb = wx.Listbook(self.panel)
    
            self.tab1 = scrolled.ScrolledPanel(self.lb, -1)
            self.tab1.SetupScrolling()
            self.tab1.SetBackgroundColour("Grey")
            self.lb.AddPage(self.tab1, "Foot Pedal")
    
    
            t1_1 = wx.StaticText(self.tab1, wx.ID_ANY, ("Pedal Device"))
            self.fc_hidfile = wx.TextCtrl(self.tab1, wx.ID_ANY, "",size=(150, -1))
            t1_2 = wx.StaticText(self.tab1, wx.ID_ANY, ("Pedal 1 *"))
            self.fc_pedal_1 = wx.ComboBox(self.tab1, wx.ID_ANY, choices=[("Jump Back"), ("Play/Pause"), ("Jump Forward"),("Timestamp"),("Unclear"),("Comment Time stamp"),("Bookmark Time stamp"),("OSD Time stamp"),("Pedal De-activated")],style=wx.CB_READONLY)
            t1_3 = wx.StaticText(self.tab1, wx.ID_ANY, ("Pedal 2 *"))
            self.fc_pedal_2 = wx.ComboBox(self.tab1, wx.ID_ANY, choices=[("Jump Back"), ("Play/Pause"), ("Jump Forward"),("Timestamp"),("Unclear"),("Comment Time stamp"),("Bookmark Time stamp"),("OSD Time stamp"),("Pedal De-activated")],style=wx.CB_READONLY)
            t1_4 = wx.StaticText(self.tab1, wx.ID_ANY, ("Pedal 3 *"))
            self.fc_pedal_3 = wx.ComboBox(self.tab1, wx.ID_ANY, choices=[("Jump Back"), ("Play/Pause"), ("Jump Forward"),("Timestamp"),("Unclear"),("Comment Time stamp"),("Bookmark Time stamp"),("OSD Time stamp"),("Pedal De-activated")],style=wx.CB_READONLY)
            t1_5 = wx.StaticText(self.tab1, wx.ID_ANY, ("Classic"))
            self.fc_classic = wx.SpinCtrl(self.tab1, wx.ID_ANY,"0", min=0, max=2)#, ("Classic Play/Pause"))
            t1sizer = wx.FlexGridSizer(10,2,5,5)
            t1sizer.Add(t1_1, 0, wx.ALL, 5)
            t1sizer.Add(self.fc_hidfile, 0, wx.ALL, 5)
            t1sizer.Add(t1_2, 0, wx.ALL, 5)
            t1sizer.Add(self.fc_pedal_1, 0, wx.ALL, 5)
            t1sizer.Add(t1_3, 0, wx.ALL, 5)
            t1sizer.Add(self.fc_pedal_2, 0, wx.ALL, 5)
            t1sizer.Add(t1_4, 0, wx.ALL, 5)
            t1sizer.Add(self.fc_pedal_3, 0, wx.ALL, 5)
            t1sizer.Add(t1_5, 0, wx.ALL, 5)
            t1sizer.Add(self.fc_classic, 0, wx.ALL, 5)
    
    
            self.tab1.SetSizer(t1sizer)
    
            self.tab2 = scrolled.ScrolledPanel(self.lb, -1)
            self.tab2.SetupScrolling()
            self.tab2.SetBackgroundColour("Grey")
            self.lb.AddPage(self.tab2, "Control")
    
            t2_1 = wx.StaticText(self.tab2, wx.ID_ANY, ("Include Hours in Time display"))
            self.fc_time_disp = wx.ComboBox(self.tab2, wx.ID_ANY, choices=[("H"),("M")],style=wx.CB_READONLY)
            t2_2 = wx.StaticText(self.tab2, wx.ID_ANY, ("Jump Length (secs) *"))
            self.fc_jump_length = wx.SpinCtrl(self.tab2, wx.ID_ANY, "3", min=1, max=15)
            t2_3 = wx.StaticText(self.tab2, wx.ID_ANY, ("Long Jump *"))
            self.fc_l_jump_length = wx.SpinCtrl(self.tab2, wx.ID_ANY,value="", min=0, max=60)
            t2_4 = wx.StaticText(self.tab2, wx.ID_ANY, ("Extra Long Jump *"))
            self.fc_xl_jump_length = wx.SpinCtrl(self.tab2, wx.ID_ANY,value="", min=0, max=600)
            t2_5 = wx.StaticText(self.tab2, wx.ID_ANY, ("Pause Jump (secs) *"))
            self.fc_pause_jump = wx.SpinCtrl(self.tab2, wx.ID_ANY, "0", min=0, max=5)
            t2_6 = wx.StaticText(self.tab2, wx.ID_ANY, ("Instant Loop length *"))
            self.fc_ill = wx.SpinCtrl(self.tab2, wx.ID_ANY, "10", min=3, max=20)
    
            t2sizer = wx.FlexGridSizer(10,2,5,5)
            t2sizer.Add(t2_1, 0, wx.ALL, 5)
            t2sizer.Add(self.fc_time_disp, 0, wx.ALL, 5)
            t2sizer.Add(t2_2, 0, wx.ALL, 5)
            t2sizer.Add(self.fc_jump_length, 0, wx.ALL, 5)
            t2sizer.Add(t2_3, 0, wx.ALL, 5)
            t2sizer.Add(self.fc_l_jump_length, 0, wx.ALL, 5)
            t2sizer.Add(t2_4, 0, wx.ALL, 5)
            t2sizer.Add(self.fc_xl_jump_length, 0, wx.ALL, 5)
            t2sizer.Add(t2_5, 0, wx.ALL, 5)
            t2sizer.Add(self.fc_pause_jump, 0, wx.ALL, 5)
            t2sizer.Add(t2_6, 0, wx.ALL, 5)
            t2sizer.Add(self.fc_ill, 0, wx.ALL, 5)
    
            self.tab2.SetSizer(t2sizer)
    
            # Create and add more tabs....
    
    #        read the config file and load in the data
    
    #        cfg = ConfigObj(infile = self.config_file)
    #        try:
    #            r_hidfile = cfg["control"]["HID_FILE_ID"]
    #        except:
    #            r_hid_file = "/dev/input/eventx"
    #        self.fc_hidfile.SetValue(r_hid_file)
    # 
    # For demo purposes set fixed values
    
            self.fc_hidfile.SetValue('/dev/input/eventx')
            self.fc_time_disp.SetStringSelection('H')
            self.fc_jump_length.SetValue(2)
            self.fc_l_jump_length.SetValue(10)
            self.fc_xl_jump_length.SetValue(15)
            self.fc_pause_jump.SetValue(1)
            self.fc_classic.SetValue(0)
            self.fc_pedal_1.SetSelection(0)
            self.fc_pedal_2.SetSelection(1)
            self.fc_pedal_3.SetSelection(2)
            self.fc_ill.SetValue(5)
    
            sizer = wx.BoxSizer(wx.VERTICAL)
            sizer.Add(self.lb, 1, wx.ALL|wx.EXPAND, 5)
            self.fc_Save = wx.Button(self.panel, wx.ID_ANY, "Save")
            self.fc_Quit = wx.Button(self.panel, wx.ID_ANY, "Quit")
            self.help_button = wx.Button(self.panel, wx.ID_ANY, "Help")
            button_sizer = wx.BoxSizer(wx.HORIZONTAL)
            button_sizer.Add(self.fc_Save)
            button_sizer.Add(self.fc_Quit)
            button_sizer.Add(self.help_button)
            sizer.Add(button_sizer)
            self.panel.SetSizer(sizer)
            self.fc_Save.Bind(wx.EVT_BUTTON, self.OnSave)
            self.fc_Quit.Bind(wx.EVT_BUTTON, self.OnQuit)
            self.help_button.Bind(wx.EVT_BUTTON, self.OnHelp)
            self.Layout()
            self.Show()
    
        def OnQuit(self,event):
            self.Destroy()
            self.Close()
    
        def OnHelp(self, event):
            #  ShowHelp(parent=None,section='fs2_Config1.pdf')
            return
    
        def OnSave(self,event):
            #cfg = ConfigObj(infile = self.config_file, create_empty=True, write_empty_values=True, list_values=False)
            # write back new configuartion values here
            #cfg["control"]["FOOTPEDAL_VPID_LOCK"] = footpedal_vpid_lock
            #cfg.write()
            self.Destroy()
    
    if __name__ == "__main__":
        app = wx.App()
        frame = Test(None)
        app.MainLoop()
    

    You'll notice, that despite the Config window being active, the Main windows counter is still active.

    enter image description here