Search code examples
pythonwxpython

wxPython Acting on Element with Focus


In my program I have a notebook with a vertical box sizer with buttons next to it. The buttons performed actions on the list box I had on the frame. But I moved the list boxes into the tabs of the notebook. How can I act on the elements of the tab with a button that is not a child of the notebook but a sibling. Which means that the variable for the listbox is no longer in the same scope.

This brings me to the other part of my question. If I had two listboxes side by side and then some buttons, I want the buttons to act on whichever listbox has mouse focus. How would I achieve this?

I would assume my two questions are related but could be wrong. Basically I want these buttons to be able to act on whatever tab or items selected.

A small example would do wonders to help me understand this element of wxPython. I'm having trouble with the docs and examples I have found so far. I know it probably has something to do with a factory but I'm not sure how to do it and can't find any examples that work.

I realize that what I think I'm having trouble understanding is the event argument passed to functions you bind. Is that how you would solve the issue? How would you do it?

Thanks


Solution

  • This is a fun little exercise. Basically you want to traverse the widgets of the currently selected tab and check to see which item is selected in the listbox.

    Note: As mentioned in my comment to your question, the problem as I see it is that the listbox only has focus up until the moment that you press the button. As soon as you press the button, the button itself has the focus.

    Here's one approach:

    import random
    import wx
    
    ########################################################################
    class TabPanel(wx.Panel):
        #----------------------------------------------------------------------
        def __init__(self, parent):
            """"""
            wx.Panel.__init__(self, parent=parent)
    
            colors = ["red", "blue", "gray", "yellow", "green"]
            self.SetBackgroundColour(random.choice(colors))
    
            lbox = wx.ListBox(self, choices=colors)
            sizer = wx.BoxSizer(wx.VERTICAL)
            sizer.Add(lbox, 0, wx.ALL, 10)
            self.SetSizer(sizer)
    
    ########################################################################
    class DemoFrame(wx.Frame):
        """
        Frame that holds all other widgets
        """
    
        #----------------------------------------------------------------------
        def __init__(self):
            """Constructor"""        
            wx.Frame.__init__(self, None, wx.ID_ANY, 
                              "Notebook Tutorial",
                              size=(600,400)
                              )
            panel = wx.Panel(self)
            self.tab_num = 3
    
            self.notebook = wx.Notebook(panel)
            tabOne = TabPanel(self.notebook)
            self.notebook.AddPage(tabOne, "Tab 1")
    
            tabTwo = TabPanel(self.notebook)
            self.notebook.AddPage(tabTwo, "Tab 2")
    
            sizer = wx.BoxSizer(wx.VERTICAL)
            sizer.Add(self.notebook, 1, wx.ALL|wx.EXPAND, 5)
    
            btn = wx.Button(panel, label="Get Color")
            btn.Bind(wx.EVT_BUTTON, self.addPage)
            sizer.Add(btn)
    
            panel.SetSizer(sizer)
            self.Layout()
    
            self.Show()
    
        #----------------------------------------------------------------------
        def addPage(self, event):
            """"""
            page = self.notebook.GetCurrentPage()
            for widget in page.GetChildren():
                if isinstance(widget, wx.ListBox):
                    selection = widget.GetString(widget.GetSelection())
                    if selection:
                        print "Current color = " + selection
                    else:
                        print "No color selected"
    
    #----------------------------------------------------------------------
    if __name__ == "__main__":
        app = wx.App(False)
        frame = DemoFrame()
        app.MainLoop()
    

    I do get an annoying error of sorts on Xubuntu, but I think it's a warning and it doesn't effect the running the code above. This is what I am getting:

    python:12770): Gtk-CRITICAL **: IA__gtk_tree_model_iter_nth_child: assertion 'n >= 0' failed
    

    I don't believe this is something to worry about though. It's probably just an artifact of using a version of wxPython that has its warnings enabled.