5

インタラクティブな 3D プロットを PySide GUI に埋め込む最良の方法は何ですか? ここで、PySide GUI に埋め込まれた 2D プロットの例をいくつか見てきました。

PySide を Matplotlib で動作させる
PyQt に組み込まれた Matplotlib インタラクティブ グラフ
Python/Matplotlib/Pyside 高速タイムトレース スクロール

ただし、私が探している機能はまったく同じではありません。Figure は、別のウィンドウに描画されている場合と同じように、ユーザーからのマウス入力に基づいて回転およびズームする必要があります。

私は、手動でマウスクリック+移動を図の回転とキャンバスの再描画に変換するための関数を手動で作成する必要を避けようとしています-それが唯一の方法であっても、その方法がわかりません。しかし、独自のウィンドウで 3D プロットを作成するために既に存在する機能を再利用する方法があるはずだと考えています (しゃれは意図していません)。

これが私のコードです。意図したとおりに機能しますが、プロットはインタラクティブではありません。どんなアドバイスでも大歓迎です!

編集: tcaswellの修正に従って、 FigureCanvas の使用を修正しました。また、図がマウスクリック時にイベントを取得しているように見えることを示すために、matplotlibイベント処理とピッキングのドキュメントから少し追加しました。

最終編集:次のコードは、必要に応じてプロットを生成するようになりました。

# -*- 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_())
4

2 に答える 2

6

あなたはFigureCanvas正しく使用していません:

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

呼び出すたびFigureCanvas(..)に、図を新しいキャンバス (表示されていないものFigureCanvas) にアタッチしていたため、コールバックは発生しませんでした (表示されていない でリッスンしていたためFigureCanvas)。

于 2013-08-16T16:53:59.537 に答える
1

1) 軸を追加する前に FigureCanvas を作成します。https://stackoverflow.com/a/9007892/3962328を参照してください

canvas = FigureCanvas(fig)
ax = figure.add_subplot(111, projection='3d')

また

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() を試して接続を復元します。

...
ax = fig.gca(projection="3d")
...
canvas = FigureCanvas(fig)
ax.mouse_init()
于 2014-09-11T07:07:29.230 に答える