我正在开发一个基本上包含多个小部件的GUI,每个小部件都包含一个数字以及几个按钮/等等。其中一个数字应该是交互式的,每当用户点击图的任何部分时调用一个函数。然而,即使在使用焦点等等之后,我也无法使用mpl_connect来启动该功能。我对PySide / Qt有点新鲜,所以我不完全理解为什么我的代码表现得像这样(我一直在寻找解决方案的天数,但是没有发现任何东西关于它)。
我使用Qt Designer为GUI创建布局。我使用Anaconda 2.2.0(32位),Python 2.7和PySide的Spyder来开发GUI。如果有任何帮助,我来自MATLAB背景,我开发了一个完整版的GUI,我试图用Python制作。
以下是相关代码(向下滚动一下以查看问题所在):
from PySide import QtCore, QtGui
from PySide.QtCore import *
from PySide.QtGui import *
import numpy as np
import matplotlib
matplotlib.use('Qt4Agg')
matplotlib.rcParams['backend.qt4']='PySide'
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt4agg import NavigationToolbar2QTAgg as NavigationToolbar
import matplotlib.pyplot as plt
from PySide.QtGui import QPalette, QCursor
import matplotlib.colors as colors
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1316, 765)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.widget = QtGui.QWidget(self.centralwidget)
self.widget.setGeometry(QtCore.QRect(75, 40, 375, 490))
self.widget.setObjectName("widget")
color = self.centralwidget.palette().color(QPalette.Window)
self.leftPlot = MatplotlibWidget(None,'','','',False,color)
self.setupPlot(self.widget,self.leftPlot)
self.leftPlot.figure.tight_layout()
self.leftImage = self.leftPlot.axes.imshow(self.defaultSlide, cmap = mymap)
感兴趣的片段:
self.leftPlot.figure.canvas.setFocusPolicy(QtCore.Qt.StrongFocus)
self.leftPlot.figure.canvas.setFocus()
cid = self.leftPlot.figure.canvas.mpl_connect('button_release_event', self.getCoordinates) # doesn't get called
plt.show()
def getCoordinates(self, event):
print 'dasdsadadsa'
print 'button=%d, x=%d, y=%d, xdata=%f, ydata=%f'%(event.button, event.x, event.y, event.xdata, event.ydata)
其余的:
class MatplotlibWidget(FigureCanvas):
def __init__(self, parent=None,xlabel='x',ylabel='y',title='Title',showTicks=False,color=None):
super(MatplotlibWidget, self).__init__(Figure())
self.setParent(parent)
if color != None:
self.figure = Figure(facecolor=(color.red()/256.0,color.green()/256.0,color.blue()/256.0),frameon=0)
else:
self.figure = Figure(frameon=0)
self.canvas = FigureCanvas(self.figure)
self.axes = self.figure.add_subplot(111)
self.axes.set_xlabel(xlabel)
self.axes.set_ylabel(ylabel)
self.axes.set_title(title)
self.axes.get_xaxis().set_visible(showTicks)
self.axes.get_yaxis().set_visible(showTicks)
class ControlMainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(ControlMainWindow, self).__init__(parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
plt.show()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
mySW = ControlMainWindow()
mySW.show()
sys.exit(app.exec_())
我知道代码很乱,但是非常感谢任何输入。
答案 0 :(得分:1)
更新(2015-09-04): 我已将我提供的MWE更新为原始答案的一部分,而不是使用{{3}中建议的方法在应用程序中嵌入mpl数字。这种方法不使用pyplot接口(如我原来的答案),而是使用mpl的面向对象API。此外,由于所有mpl艺术家(图,轴等)彼此了解,因此无需显式创建新的类变量。这允许IMO代码结构更易于阅读和维护。
问题来自于您未将事件正确连接到self.leftPlot
( FigureCanvasQTAgg ),而是连接到self.leftPlot.figure.canvas
( FigureCanvasQTAgg.figure.FigureCanvasQTAgg )而不是。您正在MatplotlibWidget
类(已经是 FigureCanvasQTAgg 的子类)的画布中创建画布。您只需创建一个mpl画布,将图形传递给它,然后直接将事件连接到它。
我已经汇总了一个MWE来演示如何使用Matplotlib的面向对象的API如matplotlib documentation中所建议的那样:
from PySide import QtGui
import numpy as np
import sys
import matplotlib as mpl
mpl.use('Qt4Agg')
mpl.rcParams['backend.qt4']='PySide'
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg
class ControlMainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(ControlMainWindow, self).__init__(parent)
self.setupUi()
def setupUi(self):
figure = mpl.figure.Figure(figsize=(5, 5))
leftPlot = MatplotlibWidget(figure)
self.setCentralWidget(leftPlot)
class MatplotlibWidget(FigureCanvasQTAgg):
def __init__(self, fig):
super(MatplotlibWidget, self).__init__(fig)
#-- set up an axe artist --
ax = fig.add_axes([0.1, 0.1, 0.85, 0.85])
ax.plot(np.arange(15), np.arange(15))
self.draw()
#---- setup event ----
self.mpl_connect('button_press_event', self.onclick)
def onclick(self, event):
x, y = event.x, event.y
print(x, y)
if x != None and y != None:
ax = self.figure.axes[0]
ax.plot(event.xdata, event.ydata, 'ro')
self.draw()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
mySW = ControlMainWindow()
mySW.show()
sys.exit(app.exec_())
上面的代码导致: