Samuel L Jackson
Samuel L Jackson

Reputation: 45

Getting an error on button events in wxPython

I'm facing the following problem - Whenever I try to make an event listener to any of my buttons I get the following error:

    self.button_compute.Bind(wx.EVT_BUTTON, self.on_click)
    AttributeError: 'BMICalculator' object has no attribute 'button_compute'

I tried the suggested solution in this thread: AttributeError: 'module' object has no attribute 'PyScrolledWindow' in wxPython ,but it didn't work for me.

The program is for calculating the BMI and here's the code:

import wx

class BMICalculator(wx.Frame):
    def __init__(self, parent, id):
        wx.Frame.__init__(self, parent, id, "BMI calculator", (600, 800))
        panel = wx.Panel(self)
        self.Centre()
        #Creating the buttons and text fields
        static_text_height = wx.StaticText(panel, -1, "Height", (170, 10))
        height = wx.SpinCtrl(panel, -1, pos=(164, 40), size=(60, -1))
        static_text_weight = wx.StaticText(panel, -1, "Weight", (170, 100))
        weight = wx.SpinCtrl(panel, -1, pos=(164, 130), size=(60, -1))

        button_compute = wx.Button(panel, label="Compute", pos=(110, 180), size=(60, -1))
        button_cancel = wx.Button(panel, label="Cancel", pos=(210, 180), size=(60, -1))

        result_text = wx.StaticText(panel, -1, "Enter your height and weight and press compute", (68, 220))
        #Adding the events for the buttons (Where I get the error)
        self.button_compute.Bind(wx.EVT_BUTTON, self.on_click)

        self.button_cancel.Bind(wx.EVT_CLOSE, self.click_close)

    def compute_BMI(height, weight):
        #BMI = x KG / (y M *  y M)
        height_m = height/100
        BMI = weight/(height_m *  height_m)
        return BMI

    def click_close(self, event):
        self.Close(True)

    def on_click(self, event):
        result_text.SetValue(compute_BMI(height.GetValue(), weight.GetValue()))

def main():
    app = wx.App()
    frame = BMICalculator(None, -1)
    frame.Show()
    app.MainLoop()
    enter code here

if __name__ == '__main__':
    main()

Any help will be appreciated!

Upvotes: 2

Views: 929

Answers (1)

Aaron
Aaron

Reputation: 11075

When you create button_compute you leave it as a local variable to the function. When you try to bind the event, you then try to read from an instance attribute that you haven't created yet. You actually do this in many cases, but your script is erring out on the first one. Add self.xxx to your assignments to make instance attributes rather than local variables to the function.

import wx

class BMICalculator(wx.Frame):
    def __init__(self, parent, id):
        wx.Frame.__init__(self, parent, id, "BMI calculator", (600, 800))
        self.panel = wx.Panel(self)
        self.Centre()
        #Creating the buttons and text fields
        self.static_text_height = wx.StaticText(self.panel, -1, "Height", (170, 10))
        self.height = wx.SpinCtrl(self.panel, -1, pos=(164, 40), size=(60, -1))
        self.static_text_weight = wx.StaticText(self.panel, -1, "Weight", (170, 100))
        self.weight = wx.SpinCtrl(self.panel, -1, pos=(164, 130), size=(60, -1))

        self.button_compute = wx.Button(self.panel, label="Compute", pos=(110, 180), size=(60, -1))
        self.button_cancel = wx.Button(self.panel, label="Cancel", pos=(210, 180), size=(60, -1))

        self.result_text = wx.StaticText(self.panel, -1, "Enter your height and weight and press compute", (68, 220))
        #Adding the events for the buttons (Where I get the error)
        self.button_compute.Bind(wx.EVT_BUTTON, self.on_click)

        self.button_cancel.Bind(wx.EVT_CLOSE, self.click_close)

    def compute_BMI(height, weight):
        #BMI = x KG / (y M *  y M)
        height_m = height/100
        BMI = weight/(height_m *  height_m)
        return BMI

    def click_close(self, event):
        self.Close(True)

    def on_click(self, event):
        self.result_text.SetValue(self.compute_BMI(self.height.GetValue(), self.weight.GetValue()))

def main():
    app = wx.App()
    frame = BMICalculator(None, -1)
    frame.Show()
    app.MainLoop()
    #enter code here

if __name__ == '__main__':
    main()

Upvotes: 2

Related Questions