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