AttributeError: 'Border' object has no attribute 'GetDC'

I’m trying to learn how to integrate a Opencv image into a wxpython frame …My app takes a picture and then displays it in the self.topPan panel… when it starts up every thing works fine , but when I take a new picture and try to redraw it to the panel I get this error

Traceback (most recent call last): File "C:\Python27\camera\WorkingExample.py", line 119, in capturing self.OnEraseBackground(self) File "C:\Python27\camera\WorkingExample.py", line 59, in OnEraseBackground dc = evt.GetDC() AttributeError: 'Border' object has no attribute 'GetDC'
I’m figuring it has something to do with having to erase the background before I repaint it , but there isn’t much on the internet of the this topic that I could find… so can someone point me in the right direction to get this done correctly ? Is this the best way to do this ? Someone could potentially take 100 of picture and each one at some point displayed in the panel to eventually get to a keep or discard option, but I’m new so baby steps Can someone point me in the direction of some good tutorials also

[code]import wx
import cv

class Border(wx.Frame):
def init(self, parent, id, title):
wx.Frame.init(self, parent, id, title, size=(300, 640))

    borderPanel = wx.Panel(self, -1) # Make a new panel inside the frame \
    borderPanel.SetBackgroundColour('#ededed') #(using as border)
   
    self.panel = wx.Panel(borderPanel, -1) # Make a new panel inside the frame
    self.panel.SetBackgroundColour('BLACK') # Set 'panels' bgcolor
   
    self.topPan = wx.Panel(self.panel, -1) # Make a subpanel for the top of 'panel'
    #topPan.SetBackgroundColour('WHITE')# Set 'topPans' bgcolor
    self.topPan.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
    self.topPan.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)

   
    smallPan = wx.Panel(self.panel , -1) # Make a subpanel for the top of 'panel'
    smallPan.SetBackgroundColour('#4f5049') # Set 'smallPans' bgcolor
   
   
   
    bbox = wx.BoxSizer(wx.VERTICAL) # Make a new sizer for 'borderPanel'
    vbox = wx.BoxSizer(wx.VERTICAL) # Make a new sizer for 'panel'
   
    bbox.Add(self.panel, 1, wx.EXPAND | wx.ALL, 20)# Add panel to border panel
    vbox.Add(self.topPan, 5, wx.EXPAND | wx.ALL, 10) # Add both subpanels to the new sizer \
    vbox.Add(smallPan, 4, wx.EXPAND | wx.ALL, 10) # in order
   
    borderPanel.SetSizer(bbox) # set 'panel' inside 'borderPanel'
    self.panel.SetSizer(vbox) # set the sizer containing 'topPan' and 'smallPan' \
    # inside 'panel
   
    ### Add the buttons to smallPan###
    self.button1=wx.Button(smallPan,label="1",pos=(30,30),size=(50,30))       
self.button1.Bind(wx.EVT_BUTTON, self.capturing,self.button1)
···
#######################################################################
    button2=wx.Button(smallPan,label="2",pos=(90,30),size=(50,30))
#button2.Bind(wx.EVT_BUTTON,self.erasebackground,button2)
    button3=wx.Button(smallPan,label="3",pos=(150,30),size=(50,30))
    button4=wx.Button(smallPan,label="4",pos=(30,70),size=(50,30))
    button5=wx.Button(smallPan,label="5",pos=(90,70),size=(50,30))
    button6=wx.Button(smallPan,label="6",pos=(150,70),size=(50,30))
    button7=wx.Button(smallPan,label="7",pos=(30,110),size=(50,30))
    button8=wx.Button(smallPan,label="8",pos=(90,110),size=(50,30))
    button9=wx.Button(smallPan,label="9",pos=(150,110),size=(50,30))
    button_star=wx.Button(smallPan,label="*",pos=(30,150),size=(50,30))
    button0=wx.Button(smallPan,label="0",pos=(90,150),size=(50,30))
    button=wx.Button(smallPan,label="#",pos=(150,150),size=(50,30))
    self.Centre()
    self.Show(True)
def OnEraseBackground(self, evt):
    """
    Add a picture to the background
    """
    # yanked from ColourDB.py
    dc = evt.GetDC()
       
    if not dc:
        dc = wx.ClientDC(self)
        rect = self.GetUpdateRegion().GetBox()
        dc.SetClippingRect(rect)
    dc.Clear()
    bmp = wx.Bitmap("test.jpg")
    image = wx.ImageFromBitmap(bmp)
    image = image.Scale(295,300, wx.IMAGE_QUALITY_HIGH)
    result = wx.BitmapFromImage(image)
   
    dc.DrawBitmap(result, 0, 0)
    return result
def capturing(self,event):
      #print "Press ESC to exit or c to capture..."

    # create windows
    cv.NamedWindow('Raw', cv.CV_WINDOW_AUTOSIZE)
    #cv.NamedWindow('Processed', cv.CV_WINDOW_AUTOSIZE)
   
    # create capture device
    device = 0 # assume we want first device
    capture = cv.CaptureFromCAM(0)
    cv.SetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_WIDTH, 640)
    cv.SetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_HEIGHT, 480)
   
   
    # check if capture device is OK
    if not capture:
        print "Error opening capture device"
        sys.exit(1)
   
    while 1:
        # do forever
   
        # capture the current frame
        frame = cv.QueryFrame(capture)
        if frame is None:
            break
   
        # mirror
        cv.Flip(frame, None, 1)
   
        # face detection
        #cv.
        #detected = cv.HaarDetectObjects(frame, haar, storage, 1.2, 2,cv.CV_HAAR_DO_CANNY_PRUNING, (100,100))
        # display webcam image
        cv.ShowImage('Raw', frame)
   
        # handle events
        k = cv.WaitKey(10)
   
        if k == 0x1b or k==0x003f: # ESC
            print 'ESC pressed. Exiting ...'
            break
   
        if k == 0x63 or k == 0x43:
            print 'capturing!'
            cv.SaveImage("test.jpg",frame)
    self.OnEraseBackground(self)
    break

app = wx.App()
Border(None, -1, ‘’)
app.MainLoop()[/code]

No, it has to do with you calling the OnEraseBackground event handler function directly and passing your frame as the evt parameter. I'm not totally sure what you are needing, but I would guess that you should be drawing your image in a EVT_PAINT handler, and then call Refresh() when you want the window to be repainted. You can then either have your OnEraseBackground do nothing or call the window's SetBackgroundStyle(wx.BG_STYLE_PAINT) method to indicate that the background should not be erased because it is going to be fully redrawn in the paint event anyway.

The "while 1:" loop in capturing() is going to cause you trouble too. You should not block the return to the event loop, otherwise no events can be delivered and your GUI will appear to be frozen. Take a look at these pages for some alternatives.

http://wiki.wxpython.org/LongRunningTasks
http://wiki.wxpython.org/Non-Blocking_Gui
http://wiki.wxpython.org/CallAfter

···

On 11/18/12 10:27 AM, aikidoguy wrote:

I'm trying to learn how to integrate a Opencv image into a wxpython
frame ...My app takes a picture and then displays it in the self.topPan
panel... when it starts up every thing works fine , but when I take a
new picture and try to redraw it to the panel I get this error

[code]Traceback (most recent call last):
   File "C:\Python27\camera\WorkingExample.py", line 119, in capturing
     self.OnEraseBackground(self)
   File "C:\Python27\camera\WorkingExample.py", line 59, in
OnEraseBackground
     dc = evt.GetDC()
AttributeError: 'Border' object has no attribute 'GetDC'
[/code]
I'm figuring it has something to do with having to erase the background
before I repaint it ,

--
Robin Dunn
Software Craftsman