2016-04-19 103 views
0

我试图通过创建一个可以拖动的子图(matplotlib曲线,而不是整个窗口)在可拖动绘图教程上展开。我觉得我很接近,但只是错过了一个关键的细节。可拖曳Matplotlib使用wxPython的子图使用wxPython

大部分代码只是创建饼干子图,图3是唯一一个我试图拖动图形数据的地方。

任何帮助,将不胜感激!

import wxversion 
wxversion.ensureMinimal('2.8') 

import numpy as np 

import matplotlib 
matplotlib.interactive(True) 

matplotlib.use('WXAgg') 
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas 
from matplotlib.figure import Figure 

import wx 

class DraggableCurve: 

    def __init__(self,curve): 
     self.curve = curve[0] 
     self.press = None 

    def connect(self): 
     'connect to all the events we need' 
     self.cidpress = self.curve.figure.canvas.mpl_connect(
      'button_press_event', self.on_press) 
     self.cidrelease = self.curve.figure.canvas.mpl_connect(
      'button_release_event', self.on_release) 
     self.cidmotion = self.curve.figure.canvas.mpl_connect(
      'motion_notify_event', self.on_motion) 

    def on_press(self, event): 
     print "on_press" 
     'on button press we will see if the mouse is over us and store some data' 
     if event.inaxes != self.curve.axes: return 

     contains, attrd = self.curve.contains(event) 
     if not contains: return 
     print 'event contains', self.curve.xy 
     x0, y0 = self.curve.xy 
     # print x0,y0 
     self.press = x0, y0, event.xdata, event.ydata 

    def on_motion(self, event): 
     print "on_motion" 
     'on motion we will move the curve if the mouse is over us' 
     if self.press is None: return 
     if event.inaxes != self.curve.axes: return 
     x0, y0, xpress, ypress = self.press 
     print xpress, ypress 
     dx = event.xdata - xpress 
     dy = event.ydata - ypress 
     #print 'x0=%f, xpress=%f, event.xdata=%f, dx=%f, x0+dx=%f'%(x0, xpress, event.xdata, dx, x0+dx) 
     self.curve.set_x(x0+dx) 
     self.curve.set_y(y0+dy) 
     # print x0+dx, y0+dy 

     #self.curve.figure.canvas.draw() 
     self.curve.figure.canvas.draw_idle() 

    def on_release(self, event): 
     print "on_release" 
     'on release we reset the press data' 
     self.press = None 
     #self.curve.figure.canvas.draw() 
     self.curve.figure.canvas.draw_idle() 

    def disconnect(self): 
     'disconnect all the stored connection ids' 
     self.curve.figure.canvas.mpl_disconnect(self.cidpress) 
     self.curve.figure.canvas.mpl_disconnect(self.cidrelease) 
     self.curve.figure.canvas.mpl_disconnect(self.cidmotion) 

class CanvasFrame(wx.Frame): 

    def __init__(self): 

     #create frame 
     frame = wx.Frame.__init__(self,None,-1, 
         'Test',size=(550,350)) 

     #set background 
     self.SetBackgroundColour(wx.NamedColour("WHITE")) 

     #initialize figures 
     self.figure1 = Figure() 
     self.figure2 = Figure() 
     self.figure3 = Figure() 
     self.figure4 = Figure() 

     #initialize figure1 
     self.axes1 = self.figure1.add_subplot(111) 
     self.axes1.text(0.5,0.5, 'Test 1', horizontalalignment='center', fontsize=15) 
     self.axes1.get_xaxis().set_visible(False) 
     self.axes1.get_yaxis().set_visible(False) 
     self.canvas1 = FigureCanvas(self, -1, self.figure1) 

     #initialize figure2 
     self.axes2 = self.figure2.add_subplot(111) 
     self.axes2.text(0.5,0.5, 'Test 2', horizontalalignment='center', fontsize=15) 
     self.axes2.get_xaxis().set_visible(False) 
     self.axes2.get_yaxis().set_visible(False) 
     self.canvas2 = FigureCanvas(self, -1, self.figure2) 

     #initialize figure3 
     self.axes3 = self.figure3.add_subplot(111) 
     curve = self.axes3.plot(np.arange(1,11),10*np.random.rand(10),color='r',marker='o') 
     self.canvas3 = FigureCanvas(self, -1, self.figure3) 
     # self.axes3.get_xaxis().set_visible(True) 
     # self.axes3.get_yaxis().set_visible(True) 
     # self.canvas3.draw() 
     # self.canvas3.draw_idle() 
     dc = DraggableCurve(curve) 
     dc.connect() 

     #initialize figure4 
     self.axes4 = self.figure4.add_subplot(111) 
     self.axes4.text(0.5,0.5, 'Test4', horizontalalignment='center', fontsize=15) 
     self.axes4.get_xaxis().set_visible(False) 
     self.axes4.get_yaxis().set_visible(False) 
     self.canvas4 = FigureCanvas(self, -1, self.figure4) 

     #create figures into the 2x2 grid 
     self.sizer = wx.GridSizer(rows=2, cols=2, hgap=5, vgap=5) 
     self.sizer.Add(self.canvas1, 1, wx.EXPAND) 
     self.sizer.Add(self.canvas2, 1, wx.EXPAND) 
     self.sizer.Add(self.canvas3, 1, wx.EXPAND) 
     self.sizer.Add(self.canvas4, 1, wx.EXPAND) 
     self.SetSizer(self.sizer) 
     self.Fit() 

     return 

class App(wx.App): 

    def OnInit(self): 
     'Create the main window and insert the custom frame' 
     frame = CanvasFrame() 
     frame.Show(True) 

     return True 

app = App(0) 
app.MainLoop() 

enter image description here

回答

1

检查这个例子:

# -*- coding: utf-8 -*- 
import wxversion 
wxversion.ensureMinimal('2.8') 
import wx 
import numpy as np 
import matplotlib 
matplotlib.use('WXAgg') 
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg 
from matplotlib.figure import Figure 

class FigureCanvas(FigureCanvasWxAgg): 
    def __init__(self,parent,id,figure,**kwargs): 
     FigureCanvasWxAgg.__init__(self,parent=parent, id=id, figure=figure,**kwargs) 
     self.figure = figure 
     self.axes = self.figure.get_axes()[0] # Get axes 
     self.connect() # Connect event 

    def connect(self): 
     """Connect pick event""" 
     self.MOVE_LINE_EVT = self.mpl_connect("pick_event", self.on_pick) 

    def on_pick(self,event): 
     self._selected_line = event.artist # Get selected line 
     # Get initial x,y data 
     self._p0 = (event.mouseevent.xdata, event.mouseevent.ydata) 
     self._xdata0 = self._selected_line.get_xdata() 
     self._ydata0 = self._selected_line.get_ydata() 
     # Connect events for motion and release. 
     self._on_motion = self.mpl_connect("motion_notify_event", self.on_motion) 
     self._on_release = self.mpl_connect("button_release_event", self.on_release) 

    def on_motion(self,event): 
     cx = event.xdata # Current xdata 
     cy = event.ydata # Current ydata 
     deltax = cx - self._p0[0] 
     deltay = cy - self._p0[1] 
     self._selected_line.set_xdata(self._xdata0 + deltax) 
     self._selected_line.set_ydata(self._ydata0 + deltay) 
     self.draw() 

    def on_release(self,event): 
     """On release, disconnect motion and release""" 
     self.mpl_disconnect(self._on_motion) 
     self.mpl_disconnect(self._on_release) 
     self.axes.relim() 
     self.axes.autoscale_view(True,True,True) 
     self.draw() 


class Frame(wx.Frame): 
    def __init__(self,parent,title): 
     wx.Frame.__init__(self,parent,title=title,size=(800,600)) 
     self.initCtrls() 
     self.plotting() 
     self.Centre(True) 
     self.Show() 

    def initCtrls(self): 
     self.mainsizer = wx.GridSizer(rows=2, cols=2, hgap=2, vgap=2) 
     # 1 
     self.figure = Figure() 
     self.axes = self.figure.add_subplot(111) 
     self.canvas = FigureCanvas(self, wx.ID_ANY, self.figure) 

     # 2 
     self.figure2 = Figure() 
     self.axes2 = self.figure2.add_subplot(111) 
     self.canvas2 = FigureCanvas(self, wx.ID_ANY, self.figure2) 

     self.figure3 = Figure() 
     self.axes3 = self.figure3.add_subplot(111) 
     self.canvas3 = FigureCanvas(self, wx.ID_ANY, self.figure3) 

     self.figure4 = Figure() 
     self.axes4 = self.figure4.add_subplot(111) 
     self.canvas4 = FigureCanvas(self, wx.ID_ANY, self.figure4) 

     self.mainsizer.Add(self.canvas, 1, wx.EXPAND) 
     self.mainsizer.Add(self.canvas2, 1, wx.EXPAND) 
     self.mainsizer.Add(self.canvas3, 1, wx.EXPAND) 
     self.mainsizer.Add(self.canvas4, 1, wx.EXPAND) 
     self.SetSizer(self.mainsizer) 

    def plotting(self): 
     # Set picker property -> true 
     self.axes2.plot(np.arange(1,11),10*np.random.rand(10),color='b', 
         marker='o', picker=True) 
     self.axes3.plot(np.arange(1,11),10*np.random.rand(10),color='r', 
         marker='o', picker=True) 
     self.canvas.draw() 


if __name__=='__main__': 
    app = wx.App() 
    frame = Frame(None, "Matplotlib Demo") 
    frame.Show() 
    app.MainLoop() 

基本上思想是定义自定义FigureCanvas,其支持使用选图事件的线的选择和移动。

很明显,这段代码仍然需要大量的审查才能正常工作。

+0

太棒了!这将有助于一吨。谢谢! – bsf10