这里Mayavi指Mayavi2
一、UI建立
用qt的designer工具简单建立一个UI,如下图所示。
对象层级关系为:
其中,verticalLayout是给mayavi场景预留的位置。
保存ui文件,然后用qt的pyuic工具转换为py文件,如下。其中,input.ui是 Qt Designer生成的.ui 文件的路径,output.py是要生成的Python代码文件的路径。-o是一个选项参数,用于指定输出文件的路径。
pyuic5 input.ui -o output.py
转换得到的py文件如下。在通常的开发中,ui需要反复修改,下述py文件会反复生成,所以不要在下述代码中加入任何人工修改内容。
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'output.ui'
#
# Created by: PyQt5 UI code generator 5.15.7
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.centralwidget)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.groupBox = QtWidgets.QGroupBox(self.centralwidget)
font = QtGui.QFont()
font.setFamily("Microsoft YaHei UI")
font.setPointSize(12)
self.groupBox.setFont(font)
self.groupBox.setObjectName("groupBox")
self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.groupBox)
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.verticalLayout = QtWidgets.QVBoxLayout()
self.verticalLayout.setObjectName("verticalLayout")
self.horizontalLayout_3.addLayout(self.verticalLayout)
self.horizontalLayout.addWidget(self.groupBox)
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
font = QtGui.QFont()
font.setFamily("Microsoft YaHei UI")
font.setPointSize(12)
self.pushButton.setFont(font)
self.pushButton.setObjectName("pushButton")
self.horizontalLayout.addWidget(self.pushButton)
self.horizontalLayout.setStretch(0, 9)
self.horizontalLayout.setStretch(1, 1)
self.horizontalLayout_2.addLayout(self.horizontalLayout)
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "mayavi_demo"))
self.groupBox.setTitle(_translate("MainWindow", "mayavi_scene"))
self.pushButton.setText(_translate("MainWindow", "显示"))
新建立一个py文件来编写逻辑,在下文中称该文件为逻辑文件。在逻辑文件里创建一个继承qt的QMainWindow类的子类,命名为MainWindow,在该子类里实例化我们建立的ui,将其看作MainWindow的一个属性。
from PyQt5.QtWidgets import QApplication, QMainWindow
import sys
from output import Ui_MainWindow
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(QMainWindow, self).__init__(parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
if __name__ == '__main__':
app = QApplication(sys.argv)
mw = MainWindow()
mw.show()
sys.exit(app.exec_())
运行上述代码可以查看我们刚建立的窗口。
二、插入mayavi场景
继续修改逻辑文件。先给出完整的需要导入的库。
from PyQt5.QtWidgets import QApplication, QMainWindow
import sys
from output import Ui_MainWindow
from traits.api import HasTraits, Instance
from traitsui.api import View, Item
from tvtk.pyface.scene_editor import SceneEditor
from mayavi.tools.mlab_scene_model import MlabSceneModel
from mayavi.core.ui.mayavi_scene import MayaviScene
在逻辑文件里创建一个继承HasTraits类的子类Visualization,
class Visualization(HasTraits):
scene = Instance(MlabSceneModel, ())
# the layout of the dialog created
view = View(Item('scene', editor=SceneEditor(scene_class=MayaviScene),
height=250, width=300, show_label=False),)
def __init__(self):
HasTraits.__init__(self)
在MainWindow类里建立Visualization的对象,获取mayavi场景,将mayavi场景添加到预留的位置里,修改后的MainWindow类如下。
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(QMainWindow, self).__init__(parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.visualization = Visualization()
self.mayavi_scence = self.visualization.edit_traits().control
self.ui.verticalLayout.addWidget(self.mayavi_scence)
继续修改MainWindow,建立一个按钮事件来显示科学绘图对象,这里还是来绘制球谐函数的面。修改完的完整MainWindow如下。
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(QMainWindow, self).__init__(parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.visualization = Visualization()
self.mayavi_scence = self.visualization.edit_traits().control
self.ui.verticalLayout.addWidget(self.mayavi_scence)
self.ui.pushButton.clicked.connect(self.button_event)
def button_event(self):
# Create the data.
from numpy import pi, sin, cos, mgrid
dphi, dtheta = pi / 250.0, pi / 250.0
[phi, theta] = mgrid[0:pi + dphi * 1.5:dphi, 0:2 * pi + dtheta * 1.5:dtheta]
m0 = 4; m1 = 3; m2 = 2; m3 = 3; m4 = 6; m5 = 2; m6 = 6; m7 = 4;
r = sin(m0 * phi) ** m1 + cos(m2 * phi) ** m3 + sin(m4 * theta) ** m5 + cos(m6 * theta) ** m7
x = r * sin(phi) * cos(theta)
y = r * cos(phi)
z = r * sin(phi) * sin(theta)
# View it.
self.visualization.scene.mlab.mesh(x, y, z)
至此,运行逻辑文件代码。会报一个错误。
点击报错最后一个文件链接,把下面一行代码的qt4改为qt。
from traitsui.qt4.editor import Editor
再次运行。正常应该再无任何报错了,运行结果如下。
点击显示按钮来触发按钮事件,结果如下。
三、逻辑文件完整代码
最后,贴上逻辑文件完整代码。
from PyQt5.QtWidgets import QApplication, QMainWindow
import sys
from output import Ui_MainWindow
from traits.api import HasTraits, Instance
from traitsui.api import View, Item
from tvtk.pyface.scene_editor import SceneEditor
from mayavi.tools.mlab_scene_model import MlabSceneModel
from mayavi.core.ui.mayavi_scene import MayaviScene
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(QMainWindow, self).__init__(parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.visualization = Visualization()
self.mayavi_scence = self.visualization.edit_traits().control
self.ui.verticalLayout.addWidget(self.mayavi_scence)
self.ui.pushButton.clicked.connect(self.button_event)
def button_event(self):
# Create the data.
from numpy import pi, sin, cos, mgrid
dphi, dtheta = pi / 250.0, pi / 250.0
[phi, theta] = mgrid[0:pi + dphi * 1.5:dphi, 0:2 * pi + dtheta * 1.5:dtheta]
m0 = 4; m1 = 3; m2 = 2; m3 = 3; m4 = 6; m5 = 2; m6 = 6; m7 = 4;
r = sin(m0 * phi) ** m1 + cos(m2 * phi) ** m3 + sin(m4 * theta) ** m5 + cos(m6 * theta) ** m7
x = r * sin(phi) * cos(theta)
y = r * cos(phi)
z = r * sin(phi) * sin(theta)
# View it.
self.visualization.scene.mlab.mesh(x, y, z)
class Visualization(HasTraits):
scene = Instance(MlabSceneModel, ())
def __init__(self):
HasTraits.__init__(self)
# the layout of the dialog created
view = View(Item('scene', editor=SceneEditor(scene_class=MayaviScene),
height=250, width=300, show_label=False), )
if __name__ == '__main__':
app = QApplication(sys.argv)
mw = MainWindow()
mw.show()
sys.exit(app.exec_())
四、最后
一点简单的mayavi应用,如果对你有帮助,就点个赞吧,虽然没啥用,但看到有人点赞还是开心的。