2013-11-10 2 views
0

Привет, поэтому у меня есть приложение, в котором у меня есть окно, отображающее график matplotlib.Как совместить wxPython, matplotlib и Pyopengl

т.е. таких, как это:

from numpy import arange, sin, pi 
import matplotlib 
matplotlib.use('WXAgg') 

from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas 
from matplotlib.backends.backend_wx import NavigationToolbar2Wx 
from matplotlib.figure import Figure 

import wx 

class CanvasPanel(wx.Panel): 
    def __init__(self, parent): 
     wx.Panel.__init__(self, parent) 
     self.figure = Figure() 
     self.axes = self.figure.add_subplot(111) 
     self.canvas = FigureCanvas(self, -1, self.figure) 
     self.sizer = wx.BoxSizer(wx.VERTICAL) 
     self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW) 
     self.SetSizer(self.sizer) 
     self.Fit() 

    def draw(self): 
     t = arange(0.0, 3.0, 0.01) 
     s = sin(2 * pi * t) 
     self.axes.plot(t, s) 


if __name__ == "__main__": 
    app = wx.PySimpleApp() 
    fr = wx.Frame(None, title='test') 
    panel = CanvasPanel(fr) 
    panel.draw() 
    fr.Show() 
    app.MainLoop() 

взяты из https://stackoverflow.com/a/10741760/1800665

То, что я хотел бы сделать, это есть два холста в этой одной панели, левая сторона, показывающая фигуру в Matplotlib холст и тому правая сторона показывает форму на полотне opengl.

У меня есть следующий код, чтобы нарисовать куб в OPENGL холст в WxPython:

import wx 
import sys 
from wx import glcanvas 
from OpenGL.GL import * 
from OpenGL.GLUT import * 

class MyCanvasBase(glcanvas.GLCanvas): 
    def __init__(self, parent): 
     glcanvas.GLCanvas.__init__(self, parent, -1) 
     self.init = False 
     self.context = glcanvas.GLContext(self) 

     # initial mouse position 
     self.lastx = self.x = 30 
     self.lasty = self.y = 30 
     self.size = None 
     self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground) 
     self.Bind(wx.EVT_SIZE, self.OnSize) 
     self.Bind(wx.EVT_PAINT, self.OnPaint) 
     self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown) 
     self.Bind(wx.EVT_LEFT_UP, self.OnMouseUp) 
     self.Bind(wx.EVT_MOTION, self.OnMouseMotion) 

    def OnEraseBackground(self, event): 
     pass # Do nothing, to avoid flashing on MSW. 

    def OnSize(self, event): 
     wx.CallAfter(self.DoSetViewport) 
     event.Skip() 

    def DoSetViewport(self): 
     size = self.size = self.GetClientSize() 
     self.SetCurrent(self.context) 
     glViewport(0, 0, size.width, size.height) 

    def OnPaint(self, event): 
     dc = wx.PaintDC(self) 
     self.SetCurrent(self.context) 
     if not self.init: 
      self.InitGL() 
      self.init = True 
     self.OnDraw() 

    def OnMouseDown(self, evt): 
     self.CaptureMouse() 
     self.x, self.y = self.lastx, self.lasty = evt.GetPosition() 

    def OnMouseUp(self, evt): 
     self.ReleaseMouse() 

    def OnMouseMotion(self, evt): 
     if evt.Dragging() and evt.LeftIsDown(): 
      self.lastx, self.lasty = self.x, self.y 
      self.x, self.y = evt.GetPosition() 
      self.Refresh(False) 

class CubeCanvas(MyCanvasBase): 
    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() 

     if self.size is None: 
      self.size = self.GetClientSize() 
     w, h = self.size 
     w = max(w, 1.0) 
     h = max(h, 1.0) 
     xScale = 180.0/w 
     yScale = 180.0/h 
     glRotatef((self.y - self.lasty) * yScale, 1.0, 0.0, 0.0); 
     glRotatef((self.x - self.lastx) * xScale, 0.0, 1.0, 0.0); 

     self.SwapBuffers() 

#---------------------------------------------------------------------- 
class RunDemoApp(wx.App): 
    def __init__(self): 
     wx.App.__init__(self, redirect=False) 

    def OnInit(self): 
     canvasClass = eval('CubeCanvas') 

     cx = 0 

     frame = wx.Frame(None, -1, 'CubeCanvas', size=(400,400), pos=(cx,400)) 
     canvasClass(frame) # CubeCanvas(frame) or ConeCanvas(frame); frame passed to   MyCanvasBase 
     frame.Show(True) 

     self.frame = frame 
     return True 

    def OnExitApp(self, evt): 
     self.frame.Close(True) 

    def OnCloseFrame(self, evt): 
     if hasattr(self, "window") and hasattr(self.window, "ShutdownDemo"): 
      self.window.ShutdownDemo() 
     evt.Skip() 

app = RunDemoApp() 
app.MainLoop() 

взяты из и адаптированный для удаления кнопки панели и параметры конуса: http://wiki.wxpython.org/GLCanvas%20update

Я играл около и исследование довольно долгое время, и мне очень трудно понять, как смешивать эти два холста и отображать их в одном кадре, поэтому любая помощь будет принята с благодарностью!

Заранее благодарен!

ответ

0

Этот код нуждается в полировке, но он работает.

import wx 
import sys 
from wx import glcanvas 
from OpenGL.GL import * 
from OpenGL.GLUT import * 

from numpy import arange, sin, pi 
import matplotlib 
matplotlib.use('WXAgg') 

from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas 
from matplotlib.backends.backend_wx import NavigationToolbar2Wx 
from matplotlib.figure import Figure 

class CanvasPanel(wx.Panel): 
    def __init__(self, parent): 
     wx.Panel.__init__(self, parent) 
     self.figure = Figure() 
     self.axes = self.figure.add_subplot(111) 
     self.canvas = FigureCanvas(self, -1, self.figure) 
     self.sizer = wx.BoxSizer(wx.VERTICAL) 
     self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW) 
     self.SetSizer(self.sizer) 
     self.Fit() 

    def draw(self): 
     t = arange(0.0, 3.0, 0.01) 
     s = sin(2 * pi * t) 
     self.axes.plot(t, s) 

class MyCanvasBase(glcanvas.GLCanvas): 
    def __init__(self, parent): 
     glcanvas.GLCanvas.__init__(self, parent, -1) 
     self.init = False 
     self.context = glcanvas.GLContext(self) 

     # initial mouse position 
     self.lastx = self.x = 30 
     self.lasty = self.y = 30 
     self.size = None 
     self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground) 
     self.Bind(wx.EVT_SIZE, self.OnSize) 
     self.Bind(wx.EVT_PAINT, self.OnPaint) 
     self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown) 
     self.Bind(wx.EVT_LEFT_UP, self.OnMouseUp) 
     self.Bind(wx.EVT_MOTION, self.OnMouseMotion) 

    def OnEraseBackground(self, event): 
     pass # Do nothing, to avoid flashing on MSW. 

    def OnSize(self, event): 
     wx.CallAfter(self.DoSetViewport) 
     event.Skip() 

    def DoSetViewport(self): 
     size = self.size = self.GetClientSize() 
     self.SetCurrent(self.context) 
     glViewport(0, 0, size.width, size.height) 

    def OnPaint(self, event): 
     dc = wx.PaintDC(self) 
     self.SetCurrent(self.context) 
     if not self.init: 
      self.InitGL() 
      self.init = True 
     self.OnDraw() 

    def OnMouseDown(self, evt): 
     self.CaptureMouse() 
     self.x, self.y = self.lastx, self.lasty = evt.GetPosition() 

    def OnMouseUp(self, evt): 
     self.ReleaseMouse() 

    def OnMouseMotion(self, evt): 
     if evt.Dragging() and evt.LeftIsDown(): 
      self.lastx, self.lasty = self.x, self.y 
      self.x, self.y = evt.GetPosition() 
      self.Refresh(False) 

class CubeCanvas(MyCanvasBase): 
    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() 

     if self.size is None: 
      self.size = self.GetClientSize() 
     w, h = self.size 
     w = max(w, 1.0) 
     h = max(h, 1.0) 
     xScale = 180.0/w 
     yScale = 180.0/h 
     glRotatef((self.y - self.lasty) * yScale, 1.0, 0.0, 0.0); 
     glRotatef((self.x - self.lastx) * xScale, 0.0, 1.0, 0.0); 

     self.SwapBuffers() 

#---------------------------------------------------------------------- 
class RunDemoApp(wx.App): 
    def __init__(self): 
     wx.App.__init__(self, redirect=False) 

    def OnInit(self): 
     canvasClass = eval('CubeCanvas') 

     cx = 0 

     frame = wx.Frame(None, -1, 'CubeCanvas', size=(400,400), pos=(cx,400)) 

     # adding panel with sizer for both canvas 
     panel = wx.Panel(frame, -1) 

     self.sizer = wx.BoxSizer(wx.HORIZONTAL) 

     # adding first canvas 
     canvas1 = canvasClass(panel) # CubeCanvas(frame) or ConeCanvas(frame); frame passed to   MyCanvasBase 
     self.sizer.Add(canvas1, 1, wx.LEFT | wx.TOP | wx.GROW) 

     # adding second canvas 
     self.canvas = CanvasPanel(panel) 
     self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW) 

     panel.SetSizer(self.sizer) 
     panel.Fit() 

     frame.Show(True) 

     self.frame = frame 
     return True 

    def OnExitApp(self, evt): 
     self.frame.Close(True) 

    def OnCloseFrame(self, evt): 
     if hasattr(self, "window") and hasattr(self.window, "ShutdownDemo"): 
      self.window.ShutdownDemo() 
     evt.Skip() 

app = RunDemoApp() 
app.MainLoop() 
+0

Спасибо, я только что создал что-то похожее на это, и мне удалось заставить его работать, мне пришлось сделать несколько шагов назад и посмотреть на всю картину, чтобы понять. –

Смежные вопросы