使用主要 window 中的数据在一秒钟内绘制图 window

Making a plot in a second window using data from main window

我正在尝试制作一个程序,其中有一个主要 window 和第二个 window。第二个 window 应该通过选中主 window 中的复选框来打开,并通过取消选中它来关闭。

下面的最小示例已经可以正常工作(感谢 ImportanceOfBeingErnest!),但我想通过更改主要 window.

解决方法:见第一个答案中的第5条评论!

      import sys
      from PyQt4 import QtGui, QtCore

      from matplotlib import pyplot as plt
      from mpl_toolkits.mplot3d import Axes3D
      from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
      from matplotlib import animation

      import numpy as np


      class Newsphere(QtGui.QMainWindow):

          def __init__(self):
              super(Newsphere, self).__init__()
              self.mainbox = QtGui.QWidget()
              self.mainbox.setLayout(QtGui.QHBoxLayout())
              self.setCentralWidget(self.mainbox)
              self.spin = QtGui.QSpinBox()
              self.spin.setValue(20)
              self.spin.setMaximum(100)
              self.spin.setMinimum(-100)
              self.checkPlot = QtGui.QCheckBox("Check")
              self.mainbox.layout().addWidget(self.spin)
              self.mainbox.layout().addWidget(self.checkPlot)

              self.Plot = None
              self.checkPlot.clicked.connect(self.showPlot)

         def showPlot(self):
             if self.Plot == None:
                 self.Plot = Plot(self.kinematic())
                 self.Plot.show()
                 # register signal for closure
                 self.Plot.signalClose.connect(self.uncheck)
                 # register signal for spin value changed
                 self.spin.valueChanged.connect(self.kinematic)
             else:
                 self.Plot.close()
                 self.Plot = None

        def kinematic(self):

            x = self.spin.value() / 100

            v = np.matrix([[1.,x,0.],[0.,1.,0.],[0.,0.,1.]])
            zero = np.matrix([[0.,0.,0.],[0.,0.,0.],[0.,0.,0.]])

            pos = np.hstack([v, zero])

            return pos

        def uncheck(self):
            self.checkPlot.setChecked(False)
            self.Plot = None

    class Plot(QtGui.QWidget):

        signalClose = QtCore.pyqtSignal()

        def __init__(self, pos=None):
            super(Plot, self).__init__()
            self.setLayout(QtGui.QHBoxLayout())

            self.fig = plt.figure()
            self.ax = self.fig.add_subplot(111,projection = '3d')
            self.fig.tight_layout()
            self.ax.view_init(40, 225)

            ''' dashed coordinate system '''
            self.ax.plot([0,1], [0,0], [0,0], label='$X_0$', linestyle="dashed", color="red")
            self.ax.plot([0,0], [0,-10], [0,0], label='$Y_0$', linestyle="dashed", color="green")
            self.ax.plot([0,0], [0,0], [0,1], label='$Z_0$', linestyle="dashed", color="blue")

            self.ax.set_xlim3d(-3,3)
            self.ax.set_ylim3d(-3,3)
            self.ax.set_zlim3d(-3,3)

            self.canvas = FigureCanvas(self.fig)
            self.layout().addWidget(self.canvas)

            self.pos = pos

            self.setup_plot()

            self.ani = animation.FuncAnimation(self.fig, self.update_plot, init_func=self.setup_plot, blit=True)

        def setup_plot(self):

            self.ax.legend(loc='best')

            self.position = self.ax.quiver(0, 0, 0, 0, 0, 0, pivot="tail", color="black")

            return self.position,

        def update_plot(self, i):

            x_zero = self.pos[:,3]
            y_zero = self.pos[:,4]
            z_zero = self.pos[:,5]

            v_x = self.pos[0,0:3]
            v_y = self.pos[1,0:3]
            v_z = self.pos[2,0:3]

            self.position = self.ax.quiver(-x_zero, -y_zero, z_zero, -v_x[0,:], v_y[0,:], v_z[0,:], pivot="tail", color="black")
            self.canvas.draw()

            return self.position,

        # We need to make sure the animation stops, when the window is closed
        def closeEvent(self, event):
            self.signalClose.emit()
            self.close()
            super(Plot, self).closeEvent(event)

        def close(self):
            self.ani.event_source.stop()
            super(Plot, self).close()


    if __name__ == '__main__':

        app = QtGui.QApplication(sys.argv)
        main = Newsphere()
        main.show()
        sys.exit(app.exec_())

这是我认为您正在努力实现的工作示例。
Main Window 有一个旋转框和一个复选框。单击复选框后,将显示一个带有绘图的新 window 并开始播放动画。当前值和一些数组将被提供给绘图 window。如果在动画 运行 时更改微调框值,它将更新。当绘图 window 关闭或取消选中复选框时,动画将停止(并被删除)。

import sys
from PyQt4 import QtGui, QtCore

from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib import animation

import numpy as np


class Newsphere(QtGui.QMainWindow):

    def __init__(self):
        super(Newsphere, self).__init__()
        self.mainbox = QtGui.QWidget()
        self.mainbox.setLayout(QtGui.QHBoxLayout())
        self.setCentralWidget(self.mainbox)
        self.spin = QtGui.QSpinBox()
        self.spin.setValue(5)
        self.spin.setMaximum(10)
        self.spin.setMinimum(1)
        self.checkPlot = QtGui.QCheckBox("Check")
        self.mainbox.layout().addWidget(self.spin)
        self.mainbox.layout().addWidget(self.checkPlot)

        self.Plot = None
        self.checkPlot.clicked.connect(self.showPlot)

    def showPlot(self):
        if self.Plot == None:
            self.Plot = Plot(self.kinematic(), self.spin.value())
            self.Plot.show()
            # register signal for closure
            self.Plot.signalClose.connect(self.uncheck)
            # register signal for spin value changed
            self.spin.valueChanged.connect(self.Plot.update_factor)
        else:
            self.Plot.close()
            self.Plot = None

    def kinematic(self):
        v = np.array([[1.,2.,3.],[2.,1.,3.],[3.,2.,1.]])
        return v

    def uncheck(self):
        self.checkPlot.setChecked(False)
        self.Plot = None

class Plot(QtGui.QWidget):

    signalClose = QtCore.pyqtSignal()

    def __init__(self, v=None, factor=1):
        super(Plot, self).__init__()
        self.setLayout(QtGui.QHBoxLayout())

        self.fig = plt.figure()
        self.ax = self.fig.add_subplot(111,projection = '3d')
        self.ax.set_aspect('equal')
        self.fig.tight_layout()
        self.ax.view_init(40, 225)

        self.ax.set_xlim3d(0,3)
        self.ax.set_ylim3d(0,3)
        self.ax.set_zlim3d(0,4)

        self.canvas = FigureCanvas(self.fig)
        self.layout().addWidget(self.canvas)

        self.pos = v

        self.setup_plot()
        self.update_factor(factor)

        self.ani = animation.FuncAnimation(self.fig, self.update_plot, blit=False)

    def setup_plot(self):
        xpos, ypos = np.meshgrid(np.arange(self.pos.shape[0]),np.arange(self.pos.shape[1]) )
        self.xpos = xpos.flatten('F')
        self.ypos = ypos.flatten('F')
        self.zpos = np.zeros_like(self.xpos)
        self.bar = None

    def update_factor(self, factor):
        self.factor = factor
        self.dx = np.ones_like(self.xpos)*np.min(np.abs(self.factor/10.), 0.1)
        self.dy = self.dx.copy()

    def update_plot(self, i):

        if self.bar != None:
            self.bar.remove()
            del self.bar
        pos = self.pos+np.sin(i/8.)
        dz = pos.flatten()

        self.bar = self.ax.bar3d(self.xpos, self.ypos, self.zpos, self.dx, self.dy, dz, 
                        color=(1.-self.factor/10.,0,self.factor/10.), zsort='average', linewidth=0)

        self.canvas.draw()

    # We need to make sure the animation stops, when the window is closed
    def closeEvent(self, event):
        self.signalClose.emit()
        self.close()
        super(Plot, self).closeEvent(event)

    def close(self):
        self.ani.event_source.stop()
        super(Plot, self).close()


if __name__ == '__main__':

    app = QtGui.QApplication(sys.argv)    
    main = Newsphere()
    main.show()
    sys.exit(app.exec_())

因为我不确定你想要动画什么,我把情节改成了条形图,但你可以把它改回你需要的任何东西。希望对您有所帮助。