Search code examples
windowswxpython

wxPython: onPaint event not called on panel update


The following code is supposed to create a window consisting of a "calibrate" button and a canvas. When the "calibrate" button is clicked, the red dot is supposed to be re-drawn on a random location on the canvas.

Instead, I see the OnPaint event is called once, in the beginning, and not afterwards. Any idea what's going on?

import wx 
import datetime
import threading
import random 

class frmMain ( wx.Frame ):

    def __init__( self, parent ):
        wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 839,553 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
        self.pos = (300,100)
        self.initGUI()

    def initGUI(self):
        self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )

        topSizer = wx.BoxSizer( wx.HORIZONTAL )

        buttonsSizer = wx.BoxSizer( wx.VERTICAL )

        self.btnCalibrate = wx.Button( self, wx.ID_ANY, u"Calibrate", wx.DefaultPosition, wx.DefaultSize, 0 )
        buttonsSizer.Add( self.btnCalibrate, 0, wx.ALL, 5 )

        topSizer.Add( buttonsSizer, 0, wx.LEFT, 5 )

        sizeCanvas = wx.BoxSizer( wx.VERTICAL )

        sizeCanvas.SetMinSize( wx.Size( 600,600 ) ) 

        self.panel=wx.Panel(self, size=(600,600))
        self.panel.SetBackgroundColour('white')
        self.firstpoint=wx.Point(300,300)
        self.secondpoint=wx.Point(400,400)
        self.panel.Bind(wx.EVT_PAINT, self.onPaint)

        sizeCanvas.Add(self.panel, 0, wx.ALIGN_LEFT, 5)

        topSizer.Add( sizeCanvas, 1, wx.ALIGN_RIGHT, 5 )


        self.SetSizer( topSizer )
        self.Layout()

        self.Centre( wx.BOTH )

        # Connect Events
        self.btnCalibrate.Bind( wx.EVT_BUTTON, self.StartCalibrate )
        self.Show(True)

    def onPaint(self,event):
        print "lalal"
        dc = wx.WindowDC(self.panel) 
        color = wx.Colour(255,0,0)
        b = wx.Brush(color) 

        dc.SetBrush(b)
        dc.DrawCircle(self.pos[0], self.pos[1], 10)

    def __del__( self ):
        pass

    def StartCalibrate( self, event ):
        size = self.GetSize()
        self.pos = (random.randrange(0, size[0] - 1, 1), random.randrange(0, size[1] - 1, 1))
        print "fixation at %d, %d" % (self.pos[0], self.pos[1])
        self.panel.Update()
        event.Skip()

if __name__ == "__main__":
    app = wx.App()
    frmMain(None) 
    app.MainLoop()

Solution

  • Use Refresh instead of Update. Update causes any pending paint events to be processed immediately, but if there are no pending paint events then nothing will be done. On the other hand, Refresh causes a paint event to be sent to the widget.