我正在尝试使用“ginput”通过允许用户单击位置来测量 matplotlib 图形中的距离。我可以在 matplotlib 图中独立地完成此操作,但是当我尝试将图设置到 matplotlib Canvas 上然后将其嵌入到 PyQt4 小部件中时遇到问题。下面是我的代码,其中大部分取自 matplotlib 示例。我的解决方案是单击一组位置,并将 (x,y) 坐标传递给“dist_calc”函数来获取距离。
import sys
from PyQt4 import QtGui
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as NavigationToolbar
import matplotlib.pyplot as plt
from matplotlib.figure import Figure
import random
import numpy as np
class Window(QtGui.QWidget):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.fig = Figure((6.5, 5.0), tight_layout=True)
self.ax = self.fig.add_subplot(111)
self.canvas = FigureCanvas(self.fig)
self.toolbar = NavigationToolbar(self.canvas, self)
self.button = QtGui.QPushButton('Plot')
self.button.clicked.connect(self.plot)
self.ndist = QtGui.QPushButton('Measure')
self.ndist.clicked.connect(self.draw_line)
self.toolbar.addWidget(self.button)
self.toolbar.addWidget(self.ndist)
self.fig.tight_layout()
layout = QtGui.QVBoxLayout()
layout.addWidget(self.toolbar)
layout.addWidget(self.canvas)
self.setLayout(layout)
def plot(self):
data = [random.random() for i in range(20)]
self.ax.hold(False)
self.ax.plot(data, '*-')
self.canvas.draw()
def draw_line(self):
self.xy = plt.ginput(0)
x = [p[0] for p in self.xy]
y = [p[1] for p in self.xy]
self.ax.plot(x,y)
self.ax.figure.canvas.draw()
self.get_dist(x, y)
def get_dist(self, xpts, ypts):
npts = len(xpts)
distArr = []
for i in range(npts-1):
apt = [xpts[i], ypts[i]]
bpt = [xpts[i+1], ypts[i+1]]
dist =self.calc_dist(apt,bpt)
distArr.append(dist)
tdist = np.sum(distArr)
print(tdist)
def calc_dist(self,apt, bpt):
apt = np.asarray(apt)
dist = np.sum((apt - bpt)**2)
dist = np.sqrt(dist)
return dist
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
main = Window()
main.show()
sys.exit(app.exec_())
最佳答案
根据this comment一位领先的 Matplotlib 开发人员指出,当您在 Qt 中嵌入 Matplotlib 时,您必须不要导入 pyplot
。 Pyplot 设置了自己的 gui、mainloop 和 canvas,这会干扰 Qt 事件循环。
将行 self.xy = plt.ginput(0)
更改为 self.xy = self.fig.ginput(0)
没有帮助,但提供了深刻的见解错误:
AttributeError: 'FigureCanvasQTAgg' object has no attribute 'manager'
Figure.show works only for figures managed by pyplot, normally created by pyplot.figure().
简而言之,我认为这是不可能的。 ginput
是一个阻塞函数,似乎仅针对 Matplotlib 事件循环实现。恐怕您必须使用 Matplotlib mouse events 构建您想要的功能,在嵌入 PyQt 时确实可以工作。请确保不要使用 pyplot!
编辑:我刚刚想起来,也许是LassoSelector就是您所需要的。
关于matplotlib - 在 PyQt4 中的嵌入式 matplotlib 图中使用 ginput,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33662732/