如何避免Mayavi管道污染?

时间:2018-09-24 16:31:21

标签: python pyqt mayavi

下面是一些最小的代码,这些代码充分展示了我所谓的“管道污染”。每次按下“绘图”按钮时,MayaviScene编辑器(可通过图的左上角按钮访问)将更新图,但还会创建一个新场景的“外壳”,该外壳在管道中徘徊(如附件中所示)图片)。

我担心在我更复杂的项目中,这种堆积会产生不利影响。

有人可以指导我如何最好地设置Mayavi场景,使其简单地更新而不会产生过多的累积吗?我已经阅读了许多在线资料,但仍然不了解开发人员的逻辑。

Pipeline Pollution

import sys, os
import numpy as np

from pyface.qt import QtGui, QtCore
os.environ['ETS_TOOLKIT'] = 'qt4'

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

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

    def update_scene(self):
        Mayavi_Scene.fig1 = mlab.figure(1, bgcolor=(.5,.5,.5))
        self.scene.mlab.clf(figure=Mayavi_Scene.fig1)

        splot = mlab.points3d(P1.x, P1.y, P1.z,
                              scale_factor=0.05, figure=Mayavi_Scene.fig1)

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

class P1(QtGui.QWidget):
    # data starts out empty, wait for user input (below, via 'draw()'):
    x = []
    y = []
    z = []

    def __init__(self, parent=None):
        super(P1, self).__init__(parent)
        layout = QtGui.QGridLayout(self)
        layout.setContentsMargins(20,20,20,20)
        layout.setSpacing(10)

        self.viz1 = Mayavi_Scene()
        self.ui1 = self.viz1.edit_traits(parent=self, kind='subpanel').control
        layout.addWidget(self.ui1, 0, 0, 1, 1)

        def draw(): #a sample user input, could have been a custom data file, etc.
            P1.x = np.random.random((100,))
            P1.y = np.random.random((100,))
            P1.z = np.random.random((100,))
            Mayavi_Scene().update_scene()
            #repeated presses pollute MayaviScene pipeline

        # button to draw data:
        self.btn1 = QtGui.QPushButton('Draw',self)
        self.connect(self.btn1, QtCore.SIGNAL('clicked()'), draw)
        layout.addWidget(self.btn1, 1, 0, 1, 1)
        self.btn1.show()


class MainWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.window = P1(self) 
        self.setCentralWidget(self.window)
        self.show()

if __name__ == '__main__':
    app = QtGui.QApplication.instance()
    w = MainWindow()
    sys.exit(app.exec_())

1 个答案:

答案 0 :(得分:2)

原因可能是内部函数Mayavi_Scene().update_scene()中包含draw的行。每次调用draw时,都会创建一个新的Mayavi_Scene。接下来的P1类将draw定义为直接访问self.viz1的方法。我还用对draw

的引用替换了对self.draw的引用。
class P1(QtGui.QWidget):
    # data starts out empty, wait for user input (below, via 'draw()'):
    x = []
    y = []
    z = []

    def __init__(self, parent=None):
        super(P1, self).__init__(parent)
        layout = QtGui.QGridLayout(self)
        layout.setContentsMargins(20,20,20,20)
        layout.setSpacing(10)

        self.viz1 = Mayavi_Scene()
        self.ui1 = self.viz1.edit_traits(parent=self, kind='subpanel').control
        layout.addWidget(self.ui1, 0, 0, 1, 1)

        # button to draw data:
        self.btn1 = QtGui.QPushButton('Draw',self)
        # Connect the widget's draw method and the button
        self.connect(self.btn1, QtCore.SIGNAL('clicked()'), self.draw)
        layout.addWidget(self.btn1, 1, 0, 1, 1)
        self.btn1.show()

    def draw(self): #a sample user input, could have been a custom data file, etc.
        P1.x = np.random.random((100,))
        P1.y = np.random.random((100,))
        P1.z = np.random.random((100,))
        # Update the current scene without creating a new one.
        self.viz1.update_scene()