pythonwxpython

Is it possible to create a function to increment or decrease a variable by one, without looping or recursion(wxpython)


I have logical problem in my script. This script is supposed to create two buttons namely, add_button and subtract_button. When the add button is clicked it will increment a variable by one and if it was clicked again it should add 1 to the variable bringing the value to two. Also when the subtract button is clicked it should subtract 1 from the variable. Now that the variable is 2 when the subtract button is clicked the resultant value should be 1 and when clicked again it should become zero. How do I achieve this WITHOUT using loop and recursion? I have tried and tried without success..


class ButtonBasic(wx.Frame):
    def __init__(self, parent):
        super(ButtonBasic, self).__init__(parent)
        self.frame = wx.Panel(self)
        self.index=0
        self.next_list=[]
        self.previous_list = []
        self.but_next = wx.Button(self.frame, label="Next")
        self.but_prev = wx.Button(self.frame, label="Previous")
        self.Bind(wx.EVT_BUTTON, lambda event: self.next(self.index, self.next_list), self.but_next)
        self.Bind(wx.EVT_BUTTON, lambda event: self.prev(self.index, self.next_list), self.but_prev)
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.but_next)
        self.sizer.Add(self.but_prev)
        self.frame.SetSizer(self.sizer)
        self.frame.Layout()
    def next(self, idx, next_list):
        idx+=1
        if len(next_list)==1:
            next_list[0]=idx + next_list[0]
            idx=next_list[0]
            print(idx)
        else:
            next_list.append(idx)
            idx = next_list[0]
            print(idx)
    def prev(self, idx, next_list):
        idx-=1
        if len(next_list)==1:
            print(f"before substracting: {idx}")
            next_list[0]=idx - next_list[0]
            print(f"After substracting: {idx}")
            idx=next_list[0]
            print(idx)
        else:
            next_list.append(idx)
            idx = next_list[0]
            print(idx)
            
    
if __name__=='__main__':
    app = wx.App()
    frame = ButtonBasic(None)
    frame.Show()
    app.MainLoop()

Solution

  • The easiest way, is to forget lambda functions and use specific instance variables for specific buttons, not local variables, after all you are declaring specific functions for each button event i.e.:

    import wx
    
    class ButtonBasic(wx.Frame):
        def __init__(self, parent):
            super(ButtonBasic, self).__init__(parent)
            self.frame = wx.Panel(self)
            self.next_index = 0
            self.previous_index = 0
            self.next_list=[]
            self.previous_list = []
            self.but_next = wx.Button(self.frame, label="Next")
            self.but_prev = wx.Button(self.frame, label="Previous")
            self.Bind(wx.EVT_BUTTON, self.next, self.but_next)
            self.Bind(wx.EVT_BUTTON, self.prev, self.but_prev)
            self.Bind(wx.EVT_CLOSE, self.OnClose)
            self.sizer = wx.BoxSizer(wx.VERTICAL)
            self.sizer.Add(self.but_next)
            self.sizer.Add(self.but_prev)
            self.frame.SetSizer(self.sizer)
            self.frame.Layout()
    
        def next(self, event):
            self.next_index += 1
            self.next_list.append(self.next_index)
            print(self.next_index)
    
        def prev(self, event):
            self.previous_index -= 1
            self.previous_list.append(self.previous_index)
            print(self.previous_index)
    
        def OnClose(self, event):
            print("Next History:", self.next_list)
            print("Previous History:", self.previous_list)
            self.Destroy()
    
    if __name__=='__main__':
        app = wx.App()
        frame = ButtonBasic(None)
        frame.Show()
        app.MainLoop()
    

    However, as your code and description don't quite match, you may want a single variable shared between the two buttons. In which case the code could need to be like this:

    import wx
    
    class ButtonBasic(wx.Frame):
        def __init__(self, parent):
            super(ButtonBasic, self).__init__(parent)
            self.frame = wx.Panel(self)
            self.index = 0
            self.next_list=[]
            self.previous_list = []
            self.but_next = wx.Button(self.frame, label="Next")
            self.but_prev = wx.Button(self.frame, label="Previous")
            self.Bind(wx.EVT_BUTTON, self.next, self.but_next)
            self.Bind(wx.EVT_BUTTON, self.prev, self.but_prev)
            self.Bind(wx.EVT_CLOSE, self.OnClose)
            self.sizer = wx.BoxSizer(wx.VERTICAL)
            self.sizer.Add(self.but_next)
            self.sizer.Add(self.but_prev)
            self.frame.SetSizer(self.sizer)
            self.frame.Layout()
    
        def next(self, event):
            self.index += 1
            self.next_list.append(self.index)
            print(self.index)
    
        def prev(self, event):
            self.index -= 1
            self.previous_list.append(self.index)
            print(self.index)
    
        def OnClose(self, event):
            print("Next History:", self.next_list)
            print("Previous History:", self.previous_list)
            self.Destroy()
    
    if __name__=='__main__':
        app = wx.App()
        frame = ButtonBasic(None)
        frame.Show()
        app.MainLoop()