''' May 2017 @author: Burkhard A. Meier ''' import wx from wx import glcanvas from OpenGL.GL import * from OpenGL.GLUT import * #---------------------------------------------------------------------- class CanvasBase(glcanvas.GLCanvas): def __init__(self, parent): glcanvas.GLCanvas.__init__(self, parent, -1) self.context = glcanvas.GLContext(self) self.init = False # Cube 3D start rotation self.last_X = self.x = 30 self.last_Y = self.y = 30 self.Bind(wx.EVT_SIZE, self.sizeCallback) self.Bind(wx.EVT_PAINT, self.paintCallback) self.Bind(wx.EVT_LEFT_DOWN, self.mouseDownCallback) self.Bind(wx.EVT_LEFT_UP, self.mouseUpCallback) self.Bind(wx.EVT_MOTION, self.mouseMotionCallback) def sizeCallback(self, event): wx.CallAfter(self.setViewport) event.Skip() def setViewport(self): self.size = self.GetClientSize() self.SetCurrent(self.context) glViewport(0, 0, self.size.width, self.size.height) def paintCallback(self, event): wx.PaintDC(self) self.SetCurrent(self.context) if not self.init: self.initGL() self.init = True self.onDraw() def mouseDownCallback(self, event): self.CaptureMouse() self.x, self.y = self.last_X, self.last_Y = event.GetPosition() def mouseUpCallback(self, evt): self.ReleaseMouse() def mouseMotionCallback(self, evt): if evt.Dragging() and evt.LeftIsDown(): self.last_X, self.last_Y = self.x, self.y self.x, self.y = evt.GetPosition() self.Refresh(False) #---------------------------------------------------------------------- class CubeCanvas(CanvasBase): def initGL(self): # set viewing projection glMatrixMode(GL_PROJECTION) glFrustum(-0.5, 0.5, -0.5, 0.5, 1.0, 3.0) # position viewer glMatrixMode(GL_MODELVIEW) glTranslatef(0.0, 0.0, -2.0) # position object glRotatef(self.y, 1.0, 0.0, 0.0) glRotatef(self.x, 0.0, 1.0, 0.0) glEnable(GL_DEPTH_TEST) glEnable(GL_LIGHTING) glEnable(GL_LIGHT0) def onDraw(self): # clear color and depth buffers glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # draw six faces of a cube glBegin(GL_QUADS) glNormal3f(0.0, 0.0, 1.0) glVertex3f(0.5, 0.5, 0.5) glVertex3f(-0.5, 0.5, 0.5) glVertex3f(-0.5, -0.5, 0.5) glVertex3f(0.5, -0.5, 0.5) glNormal3f(0.0, 0.0, -1.0) glVertex3f(-0.5, -0.5, -0.5) glVertex3f(-0.5, 0.5, -0.5) glVertex3f(0.5, 0.5, -0.5) glVertex3f(0.5, -0.5, -0.5) glNormal3f(0.0, 1.0, 0.0) glVertex3f(0.5, 0.5, 0.5) glVertex3f(0.5, 0.5, -0.5) glVertex3f(-0.5, 0.5, -0.5) glVertex3f(-0.5, 0.5, 0.5) glNormal3f(0.0, -1.0, 0.0) glVertex3f(-0.5, -0.5, -0.5) glVertex3f(0.5, -0.5, -0.5) glVertex3f(0.5, -0.5, 0.5) glVertex3f(-0.5, -0.5, 0.5) glNormal3f(1.0, 0.0, 0.0) glVertex3f(0.5, 0.5, 0.5) glVertex3f(0.5, -0.5, 0.5) glVertex3f(0.5, -0.5, -0.5) glVertex3f(0.5, 0.5, -0.5) glNormal3f(-1.0, 0.0, 0.0) glVertex3f(-0.5, -0.5, -0.5) glVertex3f(-0.5, -0.5, 0.5) glVertex3f(-0.5, 0.5, 0.5) glVertex3f(-0.5, 0.5, -0.5) glEnd() width, height = self.size width = max(width, 1.0) height = max(height, 1.0) xScale = 180.0 / width yScale = 180.0 / height glRotatef((self.y - self.last_Y) * yScale, 1.0, 0.0, 0.0); glRotatef((self.x - self.last_X) * xScale, 0.0, 1.0, 0.0); self.SwapBuffers() #---------------------------------------------------------------------- class GUI(wx.Panel): # Subclass wxPython Panel def __init__(self, parent): wx.Panel.__init__(self, parent) menu = wx.Menu() menu.Append(wx.ID_ABOUT, "About", "wxPython GUI") menu.AppendSeparator() menu.Append(wx.ID_EXIT, "Exit", " Exit the GUI") menuBar = wx.MenuBar() menuBar.Append(menu, "File") parent.SetMenuBar(menuBar) self.textWidget = wx.TextCtrl(self, size=(280, 80), style=wx.TE_MULTILINE) button = wx.Button(self, label="Create OpenGL 3D Cube", pos=(60, 100)) self.Bind(wx.EVT_BUTTON, self.buttonCallback, button) parent.CreateStatusBar() def buttonCallback(self, event): self.textWidget.AppendText("Enjoy 3-Dimensional Space in Python.") self.textWidget.AppendText("\n*** Use your mouse to spin the Cube! ***\n\n") frame = wx.Frame(None, -1, title='Python OpenGL', size=(300, 300), pos=(400, 20)) CubeCanvas(frame) frame.Show(True) #================================================================================= app = wx.App() frame = wx.Frame(None, title="Python GUI using wxPython", size=(300, 230)) GUI(frame) frame.Show() app.MainLoop()