The program shown on this page seems no longer to run, perhaps due to changes in wxPython. [[GLCanvas update]] is an example which does run as of August 2012. To get the below code to run you need to install PyOpenGL. If you have pip installed you can do so by: {{{ #pip install PyOpenGL }}} == About == I could not find any information on the wiki about the glcanvas module, and most of the information here is interpreted from the [[http://www.wxwidgets.org/manuals/stable/wx_wxglcanvas.html|wxGLCanvas Documentation]], the [[http://www.wxwidgets.org/wiki/index.php/WxGLCanvas|wxWidgets wxGLCanvas Page]], and personal experience. == Installation == To install the 'glcanvas' module, make sure to enable BUILD_GLCANVAS when building wxPython. == Example Usage == {{{ try: import wx from wx import glcanvas except ImportError: raise ImportError, "Required dependency wx.glcanvas not present" try: from OpenGL.GL import * except ImportError: raise ImportError, "Required dependency OpenGL not present" class GLFrame(wx.Frame): """A simple class for using OpenGL with wxPython.""" def __init__(self, parent, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE, name='frame'): # # Forcing a specific style on the window. # Should this include styles passed? style = wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE super(GLFrame, self).__init__(parent, id, title, pos, size, style, name) self.GLinitialized = False attribList = (glcanvas.WX_GL_RGBA, # RGBA glcanvas.WX_GL_DOUBLEBUFFER, # Double Buffered glcanvas.WX_GL_DEPTH_SIZE, 24) # 24 bit # # Create the canvas self.canvas = glcanvas.GLCanvas(self, attribList=attribList) # # Set the event handlers. self.canvas.Bind(wx.EVT_ERASE_BACKGROUND, self.processEraseBackgroundEvent) self.canvas.Bind(wx.EVT_SIZE, self.processSizeEvent) self.canvas.Bind(wx.EVT_PAINT, self.processPaintEvent) # # Canvas Proxy Methods def GetGLExtents(self): """Get the extents of the OpenGL canvas.""" return self.canvas.GetClientSize() def SwapBuffers(self): """Swap the OpenGL buffers.""" self.canvas.SwapBuffers() # # wxPython Window Handlers def processEraseBackgroundEvent(self, event): """Process the erase background event.""" pass # Do nothing, to avoid flashing on MSWin def processSizeEvent(self, event): """Process the resize event.""" if self.canvas.GetContext(): # Make sure the frame is shown before calling SetCurrent. self.Show() self.canvas.SetCurrent() size = self.GetGLExtents() self.OnReshape(size.width, size.height) self.canvas.Refresh(False) event.Skip() def processPaintEvent(self, event): """Process the drawing event.""" self.canvas.SetCurrent() # This is a 'perfect' time to initialize OpenGL ... only if we need to if not self.GLinitialized: self.OnInitGL() self.GLinitialized = True self.OnDraw() event.Skip() # # GLFrame OpenGL Event Handlers def OnInitGL(self): """Initialize OpenGL for use in the window.""" glClearColor(1, 1, 1, 1) def OnReshape(self, width, height): """Reshape the OpenGL viewport based on the dimensions of the window.""" glViewport(0, 0, width, height) glMatrixMode(GL_PROJECTION) glLoadIdentity() glOrtho(-0.5, 0.5, -0.5, 0.5, -1, 1) glMatrixMode(GL_MODELVIEW) glLoadIdentity() def OnDraw(self, *args, **kwargs): "Draw the window." glClear(GL_COLOR_BUFFER_BIT) # Drawing an example triangle in the middle of the screen glBegin(GL_TRIANGLES) glColor(0, 0, 0) glVertex(-.25, -.25) glVertex(.25, -.25) glVertex(0, .25) glEnd() self.SwapBuffers() app = wx.PySimpleApp() frame = GLFrame(None, -1, 'GL Window') frame.Show() app.MainLoop() app.Destroy() }}}