Python 根据当前选择的小部件更新变量

Python Updating Variables Based on Current Widget Selected

有几个例子可以说明如何做到这一点,但在尝试了所有这些之后,我不明白如何正确地实施它。我有一个程序,一个按钮创建一个内部包含内容的小部件并将其分配给网格布局,它还在 canvas 上创建一个图形。再次单击该按钮会创建另一个填充相同内容的小部件和另一个图形,并将其分配给布局。

其中一个内容是一个旋转框,它控制图形的旋转。我希望每个旋转框都能够单独控制用它创建的图形。这就是我被困的地方。

我如何拥有一个可以创建多个小部件的通用按钮,然后在每个旋转框的每个值发生变化时,都能够分辨出它来自哪个小部件,以便旋转正确的图形?我想要小部件 ID 或名称,或者我可以访问它。到目前为止,这是我所拥有的 - 提前致谢!:

from PyQt4.QtGui import *
from PyQt4.QtCore import *
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas, NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
import numpy as np 
import math
from scipy.optimize import fsolve
from mplwindow5 import Ui_mplMainWindow
from cU_widget import cU_Widget

class Viewer(QMainWindow, Ui_mplMainWindow):  
    def __init__(self, parent = None):
        super(Viewer, self).__init__(parent) 
        self.setupUi(self)      
        self.count = 0          
        self.cU_widget = []
        self.cU_rotate = []
        self.lbl_cU_rotate = []
        self.lbl_cU = []

        self.btn_cU.clicked.connect(self.add_cU) 

    def add_cU(self):
        self.cU_widget.append(int(self.count))

        self.cU_widget[self.count] = QWidget(self.scrollAreaWidgetContents)
        self.cU_widget[self.count].setMinimumSize(QSize(101, 81))
        self.cU_widget[self.count].setMaximumSize(QSize(101, 81))
        self.cU_widget[self.count].setObjectName("cU_widget"  + str(self.count+1))

        self.lbl_cU.append(int(self.count))

        self.lbl_cU[self.count] = QLabel("cU " + str(self.count+1), self.cU_widget[self.count])
        self.lbl_cU[self.count].setGeometry(QRect(0, 0, 101, 27))
        self.lbl_cU[self.count].setObjectName("lbl_cU_" + str(self.count+1))

        self.lbl_cU_rotate.append(int(self.count))

        self.lbl_cU_rotate[self.count] = QLabel("R", self.cU_widget[self.count])
        self.lbl_cU_rotate[self.count].setGeometry(QRect(6, 50, 20, 20))
        self.lbl_cU_rotate[self.count].setObjectName("lbl_cU_rotate"  + str(self.count+1))

        self.cU_rotate.append(int(self.count))

        self.cU_rotate[self.count] = QDoubleSpinBox(self.cU_widget[self.count])
        self.cU_rotate[self.count].setGeometry(QRect(20, 40, 71, 27))
        self.cU_rotate[self.count].setObjectName("cU_rotate"  + str(self.count+1))

        self.cU_rotate[self.count].valueChanged.connect(self.cU) # ??? What to use here

        self.gridLayout.addWidget(self.cU_widget[self.count], self.count, 0)

        self.cU()

    def cU(self):

        self.cU_rotate[self.count] = self.cU_rotate[self.count].value()  # ?? What to use here

        rotate = 1          
        tt = np.arange(0,1, 0.001)  

        lco_x0 = 0
        lco_x1 = 4

        lco_y0 = 1
        lco_y1 = 3

        cU_L_x0 = (lco_x0 * math.cos(math.radians(self.cU_rotate[self.count] + rotate))) - (lco_y0 * math.sin(math.radians(self.cU_rotate[self.count] + rotate)))
        cU_L_x1 = (lco_x1 * math.cos(math.radians(self.cU_rotate[self.count] + rotate))) - (lco_y1 * math.sin(math.radians(self.cU_rotate[self.count] + rotate)))
        #...   
        cU_L_y0 = (lco_x0 * math.sin(math.radians(self.cU_rotate[self.count] + rotate))) + (lco_y0 * math.cos(math.radians(self.cU_rotate[self.count] + rotate)))
        cU_L_y1 = (lco_x1 * math.sin(math.radians(self.cU_rotate[self.count] + rotate))) + (lco_y1 * math.cos(math.radians(self.cU_rotate[self.count] + rotate)))
        #...    
        cU_L_ax = ( 1  * cU_L_x0) 
        cU_L_bx = ((-6  * cU_L_x0) +(30 * cU_L_x1))
        # ...    
        cU_L_ay = ( 1  * cU_L_y0)
        cU_L_by = ((-6  * cU_L_y0) +(30 * cU_L_y1))
        #...    
        cU_L_xtt = (cU_L_ax * tt**2) + (cU_L_bx * tt) + 1
        cU_L_ytt = (cU_L_ay * tt**2) + (cU_L_by * tt) + 1

        self.mplContainer.canvas.ax.plot(cU_L_xtt, cU_L_ytt, 'r')

        self.mplContainer.canvas.ax.set_ylim([-5, 5])
        self.mplContainer.canvas.ax.set_xlim([0, 10])
        self.mplContainer.canvas.ax.set_aspect(1)

        self.mplContainer.canvas.draw()

        self.count += 1

app = QApplication(sys.argv)
viewer = Viewer()
viewer.show()
sys.exit(app.exec_())

这里是 mplwindow5:

from PyQt4 import QtCore, QtGui

class Ui_mplMainWindow(object):
    def setupUi(self, mplMainWindow):
        mplMainWindow.setObjectName("mplMainWindow")
        mplMainWindow.resize(1171, 826)
        self.centralwidget = QtGui.QWidget(mplMainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.mplContainer = MplWidget(self.centralwidget)
        self.mplContainer.setGeometry(QtCore.QRect(259, 20, 861, 741))
        self.mplContainer.setObjectName("mplContainer")
        self.inputContainer = QtGui.QWidget(self.centralwidget)
        self.inputContainer.setGeometry(QtCore.QRect(10, 20, 251, 741))
        self.inputContainer.setObjectName("inputContainer")

        self.scrollArea = QtGui.QScrollArea(self.inputContainer)
        self.scrollArea.setGeometry(QtCore.QRect(0, 160, 241, 581))
        self.scrollArea.setFrameShape(QtGui.QFrame.WinPanel)
        self.scrollArea.setLineWidth(1)
        self.scrollArea.setMidLineWidth(10)
        self.scrollArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
        self.scrollArea.setWidgetResizable(True)
        self.scrollArea.setObjectName("scrollArea")
        self.scrollAreaWidgetContents = QtGui.QWidget()
        self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 226, 577))
        self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")

        self.scrollLayout = QtGui.QVBoxLayout(self.scrollAreaWidgetContents)

        self.gridLayout = QtGui.QGridLayout()
        self.gridLayout.setObjectName("formLayout")
        self.gridLayout.setColumnStretch(0, 0)
        self.gridLayout.setColumnStretch(2, 4)

        self.scrollLayout.addLayout(self.gridLayout)
        self.scrollLayout.addStretch()

        self.scrollArea.setWidget(self.scrollAreaWidgetContents)
        mplMainWindow.setCentralWidget(self.centralwidget)

        self.btn_cU = QtGui.QPushButton("cU", self.inputContainer)
        self.btn_cU.setGeometry(QtCore.QRect(0, 0, 31, 27))
        self.btn_cU.setObjectName("btn_cU")  

        QtCore.QMetaObject.connectSlotsByName(mplMainWindow)



from mplwidget import MplWidget

mpl 小部件:

from PyQt4.QtGui import *
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas, NavigationToolbar2QT as NavigationToolbar 
from matplotlib.figure import Figure 

class MplCanvas(FigureCanvas):    
    def __init__(self):    
        self.fig = Figure()
        self.ax = self.fig.add_subplot(111)     
        FigureCanvas.__init__(self, self.fig)   
        FigureCanvas.setSizePolicy(self, QSizePolicy.Expanding, QSizePolicy.Preferred)
        FigureCanvas.updateGeometry(self)

class MplWidget(QWidget):
    def __init__(self, parent = None):  
        QWidget.__init__(self, parent)   
        self.main_widget = QWidget(self)
        self.canvas = MplCanvas()
        self.ntb = NavigationToolbar(self.canvas, self.main_widget)

        self.vbl = QGridLayout()
        self.vbl.addWidget(self.canvas)
        self.vbl.addWidget(self.ntb)

        self.setLayout(self.vbl)

由于没有必要进行大量的数学运算来解决这个问题,所以我忽略了那部分。因此,假设我们想要使用 SpinBoxes 更改多条线的斜率。

一个选项是使线条成为 class 的一部分,该 class 控制 SpinBoxes 以及 matplotlib 线条。我在下面的代码中称它为 LineWidget。按下按钮时,将创建一个新的 LineWidget 实例并将其添加到滚动区域,您可以在其中操作参数。一旦参数更改,该行就会更新。

这是一个完整的示例,我还简化了其余代码。

import sys
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
import numpy as np 
from PyQt4 import QtGui , QtCore

class Viewer(QtGui.QMainWindow):  
    def __init__(self, parent = None):
        super(Viewer, self).__init__(parent) 
        self.setupUI() 
        self.ax = self.fig.add_subplot(111)
        self.count = 0          
        self.container = []
        self.button.clicked.connect(self.addLine) 

    def setupUI(self):
        self.centralwidget = QtGui.QWidget(self)
        self.setCentralWidget(self.centralwidget)
        self.centralwidget.setLayout(QtGui.QHBoxLayout())

        self.leftWidget = QtGui.QWidget(self)
        self.leftWidget.setMinimumWidth(200)
        self.leftWidget.setLayout(QtGui.QVBoxLayout())

        self.mplWidget = QtGui.QWidget(self)
        self.mplWidget.setLayout(QtGui.QVBoxLayout())

        self.fig = Figure()
        self.canvas = FigureCanvas(self.fig)
        self.ntb = NavigationToolbar(self.canvas, self.mplWidget)
        self.mplWidget.layout().addWidget(self.canvas)
        self.mplWidget.layout().addWidget(self.ntb)

        self.button = QtGui.QPushButton("Push")

        self.scrollWidget = QtGui.QWidget()
        self.scrollLayout = QtGui.QVBoxLayout()
        self.scrollWidget.setLayout(self.scrollLayout)
        self.scrollLayout.addStretch()
        self.scrollArea = QtGui.QScrollArea()
        self.scrollArea.setWidgetResizable(True)
        self.scrollArea.setWidget(self.scrollWidget)

        self.leftWidget.layout().addWidget(self.button)
        self.leftWidget.layout().addWidget(self.scrollArea)

        self.centralwidget.layout().addWidget(self.leftWidget)
        self.centralwidget.layout().addWidget(self.mplWidget)

    def addLine(self):
        b = LineWidget(self.count, self.ax)
        self.container.append(b)
        self.scrollLayout.insertWidget(self.scrollLayout.count() - 1, b)
        self.count += 1


class LineWidget(QtGui.QWidget):
    def __init__( self, number, ax, R=0, parent=None, **kwargs):
        super(LineWidget, self).__init__(parent)
        self.number = number
        label = QtGui.QLabel("cU " + str(self.number))
        self.spin = QtGui.QDoubleSpinBox()
        self.spin.setSingleStep(0.2)
        self.spin.setRange(-100,100)
        self.setLayout(QtGui.QHBoxLayout())
        self.layout().addWidget(label)
        self.layout().addWidget(self.spin)

        self.R = R
        self.t = np.linspace(0,1)
        self.f = lambda t, R: R*t
        self.ax = ax
        self.line, = self.ax.plot([],[], **kwargs)

        self.update()
        self.spin.valueChanged.connect(self.changed)

    def changed(self):
        self.R = self.spin.value()
        self.update()

    def update(self):
        self.line.set_data(self.t, self.f(self.t, self.R))
        self.ax.relim()
        self.ax.autoscale_view()
        self.ax.figure.canvas.draw_idle()


app = QtGui.QApplication(sys.argv)
viewer = Viewer()
viewer.show()
sys.exit(app.exec_())