pythonwxpythonwxnotebook

How to generate new pages on wxPython notebook with close buttons?


I have the following Toy Example code in which I create two tabs within a wxPython notebook. There is a button to add new pages and within each page I want to have a button that closes the page. However the below code does no action when clicking on the close buttons.

import wx

class TabPanel(wx.Panel):
    def __init__(self, parent, pageNum):
        self.parent = parent
        self.pageNum = pageNum
        wx.Panel.__init__(self, parent=parent)

        btn = wx.Button(self, label="Close Page " + str(pageNum))
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(btn, 0, wx.ALL, 10)
        self.SetSizer(sizer)

        btn.Bind(wx.EVT_BUTTON, self.closeTab)

    def closeTab(self,event):
        self.Close()

class DemoFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, "Notebook", size=(600,400))
        panel = wx.Panel(self)
        self.tab_num = 2

        self.notebook = wx.Notebook(panel)
        tabOne = TabPanel(self.notebook, 1)
        self.notebook.AddPage(tabOne, "Page 1")

        tabTwo = TabPanel(self.notebook, 2)
        self.notebook.AddPage(tabTwo, "Page 2")

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.notebook, 1, wx.ALL|wx.EXPAND, 5)

        btn = wx.Button(panel, label="Add Page")
        btn.Bind(wx.EVT_BUTTON, self.addPage)
        sizer.Add(btn)

        panel.SetSizer(sizer)
        self.Layout()
        self.Show()

    def addPage(self, event):
        self.tab_num += 1
        new_tab = TabPanel(self.notebook, self.tab_num)
        self.notebook.AddPage(new_tab, "Page %s" % self.tab_num)

if __name__ == "__main__":
    app = wx.App(False)
    frame = DemoFrame()
    app.MainLoop()

That code produces below window:

Notebook program

Problem

The close buttons aren't doing any action.

Question

How should I change my code in order to get the close button to close the corresponding page where it's located?


Solution

  • It could be easier if you use the GetSelection() method of a wx.Notebook. The method returns the index of the currently selected page. After this, you can directly remove the selected page.

    Code with comments (####):

    import wx
    
    class TabPanel(wx.Panel):
        def __init__(self, parent, pageNum):
            self.parent = parent
            self.pageNum = pageNum
            wx.Panel.__init__(self, parent=parent)
    
            btn = wx.Button(self, label="Close Page " + str(pageNum))
            sizer = wx.BoxSizer(wx.VERTICAL)
            sizer.Add(btn, 0, wx.ALL, 10)
            self.SetSizer(sizer)
    
            btn.Bind(wx.EVT_BUTTON, self.closeTab)
    
        def closeTab(self,event):
            #### Just one line and no extra variable to remove the selected page
            self.parent.RemovePage(self.parent.GetSelection())
    
    class DemoFrame(wx.Frame):
        def __init__(self):
            wx.Frame.__init__(self, None, wx.ID_ANY, "Notebook", size=(600,400))
            panel = wx.Panel(self)
            self.tab_num = 2
    
            self.notebook = wx.Notebook(panel)
            tabOne = TabPanel(self.notebook, 1)
            self.notebook.AddPage(tabOne, "Page 1")
    
            tabTwo = TabPanel(self.notebook, 2)
            self.notebook.AddPage(tabTwo, "Page 2")
    
            sizer = wx.BoxSizer(wx.VERTICAL)
            sizer.Add(self.notebook, 1, wx.ALL|wx.EXPAND, 5)
    
            btn = wx.Button(panel, label="Add Page")
            btn.Bind(wx.EVT_BUTTON, self.addPage)
            sizer.Add(btn)
    
            panel.SetSizer(sizer)
            self.Layout()
            self.Show()
    
        def addPage(self, event):
            self.tab_num += 1
            new_tab = TabPanel(self.notebook, self.tab_num)
            self.notebook.AddPage(new_tab, "Page %s" % self.tab_num)
    
    if __name__ == "__main__":
        app = wx.App(False)
        frame = DemoFrame()
        app.MainLoop()