【问题标题】:how to combine wxPython, matplotlib and Pyopengl如何结合 wxPython、matplotlib 和 Pyopengl
【发布时间】:2013-11-22 12:14:11
【问题描述】:

嗨,我目前有一个应用程序,我有一个显示 matplotlib 图形的窗口。

即比如这样:

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 画布上的形状。

我有以下代码在 wxpython 的 opengl 画布中绘制立方体:

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

我已经玩了很长一段时间了,我发现很难理解如何混合这两个画布并将它们显示在一个框架中,所以非常感谢任何帮助!

提前致谢!

【问题讨论】:

    标签: python matplotlib wxpython pyopengl


    【解决方案1】:

    这段代码需要完善,但它可以工作。

    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()
    

    【讨论】:

    • 谢谢,我刚刚创建了类似的东西,并设法让它工作,我不得不退后几步,看看整个图片才能理解。
    猜你喜欢
    • 2012-06-21
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    • 2011-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-06
    相关资源
    最近更新 更多