【发布时间】:2017-11-22 15:49:42
【问题描述】:
我有以下代码可以很好地与 matplotlib 2.0.2(在 Python 3.6.3 下)一起使用,但会引发类型错误(TypeError: 'Rectangle' object不可调用)与 matplotlib 2.1.0。 它的目的是通过“press&move”在 PyQt5 窗口中嵌入的图形上交互地绘制一个矩形,当用户释放鼠标按钮 1 时,矩形给出了图形的新限制(即像 Matlab 一样的缩放行为)。
我做错了什么?
# Python 3.6
...
from PyQt5 import QtCore, QtGui, QtWidgets
...
from matplotlib.patches import Rectangle
...
class MplWidget(Canvas):
zoom_in = False
cid_zoom_P = None
cid_zoom_R = None
cid_zoom_M = None
def __init__(self, parent, dpi = 100, hold = False, **kwargs):
super().__init__(Figure())
self.parent = parent
self.setParent(parent)
self.figure = Figure(dpi = dpi)
self.canvas = Canvas(self.figure)
self.repres = self.figure.add_subplot(111)
...
def zoomManager(self, bouton_pan, bouton_tip):
if self.zoom_in is not True:
self.zoom_in = True
QtWidgets.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.CrossCursor))
self.x0 = None
self.y0 = None
self.x1 = None
self.y1 = None
self.cid_zoom_P = self.mpl_connect("button_press_event", self.zoomOnPress)
self.cid_zoom_R = self.mpl_connect("button_release_event", self.zoomOnRelease)
self.cid_zoom_M = self.mpl_connect("motion_notify_event", self.zoomOnMotion)
else:
self.zoom_in = False
QtWidgets.QApplication.restoreOverrideCursor()
self.mpl_disconnect(self.cid_zoom_P)
self.mpl_disconnect(self.cid_zoom_R)
self.mpl_disconnect(self.cid_zoom_M)
...
def zoomOnPress(self, event):
if event.button == 1:
if not bool(event.inaxes):
return
self.zoom_pressed = True
self.x0 = event.xdata
self.y0 = event.ydata
self.rect = Rectangle((0,0), 1, 1, alpha=0.25, ls='--', lw=1, ec='k')
self.repres.add_patch(self.rect)
def zoomOnRelease(self, event):
if event.button == 1:
self.zoom_pressed = False
self.x1 = event.xdata
if not self.x1:
self.x1 = self.x1_old
else:
self.x1_old = self.x1
self.y1 = event.ydata
if not self.y1:
self.y1 = self.y1_old
else:
self.y1_old = self.y1
self.rect.remove()
self.repres.set_xlim([min(self.x1, self.x0), max(self.x1, self.x0)])
self.repres.set_ylim([min(self.y1, self.y0), max(self.y1, self.y0)])
self.draw()
def zoomOnMotion(self, event):
if self.zoom_pressed is False:
return
self.x1 = event.xdata
if not self.x1:
self.x1 = self.x1_old
else:
self.x1_old = self.x1
self.y1 = event.ydata
if not self.y1:
self.y1 = self.y1_old
else:
self.y1_old = self.y1
self.rect.set_width(self.x1 - self.x0)
self.rect.set_height(self.y1 - self.y0)
self.rect.set_xy((self.x0, self.y0))
self.draw()
...
【问题讨论】:
-
您需要提供问题的minimal reproducible example,以便人们能够重现它并找到错误。如果没有minimal reproducible example,这个问题就很难解决。您还需要提供完整的错误回溯,而不仅仅是最后一行。
-
@ImportanceOfBeingErnest :这是一个关于 matplotlib 版本和向后兼容性的理论问题。真正的代码太长太复杂,无法在此处发布。我已经花了很多时间写这个问题......
-
那么理论上的答案是:不,
Rectangle的功能在两个版本之间没有变化,并且 Rectangle 是向后兼容的。如果您仍然对实际问题的解决方案感兴趣,请参见上文。 -
@ImportanceOfBeingErnest :我对您的回答感到惊讶,因为在我的情况下,这两个版本的 Matplotlib 之间的操作存在真正的差异。此处部分公开的代码在 Matplotlib 2.0.2 中完美运行,但不适用于 2.1.0 版本。在最后一种情况下,错误是对“self.draw”的调用产生的。我已经测试了这个语句的很多变体,但没有成功。我将尝试在“PyPlot”下重现错误,为您提供所需的示例功能和可重现性。感谢您的帮助
-
不要误会我的意思,我并不是说版本之间没有任何会导致此错误的更改。我要说的是
Rectangle没有变化。为了找出导致错误的原因,需要一个完整且可验证的示例,充其量也应该是最小的。只有这样才能开始调试。
标签: python matplotlib pyqt5 python-3.6