4

PySide に埋め込まれた matplotlib に問題があります。ウィンドウでオブジェクトを選択しようとすると、エラーが発生するため、サブプロットのみを選択できるように見えます

AttributeError: 'AxesSubplot' object has no attribute 'get_xdata'

キャンバス上の Line2D クラスのインスタンスをラインでキャプチャしようとすると、

if isinstance(event.artist, Line2D)

Line2D (四角形もテキストも) ではなく、AxesSubplot オブジェクトのみをキャプチャできます。

支援に感謝します、リチャード

class navDialog(QtGui.QDialog, Ui_mplDialog):
    def __init__(self, parent=None):
        super(navDialog, self).__init__(parent)
        # Basic preparation for an embedded matplotlib
        self.setupUi(self)
        fig = Figure(figsize=(600,600), dpi=72, facecolor=(1,1,1),edgecolor=(1,1,1))
        #fig.set_picker(picker)

        self.canvas = FigureCanvas(fig)
        self.verticalLayout.addWidget(self.canvas)

        ax = fig.add_subplot(111, xlim=(0, 10), ylim=(0, 10),axisbg='0.3', picker = True)
        ax.set_title('Click on the points', picker=True)
        fig.set_frameon(False)
        #fig.set_alpha(self, alpha)

        self.canvas.setSizePolicy(QtGui.QSizePolicy.Expanding,
                                  QtGui.QSizePolicy.Expanding)
        self.canvas.updateGeometry()


        self.navigation_toolbar = NavigationToolbar(self.canvas, self)
        self.verticalLayout.addWidget(self.navigation_toolbar, 0)

        #self.canvas.mpl_connect('button_press_event', self.on_pick)
        self.canvas.mpl_connect('pick_event', self.on_pick)

        # Specific content
        from matplotlib.collections import PatchCollection
        from matplotlib.projections.polar import PolarAxes
        import matplotlib.path as mpath
        import matplotlib.patches as mpatches
        import matplotlib.lines as mlines


        fig = plt.figure(figsize=(5,5))
        ax = plt.axes([0,0,1,1])
        patches = []

        # add entities on a circle
        es = session.query(Entity).all()
        vpuInFocus =session.query(Entity).filter(Entity.entity_in_focus == True) \
                                        .filter(Entity.entity_class_id== 1).one()
        esQty = len(es) - 1
        center = [5,5]

        theta = 2*3.14 / esQty
        arc = 0
        rad = 3
        pos = []
        # Entity in focus
        ePatch = mpatches.Circle(center, 0.3, ec='r', color='0.7',picker=True)
        patches.append(ePatch)
        ax.text(center[0], center[1], vpuInFocus.name, ha="center",family=font, size=14)

        for e in es:
            if e.Id is not vpuInFocus.Id:
                eX = center[0] + np.sin(arc) * rad
                eY = center[1] + np.cos(arc) * rad
                pos.append([e.name, eX , eY])
                # patch form can depend on the entityclass !!!
                ePatch = mpatches.Circle([eX, eY], 0.3, ec='r',color='0.7', picker=True)
                patches.append(ePatch)
                ax.text(eX, eY, e.name, ha="center", family=font,size=14)

                line = matplotlib.lines.Line2D([center[0], eX],[center[1], eY], picker=True)  # [x1, x2], [y1, y2]
                line.set_color('1.0')
                patches.append(line)

                arc = arc + theta


        collection = PatchCollection(patches, cmap=matplotlib.cm.jet,alpha=0.4)
        ax.add_collection(collection)

    def onclick(self, event):
        print 'button=%d, x=%d, y=%d, xdata=%f, ydata=%f'%(
            event.button, event.x, event.y, event.xdata, event.ydata)

    def on_pick(self, event):
        if isinstance(event.artist, Line2D):
            thisline = event.artist
            xdata = thisline.get_xdata()
            ydata = thisline.get_ydata()
            ind = event.ind
            print 'onpick1 line:', zip(npy.take(xdata, ind),npy.take(ydata, ind))
        elif isinstance(event.artist, Rectangle):
            patch = event.artist
            print 'onpick1 patch:', patch.get_path()
        elif isinstance(event.artist, Text):
            text = event.artist
            print 'onpick1 text:', text.get_text()
        mouseevent = event.mouseevent
        msg = "X is: " + str(mouseevent.xdata) + "\nY is: " +str(mouseevent.ydata)
        print msg

したがって、パッチを選択することはできません。次のコードは私にとってはうまくいきます。

class mplDialog(QtGui.QDialog, Ui_mplDialog):
  def __init__(self, parent=None):
    super(mplDialog, self).__init__(parent)


    # Basic preparation for an embedded matplotlib
    self.setupUi(self)

    # Context menu on system2 in focus button
    self.setContextMenuPolicy(Qt.CustomContextMenu)
    self.customContextMenuRequested.connect(self.ctxMenu)

    fig = Figure(figsize=(600,600), dpi=72, facecolor=(1,1,1), edgecolor=(0,0,0))

    self.canvas = FigureCanvas(fig)
    self.verticalLayout.addWidget(self.canvas)           

    self.axes = fig.add_subplot(111)        
    self.canvas.setSizePolicy(QtGui.QSizePolicy.Expanding,
                               QtGui.QSizePolicy.Expanding)
    self.canvas.updateGeometry()
    self.navigation_toolbar = NavigationToolbar(self.canvas, self)
    self.verticalLayout.addWidget(self.navigation_toolbar, 0)

    # Specific content
    self.axes.plot([1,2,3,4,5,6,7,8,9],[50, 67, 74, 57, 57, 57, 75, 64, 96], picker=True)
    self.axes.scatter(2, 80, marker='o', picker=True)

    # Add patches (which can't be picked!)
    from matplotlib.collections import PatchCollection
    import matplotlib.patches as mpatches
    font = "sans-serif"
    patches = []
    ePatch = mpatches.Circle([5,70], ec='r', color='r', picker=True)
    patches.append(ePatch) 
    ePatch = mpatches.Rectangle([7,60], 3, 10,  ec='r', color='0.7', picker=True)
    self.axes.text(7,60, "Rect name", picker=True)
    patches.append(ePatch)   
    collection = PatchCollection(patches, cmap=matplotlib.cm.jet, alpha=0.4)
    self.axes.add_collection(collection)

    self.canvas.mpl_connect('pick_event', self.onpick1)  

def onpick1(self, event):
    #print event.artist
    if isinstance(event.artist, Line2D):
        thisline = event.artist
        xdata = thisline.get_xdata()
        ydata = thisline.get_ydata()
        ind = event.ind
        print 'onpick1 line:', zip(np.take(xdata, ind), np.take(ydata, ind))
    elif isinstance(event.artist, Rectangle):  # For bar plots
        patch = event.artist
        print 'onpick1 patch:', patch.get_path()
    elif isinstance(event.artist, Text):
        text = event.artist
        print 'onpick1 text:', text.get_text(), "Obj", text
    else:   # For scatter plots
        patch = event.artist
        print 'onpick1 Circle:' #patch.get_path()
4

0 に答える 0