views:

46

answers:

2

I have been hitting a dead end with this program. I am trying to build a class that will let me control the BIP's of a button when it is in use. so far this is what i have (see following.) It keeps running this weird error TypeError: 'module' object is not callable - I, coming from C++ and C# (for some reason the #include... is so much easier) , have no idea what that means, Google is of no help so... I know I need some real help with syntax and such - anything would be helpful. I know there are a lot of questions in this I would really appreciate the help!

Note: The base code found here was used to create a skeleton for this 'custom button class'

Custom Button

import wx
from wxPython.wx import *

class Custom_Button(wx.PyControl):

                                    # The BMP's
# AM I DOING THIS RIGHT? - I am trying to get empty 'global' 
# variables within the class
    Mouse_over_bmp = None #wxEmptyBitmap(1,1,1)   # When the mouse is over
    Norm_bmp = None #wxEmptyBitmap(1,1,1)         # The normal BMP
    Push_bmp = None #wxEmptyBitmap(1,1,1)         # The down BMP

    Pos_bmp = wx.Point(0,0)         # The posisition of the button

    def __init__(self, parent, NORM_BMP, PUSH_BMP, MOUSE_OVER_BMP,
                 pos, size, text="", id=-1, **kwargs):
        wx.PyControl.__init__(self,parent, id, **kwargs)

# The conversions, hereafter, were to solve another but. I don't know if it is 
# necessary to do this since the source being given to the class (in this case)
# is a BMP - is there a better way to prevent an error that i have not
# stumbled accost? 

        # Set the BMP's to the ones given in the constructor
        self.Mouse_over_bmp = wx.Bitmap(wx.Image(MOUSE_OVER_BMP, wx.BITMAP_TYPE_ANY).ConvertToBitmap())
        self.Norm_bmp = wx.Bitmap(wx.Image(NORM_BMP, wx.BITMAP_TYPE_ANY).ConvertToBitmap())
        self.Push_bmp = wx.Bitmap(wx.Image(PUSH_BMP, wx.BITMAP_TYPE_ANY).ConvertToBitmap())
        self.Pos_bmp = self.pos

        self.Bind(wx.EVT_LEFT_DOWN, self._onMouseDown)
        self.Bind(wx.EVT_LEFT_UP, self._onMouseUp)
        self.Bind(wx.EVT_LEAVE_WINDOW, self._onMouseLeave)
        self.Bind(wx.EVT_ENTER_WINDOW, self._onMouseEnter)
        self.Bind(wx.EVT_ERASE_BACKGROUND,self._onEraseBackground)
        self.Bind(wx.EVT_PAINT,self._onPaint)

        self._mouseIn = self._mouseDown = False

    def _onMouseEnter(self, event):
        self._mouseIn = True

    def _onMouseLeave(self, event):
        self._mouseIn = False

    def _onMouseDown(self, event):
        self._mouseDown = True

    def _onMouseUp(self, event):
        self._mouseDown = False
        self.sendButtonEvent()

    def sendButtonEvent(self):
        event = wx.CommandEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED, self.GetId())
        event.SetInt(0)
        event.SetEventObject(self)
        self.GetEventHandler().ProcessEvent(event)

    def _onEraseBackground(self,event):
        # reduce flicker
        pass

    def _onPaint(self, event):
        dc = wx.BufferedPaintDC(self)
        dc.SetFont(self.GetFont())
        dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
        dc.Clear()
        dc.DrawBitmap(self.Norm_bmp)

        # draw whatever you want to draw
        # draw glossy bitmaps e.g. dc.DrawBitmap
        if self._mouseIn:   # If the Mouse is over the button
            dc.DrawBitmap(self, self.Mouse_over_bmp, self.Pos_bmp, useMask=False)
        if self._mouseDown: # If the Mouse clicks the button
            dc.DrawBitmap(self, self.Push_bmp, self.Pos_bmp, useMask=False)

Main.py

import wx
import Custom_Button
from wxPython.wx import *

ID_ABOUT = 101
ID_EXIT  = 102

class MyFrame(wx.Frame):
    def __init__(self, parent, ID, title):
        wxFrame.__init__(self, parent, ID, title,
                         wxDefaultPosition, wxSize(400, 400))

        self.CreateStatusBar()
        self.SetStatusText("Program testing custom button overlays")
        menu = wxMenu()
        menu.Append(ID_ABOUT, "&About", "More information about this program")
        menu.AppendSeparator()
        menu.Append(ID_EXIT, "E&xit", "Terminate the program")
        menuBar = wxMenuBar()
        menuBar.Append(menu, "&File");
        self.SetMenuBar(menuBar)

        self.Button1 = Custom_Button(self, parent, -1, 
                                "D:/Documents/Python/Normal.bmp", 
                                "D:/Documents/Python/Clicked.bmp",
                                "D:/Documents/Python/Over.bmp",
                                wx.Point(200,200), wx.Size(300,100))

        EVT_MENU(self, ID_ABOUT, self.OnAbout)
        EVT_MENU(self, ID_EXIT,  self.TimeToQuit)

    def OnAbout(self, event):
        dlg = wxMessageDialog(self, "Testing the functions of custom "
                              "buttons using pyDev and wxPython",
                              "About", wxOK | wxICON_INFORMATION)
        dlg.ShowModal()
        dlg.Destroy()


    def TimeToQuit(self, event):
        self.Close(true)



class MyApp(wx.App):
    def OnInit(self):
        frame = MyFrame(NULL, -1, "wxPython | Buttons")
        frame.Show(true)
        self.SetTopWindow(frame)
        return true

app = MyApp(0)
app.MainLoop()

Errors (and traceback)

/home/wallter/python/Custom Button overlay/src/Custom_Button.py:8: DeprecationWarning: The wxPython compatibility package is no longer automatically generated or actively maintained.  Please switch to the wx package as soon as possible.

I have never been able to get this to go away whenever using wxPython any help?

  from wxPython.wx import *
Traceback (most recent call last):
  File "/home/wallter/python/Custom Button overlay/src/Main.py", line 57, in <module>
    app = MyApp(0)
  File "/usr/lib/python2.6/dist-packages/wx-2.8-gtk2-unicode/wx/_core.py", line 7978, in __init__
    self._BootstrapApp()
  File "/usr/lib/python2.6/dist-packages/wx-2.8-gtk2-unicode/wx/_core.py", line 7552, in _BootstrapApp
    return _core_.PyApp__BootstrapApp(*args, **kwargs)
  File "/home/wallter/python/Custom Button overlay/src/Main.py", line 52, in OnInit
    frame = MyFrame(NULL, -1, "wxPython | Buttons")
  File "/home/wallter/python/Custom Button overlay/src/Main.py", line 32, in __init__
    wx.Point(200,200), wx.Size(300,100))
TypeError: 'module' object is not callable

I have tried removing the "wx.Point(200,200), wx.Size(300,100))" just to have the error move up to the line above. Have I declared it right? help?

Prevous questions with this code: here

+2  A: 

Commented out this whole thing and the error went away and a window popped up:

 self.Button1 = Custom_Button(self, parent, -1, 
                              "D:/Documents/Python/Normal.bmp", 
                              "D:/Documents/Python/Clicked.bmp",
                              "D:/Documents/Python/Over.bmp",
                              wx.Point(200,200), wx.Size(300,100))

So getting somewhere here...

okay found the problem:

It's the import Custom_Button. That just imports the module. You want to use the class with the same name in that module instead so:

from Custom_Button import Custom_Button

And that problem is fixed. You can then move on to the next error...

It was a bit hard to see the problem right away for me because you're programming in a different style than Python. Unlike other programming languages, Python has a particular Programming Style defined in a document. There are slight deviations from it here and there but overall most good Python developers follow it rather closely because it makes sense and helps make spotting problems easier.

Official Python Style Guide

Google Version

Google version adds more to it and is a bit more restrictive even.

So it this case the module files should instead named custom_button.py and main.py. The class should be named CustomButton.

Khorkrak
what would an alternative be? I haven't been able to find another way to import the WX library.
Wallter
Just import the module(s) that you are actually going to use in your program instead of everything. Makes things easier to find - as in well where the heck did this function come from etc.
Khorkrak
+1  A: 

When you import a module in Python, think of it as importing a namespace one level up in C#

For instance in C#, when you say
import System.IO; you can specify
var file = new File("a.txt");
But if you just say import System; you have to say
var file = new IO.File("a.txt");

In Python if you did the equivilent import System.IO you'd still need to say
file = IO.File("a.txt")

In order to not need to preface it in Python, you'd either need to say
from System.IO import File or from System.IO import * which is more like the C# version.

The advantage of being able to specify specific classes is when you have namespaces with lots of classes, or maybe there are conflicting class names in 2 modules you want to import. In C# you'd either need to alias the namespace or specify the full name, where you can instead just import the specific ones you want in Python.

Davy8