Search code examples
variableswxpythonurl-rewritingpanelsrebuild

How to rebuild panels in wxpython in function of a variable?


I searched a lot to do this but nothing of what I tried work. Now, as last attemp, I am trying with pubsub, but I can get nothing of worth, that's why I am asking for help now :). This is an minimal (as best I can do it :)) example of what I want. PanelB gets information in a list (box), and when someone of the items is selected, PanelA should change according to him. Thank you in advance.

from wx.lib.pubsub import Publisher
import wx

global name
name  = 'none, please select an item'

class PanelA(wx.Panel):
   def __init__(self, parent, name):
       wx.Panel.__init__(self, parent)
       self.hbox = wx.BoxSizer(wx.HORIZONTAL)
       self.vbox = wx.BoxSizer(wx.VERTICAL)
       str = name
       txt = wx.StaticText(self, -1, "You have selected " + str, (20, 100))
       self.hbox.Add(txt, 1, wx.EXPAND | wx.ALL, 20)

class PanelB(wx.Panel):
   def __init__(self, parent):
       wx.Panel.__init__(self, parent)

       self.hbox = wx.BoxSizer(wx.HORIZONTAL)
       self.vbox = wx.BoxSizer(wx.VERTICAL)

       self.listbox = wx.ListBox(self, -1)
       self.hbox.Add(self.listbox, 1, wx.EXPAND | wx.ALL, 20)

       self.btnPanel = wx.Panel(self, -1)      
       self.new = wx.Button(self.btnPanel,label='Add', size=(90, 30))
       self.new.Bind(wx.EVT_BUTTON, self.NewItem)

       self.vbox.Add((-1, 20))
       self.vbox.Add(self.new)

       self.btnPanel.SetSizer(self.vbox)
       self.hbox.Add(self.btnPanel, 0.6, wx.EXPAND | wx.RIGHT, 20)
       self.SetSizer(self.hbox)

       self.Bind(wx.EVT_LISTBOX, self.onSelect)

    def onSelect(self, event):
       name_selected = self.listbox.GetStringSelection()
       Publisher().sendMessage(("ListBox"), name_selected)

def NewItem(self, event):
       text = wx.GetTextFromUser('Nombre', 'Programa a salvar')
       if text != '':
           self.listbox.Append(text)

class MainFrame(wx.Frame):
   def __init__(self, parent, id, title, *args, **kw):

       wx.Frame.__init__(self, parent, id, title, size = (800,300))

       self.splitter = wx.SplitterWindow(self, -1, style=wx.SP_3D)

       self.lc1 = PanelB(self.splitter)
       Publisher().subscribe(self.OnSelect, ("ListBox"))
       self.lc2 = PanelA(self.splitter, name)
       self.splitter.SplitVertically(self.lc1, self.lc2)

       sizer = wx.BoxSizer(wx.HORIZONTAL)
       sizer.Add(self.splitter, 1, wx.EXPAND)
       self.SetSizer(sizer)

       self.Centre()
       self.Show(True)

   def OnSelect(self, name_selected):
       name = name_selected
       #I stucked here

if __name__ == "__main__":
   app = wx.App()
   frame = MainFrame(None,-1,'Mi aplicacion')
   app.MainLoop()

Solution

  • This is not beautiful solution, basically you can just destroy PanelA then call that panel again, maybe like this:

    def OnSelect(self, name_selected):
        self.lc2.Destroy()
        self.lc2 = PanelA(self.splitter, name_selected.data)
    

    Hope this can help.

    UPDATE (08/24/2012): added some code

    Okey we should not destroy the panel. I'm using your code and modified it a bit. I removed global variable name and added changeName(name) function to PanelA so that when MainFrame.onSelect() is called it will call changeName(). It's not beautiful but hope this can help.

    import wx
    from wx.lib.pubsub import Publisher
    
    class PanelA(wx.Panel):
    
        def __init__(self, parent):
            wx.Panel.__init__(self, parent)
            self.hbox = wx.BoxSizer(wx.HORIZONTAL)
            self.vbox = wx.BoxSizer(wx.VERTICAL)
            name = "none, please select an item"
            self.txt = wx.StaticText(self, -1, "You have selected " + name,
                                     (50, 100))
            self.hbox.Add(self.txt, 1, wx.EXPAND|wx.ALL, 30)
    
        def changeName(self, name):
            self.hbox.Hide(self.txt)
            self.hbox.Remove(self.txt)
            self.txt = wx.StaticText(self, -1, "You have selected " + name, (50, 100))
            self.hbox.Add(self.txt, 1, wx.EXPAND|wx.ALL, 30)
    
    
    class PanelB(wx.Panel):
    
        def __init__(self, parent):
            wx.Panel.__init__(self, parent)
    
            self.hbox = wx.BoxSizer(wx.HORIZONTAL)
            self.vbox = wx.BoxSizer(wx.VERTICAL)
    
            self.listbox = wx.ListBox(self, -1)
            self.hbox.Add(self.listbox, 1, wx.EXPAND|wx.ALL, 20)
    
            self.btnPanel = wx.Panel(self, -1)      
            self.new = wx.Button(self.btnPanel,label='Add', size=(90, 30))
            self.new.Bind(wx.EVT_BUTTON, self.NewItem)
    
            self.vbox.Add((-1, 20))
            self.vbox.Add(self.new)
    
            self.btnPanel.SetSizer(self.vbox)
            self.hbox.Add(self.btnPanel, 0.6, wx.EXPAND|wx.RIGHT, 20)
            self.SetSizer(self.hbox)
    
            self.Bind(wx.EVT_LISTBOX, self.onSelect)
    
        def onSelect(self, event):
            name_selected = self.listbox.GetStringSelection()
            Publisher().sendMessage("ListBox", name_selected)
    
        def NewItem(self, event):
            text = wx.GetTextFromUser('Nombre', 'Programa a salvar')
            if text != '':
                self.listbox.Append(text)
    
    
    class MainFrame(wx.Frame):
    
       def __init__(self, parent, id, title, *args, **kw):
    
           wx.Frame.__init__(self, parent, id, title, size = (800,300))
           self.splitter = wx.SplitterWindow(self, -1, style=wx.SP_3D)
           Publisher().subscribe(self.OnSelect, "ListBox")
    
           self.lc1 = PanelB(self.splitter)
           self.lc2 = PanelA(self.splitter)
           self.splitter.SplitVertically(self.lc1, self.lc2)
    
           self.sizer = wx.BoxSizer(wx.HORIZONTAL)
           self.sizer.Add(self.splitter, 1, wx.EXPAND)
           self.SetSizer(self.sizer)
           self.Layout()
    
           self.Centre()
    
       def OnSelect(self, name_selected):
           name = name_selected
           self.lc2.changeName(name.data)
    
    
    if __name__ == "__main__":
        app = wx.PySimpleApp()
        frame = MainFrame(None,-1,'Mi aplicacion')
        frame.Show()
        app.MainLoop()