简体   繁体   中英

How to have dynamic fields in PyQt5?

I have a piece of PyQt5 code like this:

 def displayDefaultParameters(self):
        #Create Default Parameters
        self.useDFParamsLabel = QLabel(self)
        self.useDFParamsLabel.setText('Default Parameters:')
        self.useDFParamsLabelFont = QFont("Calibri", 15)
        self.useDFParamsLabelFont.setUnderline(True)
        self.useDFParamsLabel.setFont(self.useDFParamsLabelFont)
        self.useDFParamsLabel.setGeometry(QRect(650, 75, 220, 50))
        self.useDFParamsLabel.show()

        self.DFParamsQLabel = QLabel(self)
        pixmap = QPixmap('question1.png')
        self.DFParamsQLabel.setPixmap(pixmap)
        self.DFParamsQLabel.setToolTip('Default Parameters when \nno input is provided.')
        self.DFParamsQLabel.move(860,85)

        #FIELDS THAT WILL BE CHANGED DYNAMICALLY

        self.paramFont = QFont("Arial", 12, QFont.Bold)
        self.DLabel = QLabel(self)
        self.DLabel.setText('D = ' + str(self.D))
        self.DLabel.setFont(self.paramFont)
        self.DLabel.setGeometry(QRect(675, 110, 220, 50))
        self.DLabel.show()

        self.RoNLabel = QLabel(self)
        self.RoNLabel.setText('R_on = ' + str(self.R_on) + ' \u03A9')
        self.RoNLabel.setFont(self.paramFont)
        self.RoNLabel.setGeometry(QRect(675, 135, 220, 50))
        self.RoNLabel.show()

        self.RoFFLabel = QLabel(self)
        self.RoFFLabel.setText('R_off = ' + str(self.R_off) + ' \u03A9')
        self.RoFFLabel.setFont(self.paramFont)
        self.RoFFLabel.setGeometry(QRect(675, 160, 220, 50))
        self.RoFFLabel.show()

As you can see self.D, self.R_on and self.R_off are class variables. Now I have initialized these class variables with some value, but it can be also user input. After the user inputs the value I need to be able to change the values. As for how the class values will be input by the user is through a form which looks like the form on this question . After clicking 'OK' the new values should be reflected.

在此处输入图片说明

So far whatever I have tried it is overwriting on previous values. How can we implement this?

You have to use the signals to notify changes to the other parts of the application, in this case create a model that every time a property is changed it will be notified through signals, that signals will be connected to a slot, and in that slot it will modify the GUI.

import sys
from PyQt5 import QtCore, QtGui, QtWidgets

class Model(QtCore.QObject):
    D_Changed = QtCore.pyqtSignal(float)
    R_on_Changed = QtCore.pyqtSignal(float)
    R_off_Changed = QtCore.pyqtSignal(float)
    W_0_Changed = QtCore.pyqtSignal(float)

    def __init__(self, parent=None):
        super(Model, self).__init__(parent)
        self._d = 0.0
        self._r_on = 0.0
        self._r_off = 0.0
        self._w_0 = 0.0

    def D(self):
        return self._d

    def setD(self, d):
        if self._d == d: return
        self._d = d
        self.D_Changed.emit(d)

    def R_on(self):
        return self._r_on

    def setR_on(self, r_on):
        if self._r_on == r_on: return
        self._r_on = r_on
        self.R_on_Changed.emit(r_on)

    def R_off(self):
        return self._r_off

    def setR_off(self, r_off):
        if self._r_off == r_off: return
        self._r_off = r_off
        self.R_off_Changed.emit(r_off)

    D = QtCore.pyqtProperty(float, fget=D, fset=setD, notify=D_Changed)
    R_on = QtCore.pyqtProperty(float, fget=R_on, fset=setR_on, notify=R_on_Changed)
    R_off = QtCore.pyqtProperty(float, fget=R_off, fset=setR_off, notify=R_off_Changed)

class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)

        model = Model(self)

        self.d_label = QtWidgets.QLabel()
        self.r_on_label = QtWidgets.QLabel()
        self.r_off_label = QtWidgets.QLabel()

        model.D_Changed.connect(self.on_D_Changed)
        model.R_on_Changed.connect(self.on_R_on_Changed)
        model.R_off_Changed.connect(self.on_R_off_Changed)

        model.setD(10.0)
        model.setR_on(100)
        model.setR_off(16000)

        d_le = QtWidgets.QDoubleSpinBox(
            maximum=sys.float_info.max, 
            value=model.D,
            valueChanged=model.setD
        )
        r_on_le = QtWidgets.QDoubleSpinBox(
            maximum=sys.float_info.max, 
            value=model.R_on,
            valueChanged=model.setR_on
        )
        r_off_le = QtWidgets.QDoubleSpinBox(
            maximum=sys.float_info.max, 
            value=model.R_off,
            valueChanged=model.setR_off
        )
        groub_box_input = QtWidgets.QGroupBox("Edit Values")
        flay = QtWidgets.QFormLayout()
        flay.addRow("D (nm)", d_le)
        flay.addRow("R_on (\u03A9)", r_on_le)
        flay.addRow("R_off (\u03A9)", r_off_le)
        groub_box_input.setLayout(flay)

        groub_box_output = QtWidgets.QGroupBox("Default Parameters:")
        vlay = QtWidgets.QVBoxLayout()
        vlay.addWidget(self.d_label)
        vlay.addWidget(self.r_on_label)
        vlay.addWidget(self.r_off_label)
        groub_box_output.setLayout(vlay)

        lay = QtWidgets.QVBoxLayout(self)
        lay.addWidget(groub_box_input)
        lay.addWidget(groub_box_output)

    @QtCore.pyqtSlot(float)
    def on_D_Changed(self, d):
        self.d_label.setText('D = {}'.format(d))

    @QtCore.pyqtSlot(float)
    def on_R_on_Changed(self, r_on):
        self.r_on_label.setText('R_on = {}\u03A9'.format(r_on))

    @QtCore.pyqtSlot(float)
    def on_R_off_Changed(self, r_off):
        self.r_off_label.setText('R_off = {}\u03A9'.format(r_off))

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    app.setStyle("fusion")
    w = Widget()
    w.show()
    sys.exit(app.exec_())

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM