Embed an interactive 3D plot in PySide
在Pyside GUI中嵌入交互式3D绘图的最佳方法是什么?我看了一些嵌入在Pyside GUI中的二维图的示例:
让Pyside与Matplotlib合作嵌入PYQT的Matplotlib交互图python/matplotlib/pyside快速时间跟踪滚动
但是,我所寻找的功能并不完全相同。图形需要根据用户的鼠标输入进行旋转和缩放,方式与在单独窗口中绘制图形的方式相同。
我尽量避免手动输入和编写将鼠标点击+移动转换为图形旋转和画布重新绘制的函数——即使这是唯一的方法,我甚至不知道该怎么做。但我认为(没有双关语)应该有一种方法可以重用已经存在的功能,在自己的窗口中创建三维绘图。
这是我的密码。它按预期工作,但情节不是交互式的。感谢您的任何建议!
编辑:我根据tcaswell的修正修正了figureCanvas的使用。我还从Matplotlib事件处理和选择文档中添加了一些内容,以显示这个数字似乎是在鼠标单击时获取事件。
最终编辑:下面的代码现在根据需要生成绘图。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | # -*- coding: utf-8 -*- from PySide import QtCore, QtGui import numpy as np import matplotlib import sys # specify the use of PySide matplotlib.rcParams['backend.qt4'] ="PySide" # import the figure canvas for interfacing with the backend from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg \ as FigureCanvas # import 3D plotting from mpl_toolkits.mplot3d import Axes3D # @UnusedImport from matplotlib.figure import Figure # Auto-generated code from QT Designer ---------------------------------------- class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(750, 497) self.centralwidget = QtGui.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.horizontalLayout_2 = QtGui.QHBoxLayout(self.centralwidget) self.horizontalLayout_2.setObjectName("horizontalLayout_2") self.frame_2 = QtGui.QFrame(self.centralwidget) self.frame_2.setFrameShape(QtGui.QFrame.StyledPanel) self.frame_2.setFrameShadow(QtGui.QFrame.Raised) self.frame_2.setObjectName("frame_2") self.verticalLayout = QtGui.QVBoxLayout(self.frame_2) self.verticalLayout.setObjectName("verticalLayout") self.label = QtGui.QLabel(self.frame_2) self.label.setObjectName("label") self.verticalLayout.addWidget(self.label) self.label_2 = QtGui.QLabel(self.frame_2) self.label_2.setObjectName("label_2") self.verticalLayout.addWidget(self.label_2) self.lineEdit = QtGui.QLineEdit(self.frame_2) sizePolicy = QtGui.QSizePolicy( QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.lineEdit.sizePolicy().hasHeightForWidth()) self.lineEdit.setSizePolicy(sizePolicy) self.lineEdit.setObjectName("lineEdit") self.verticalLayout.addWidget(self.lineEdit) spacerItem = QtGui.QSpacerItem( 20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) self.verticalLayout.addItem(spacerItem) self.horizontalLayout_2.addWidget(self.frame_2) self.frame_plot = QtGui.QFrame(self.centralwidget) self.frame_plot.setMinimumSize(QtCore.QSize(500, 0)) self.frame_plot.setFrameShape(QtGui.QFrame.StyledPanel) self.frame_plot.setFrameShadow(QtGui.QFrame.Raised) self.frame_plot.setObjectName("frame_plot") self.horizontalLayout_2.addWidget(self.frame_plot) MainWindow.setCentralWidget(self.centralwidget) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): MainWindow.setWindowTitle(QtGui.QApplication.translate( "MainWindow","MainWindow", None, QtGui.QApplication.UnicodeUTF8)) self.label.setText(QtGui.QApplication.translate("MainWindow", "This is a qlabel.", None, QtGui.QApplication.UnicodeUTF8)) self.label_2.setText(QtGui.QApplication.translate("MainWindow", "And this is another one.", None, QtGui.QApplication.UnicodeUTF8)) self.lineEdit.setText(QtGui.QApplication.translate("MainWindow", "Text goes here.", None, QtGui.QApplication.UnicodeUTF8)) # Auto-generated code from QT Designer ---------------------------------------- class MainWindow(QtGui.QMainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) # intialize the window self.ui = Ui_MainWindow() self.ui.setupUi(self) # create the matplotlib widget and put it in the frame on the right self.ui.plotWidget = Mpwidget(parent=self.ui.frame_plot) class Mpwidget(FigureCanvas): def __init__(self, parent=None): self.figure = Figure(facecolor=(0, 0, 0)) super(Mpwidget, self).__init__(self.figure) self.setParent(parent) # plot random 3D data self.axes = self.figure.add_subplot(111, projection='3d') self.data = np.random.random((3, 100)) self.axes.plot(self.data[0, :], self.data[1, :], self.data[2, :]) if __name__ =="__main__": app = QtGui.QApplication(sys.argv) mw = MainWindow() mw.show() # adjust the frame size so that it fits right after the window is shown s = mw.ui.frame_plot.size() mw.ui.plotWidget.setGeometry(1, 1, s.width() - 2, s.height() - 2) sys.exit(app.exec_()) |
型
你没有使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | class Mpwidget(FigureCanvas): def __init__(self, parent=None): self.figure = Figure(facecolor=(0, 0, 0)) super(Mpwidget, self).__init__(self.figure) # this object _is_ your canvas self.setParent(parent) # plot random 3D data self.axes = self.figure.add_subplot(111, projection='3d') self.data = np.random.random((3, 100)) self.axes.plot(self.data[0, :], self.data[1, :], self.data[2, :]) if __name__ =="__main__": app = QtGui.QApplication(sys.argv) mw = MainWindow() mw.show() # adjust the frame size so that it fits right after the window is shown s = mw.ui.frame_plot.size() mw.ui.plotWidget.setGeometry(1, 1, s.width() - 2, s.height() - 2) sys.exit(app.exec_()) |
每次你给
型
1)在添加轴之前创建图形转换器。请参阅https://stackoverflow.com/a/9007892/3962328
1 2 | canvas = FigureCanvas(fig) ax = figure.add_subplot(111, projection='3d') |
号
或
1 2 3 4 5 | class MyFigureCanvas(FigureCanvas): def __init__(self): self.figure = Figure() super(FigureCanvas, self).__init__(self.figure) self.axes = self.figure.add_subplot(111, projection='3d') |
2)尝试ax.mouse_init()恢复连接:
1 2 3 4 5 | ... ax = fig.gca(projection="3d") ... canvas = FigureCanvas(fig) ax.mouse_init() |
。