Mayavi 可以集成到 PyQt5 中吗?

问题描述 投票:0回答:2

是否可以将 Mayavi 3D 绘图集成到使用 pyqt5 制作的 GUI 中? 在 mayavi 文档中我发现了这一点: http://docs.enthought.com/mayavi/mayavi/building_applications.html但是当我运行代码时出现错误:“RuntimeError:没有为工具包 qt5 找到 Traitsui.toolkits 插件”。

这是代码:

# First, and before importing any Enthought packages, set the ETS_TOOLKIT
# environment variable to qt4, to tell Traits that we will use Qt.
import os
os.environ['ETS_TOOLKIT'] = 'qt4'
# By default, the PySide binding will be used. If you want the PyQt bindings
# to be used, you need to set the QT_API environment variable to 'pyqt'
#os.environ['QT_API'] = 'pyqt'

# To be able to use PySide or PyQt4 and not run in conflicts with traits,
# we need to import QtGui and QtCore from pyface.qt
from pyface.qt import QtGui, QtCore
# Alternatively, you can bypass this line, but you need to make sure that
# the following lines are executed before the import of PyQT:
#   import sip
#   sip.setapi('QString', 2)

from traits.api import HasTraits, Instance, on_trait_change
from traitsui.api import View, Item
from mayavi.core.ui.api import MayaviScene, MlabSceneModel, \
        SceneEditor


################################################################################
#The actual visualization
class Visualization(HasTraits):
    scene = Instance(MlabSceneModel, ())

    @on_trait_change('scene.activated')
    def update_plot(self):
        # This function is called when the view is opened. We don't
        # populate the scene when the view is not yet open, as some
        # VTK features require a GLContext.

        # We can do normal mlab calls on the embedded scene.
        self.scene.mlab.test_points3d()

    # the layout of the dialog screated
    view = View(Item('scene', editor=SceneEditor(scene_class=MayaviScene),
                     height=250, width=300, show_label=False),
                resizable=True # We need this to resize with the parent widget
                )


################################################################################
# The QWidget containing the visualization, this is pure PyQt4 code.
class MayaviQWidget(QtGui.QWidget):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        layout = QtGui.QVBoxLayout(self)
        layout.setContentsMargins(0,0,0,0)
        layout.setSpacing(0)
        self.visualization = Visualization()

        # If you want to debug, beware that you need to remove the Qt
        # input hook.
        #QtCore.pyqtRemoveInputHook()
        #import pdb ; pdb.set_trace()
        #QtCore.pyqtRestoreInputHook()

        # The edit_traits call will generate the widget to embed.
        self.ui = self.visualization.edit_traits(parent=self,
                                                 kind='subpanel').control
        layout.addWidget(self.ui)
        self.ui.setParent(self)


if __name__ == "__main__":
    # Don't create a new QApplication, it would unhook the Events
    # set by Traits on the existing QApplication. Simply use the
    # '.instance()' method to retrieve the existing one.
    app = QtGui.QApplication.instance()
    container = QtGui.QWidget()
    container.setWindowTitle("Embedding Mayavi in a PyQt4 Application")
    # define a "complex" layout to test the behaviour
    layout = QtGui.QGridLayout(container)

    # put some stuff around mayavi
    label_list = []
    for i in range(3):
        for j in range(3):
            if (i==1) and (j==1):continue
            label = QtGui.QLabel(container)
            label.setText("Your QWidget at (%d, %d)" % (i,j))
            label.setAlignment(QtCore.Qt.AlignHCenter|QtCore.Qt.AlignVCenter)
            layout.addWidget(label, i, j)
            label_list.append(label)
    mayavi_widget = MayaviQWidget(container)

    layout.addWidget(mayavi_widget, 1, 1)
    container.show()
    window = QtGui.QMainWindow()
    window.setCentralWidget(container)
    window.show()

    # Start the main event loop.
    app.exec_()
python qt pyqt5 mayavi
2个回答
2
投票

是的,可以将 mayavi 3d 绘图集成到使用 pyqt5 制作的 GUI 中。不仅可以显示剧情还可以显示动画!通过在 GUI 中的任何位置嵌入 mayavi 场景,几乎您使用单独的 Mayavi 窗口执行的所有操作都可以在 PyQt5 Gui 中完成。

如果您的代码与此链接完全相同:Qt 嵌入示例。然后尝试在单独的文件中运行此代码,它应该可以工作。如果没有,您必须正确重新安装库。

您可以参考下面的代码(简单版本)将mayavi嵌入到您的GUI中:

    from PyQt5 import  QtWidgets
    import os
    import numpy as np
    from numpy import cos
    from mayavi.mlab import contour3d

    os.environ['ETS_TOOLKIT'] = 'qt4'
    from pyface.qt import QtGui, QtCore
    from traits.api import HasTraits, Instance, on_trait_change
    from traitsui.api import View, Item
    from mayavi.core.ui.api import MayaviScene, MlabSceneModel, SceneEditor


    ## create Mayavi Widget and show

    class Visualization(HasTraits):
        scene = Instance(MlabSceneModel, ())

        @on_trait_change('scene.activated')
        def update_plot(self):
        ## PLot to Show        
            x, y, z = np.ogrid[-3:3:60j, -3:3:60j, -3:3:60j]
            t = 0
            Pf = 0.45+((x*cos(t))*(x*cos(t)) + (y*cos(t))*(y*cos(t))-(z*cos(t))*(z*cos(t)))
            obj = contour3d(Pf, contours=[0], transparent=False)

        view = View(Item('scene', editor=SceneEditor(scene_class=MayaviScene),
                         height=250, width=300, show_label=False),
                    resizable=True )

    class MayaviQWidget(QtGui.QWidget):
        def __init__(self, parent=None):
            QtGui.QWidget.__init__(self, parent)
            layout = QtGui.QVBoxLayout(self)
            layout.setContentsMargins(0,0,0,0)
            layout.setSpacing(0)
            self.visualization = Visualization()

            self.ui = self.visualization.edit_traits(parent=self,
                                                     kind='subpanel').control
            layout.addWidget(self.ui)
            self.ui.setParent(self)


    #### PyQt5 GUI ####
    class Ui_MainWindow(object):
        def setupUi(self, MainWindow):

        ## MAIN WINDOW
            MainWindow.setObjectName("MainWindow")
            MainWindow.setGeometry(200,200,1100,700)

        ## CENTRAL WIDGET
            self.centralwidget = QtWidgets.QWidget(MainWindow)
            self.centralwidget.setObjectName("centralwidget")
            MainWindow.setCentralWidget(self.centralwidget)

        ## GRID LAYOUT
            self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
            self.gridLayout.setObjectName("gridLayout")


        ## BUTTONS
            self.button_default = QtWidgets.QPushButton(self.centralwidget)
            self.button_default.setObjectName("button_default")
            self.gridLayout.addWidget(self.button_default, 0, 0, 1,1)

            self.button_previous_data = QtWidgets.QPushButton(self.centralwidget)
            self.button_previous_data.setObjectName("button_previous_data")
            self.gridLayout.addWidget(self.button_previous_data, 1, 1, 1,1)
        ## Mayavi Widget 1    
            container = QtGui.QWidget()
            mayavi_widget = MayaviQWidget(container)
            self.gridLayout.addWidget(mayavi_widget, 1, 0,1,1)
        ## Mayavi Widget 2
            container1 = QtGui.QWidget()
            mayavi_widget = MayaviQWidget(container1)
            self.gridLayout.addWidget(mayavi_widget, 0, 1,1,1)

        ## SET TEXT 
            self.retranslateUi(MainWindow)
            QtCore.QMetaObject.connectSlotsByName(MainWindow)

        def retranslateUi(self, MainWindow):
            _translate = QtCore.QCoreApplication.translate
            MainWindow.setWindowTitle(_translate("MainWindow", "Simulator"))
            self.button_default.setText(_translate("MainWindow","Default Values"))
            self.button_previous_data.setText(_translate("MainWindow","Previous Values"))
    if __name__ == "__main__":
        import sys
        app = QtWidgets.QApplication(sys.argv)
        app.setStyle('Fusion')
        MainWindow = QtWidgets.QMainWindow()

        ui = Ui_MainWindow()
        ui.setupUi(MainWindow)
        MainWindow.show()
        sys.exit(app.exec_())

尝试在专用控制台中运行此代码。希望这对您有帮助。


0
投票

Mayavi 可以集成到 PyQt6 中吗?我们如何修改此代码以与 PyQt6 一起使用?我一直在尝试修改它,但无法使其正常工作。

© www.soinside.com 2019 - 2024. All rights reserved.