luxz
luxz

Reputation: 5

Python TypeError when using class (wx.Python)

This program is that wx.textctrl is written "clicked" when button is clicked.

This code runs without error.

import wx

class Mainwindow(wx.Frame):

    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(300, 300))
        panel = wx.Panel(self, -1)

        vbox = wx.BoxSizer(wx.VERTICAL)

        hbox1 = wx.BoxSizer(wx.HORIZONTAL)
        btn = wx.Button(panel, -1, 'OK', size=(70, 30))
        btn.Bind(wx.EVT_BUTTON, self.click_btn) #line 12
        hbox1.Add(btn, 0)
        vbox.Add(hbox1, 0)

        hbox2 = wx.BoxSizer(wx.HORIZONTAL) 
        self.tc = wx.TextCtrl(panel, -1, style=wx.TE_MULTILINE)
        hbox2.Add(self.tc, 1, wx.EXPAND) 
        vbox.Add(hbox2, 1, wx.EXPAND)

        panel.SetSizer(vbox)

        self.Centre()
        self.Show(True)


    def click_btn(self, event): #line 27
        self.tc.WriteText("clicked\n") #line 28



if __name__=="__main__":
    app = wx.App()
    Mainwindow(None, -1, u"sample")
    app.MainLoop()

But if this code change in this way, it gets error.

change to line 12.

btn.Bind(wx.EVT_BUTTON, Click_btn.click_btn)

change to line 27 and 28.

class Click_btn:
    def click_btn(self, event):
        self.tc.WriteText("clicked\n")

The error is: Typeerror: unbound method click_btn() must be called with Click_btn instance as first argument (got CommandEvent instance instead)

I don't know how to cope with this error.

*Postscript

I read answer,and this code change. But it don't run...

change to line 12.

button = Click_btn()
btn.Bind(wx.EVT_BUTTON, button.click_btn)

change to line 27 and 28.

class Click_btn(Mainwindow):
    def click_btn(self, event):
        Mainwindow.tc.WriteText("clicked\n")

Please teach point that I should change.

Upvotes: 1

Views: 198

Answers (2)

Achim
Achim

Reputation: 15722

First of all you should drive your class from object:

class Click_btn:
    def click_btn(self, event):
        self.tc.WriteText("clicked\n")

But that's not the problem. To get a bound method, you have to write your Bind like this:

# create an instance
button = Click_btn()
# and now assign the click_btn method of that instance
btn.Bind(wx.EVT_BUTTON, button.click_btn)

Upvotes: 1

Joran Beasley
Joran Beasley

Reputation: 114098

class Click_btn:
    @classmethod
    def click_btn(cls, event):
        cls.tc.WriteText("clicked\n") #this will probably break now

this will allow you to call it on the class rather than an instance of the class

the class is Click_btn

an instance would be btn = Click_btn() (btn is the instance of Click_btn)

Upvotes: 2

Related Questions