无法实现mpl_connect

时间:2015-07-06 14:06:10

标签: user-interface matplotlib pyside

我正在开发一个基本上包含多个小部件的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_())

我知道代码很乱,但是非常感谢任何输入。

1 个答案:

答案 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_())

上面的代码导致:

documentation