[Python] How to use Model-View with a QCheckBox?

Discussão em 'Python' iniciado por Stack, Abril 26, 2025.

  1. Stack

    Stack Membro Participativo

    How to use the model-view approach with a checkbox? The view is expected to display the model status but when the user clicks on the view, the checkbox status is actually changed before it is told by the model. For example the sequence should be:

    • Current model state is checked and CB state is checked
    • User clicks the CB to switch its state to unchecked
    • The view asks the model to change its state to unchecked
    • The model updates its state to unchecked
    • The view sees the model change and sets the CB state to unchecked

    However this doesn't happen because between steps 2 and 3 the CB state switches to unchecked and the view actually asks the model to switch to the other state, checked.

    from qtpy.QtCore import QObject, Signal
    from qtpy.QtWidgets import QApplication, QMainWindow, QWidget, QCheckBox, QHBoxLayout

    class MainWindow(QMainWindow):
    def __init__(self):
    super().__init__()
    self.model = Model()
    self.view = View(self.model)
    self.setCentralWidget(self.view)

    class View(QWidget):
    user_request = Signal(bool)

    def __init__(self, model):
    super().__init__()
    self.model = model
    self.cb = QCheckBox('Click Me')
    layout = QHBoxLayout(self)
    layout.addWidget(self.cb)
    self.cb.clicked.connect(self.cb_clicked)
    self.cb.stateChanged.connect(self.cb_changed)
    self.model.updated.connect(self.update_from_model)
    self.user_request.connect(self.model.request_update)

    def cb_clicked(self):
    current_state = self.cb.isChecked()
    desired = not current_state
    print('User wants the state to be', desired)
    self.user_request.emit(desired)

    def cb_changed(self, state):
    states = ['unchecked', 'tristate', 'checked']
    print('CB has been updated to', states[state], '\n')

    def update_from_model(self):
    state = self.model.data()
    print('View aligns CB on model state', state)
    self.cb.setChecked(state)

    class Model(QObject):
    updated = Signal(bool)

    def __init__(self):
    super().__init__()
    self.state = True
    self.updated.emit(self.state)

    def data(self):
    return self.state

    def request_update(self, checked):
    self._data = checked
    print('Model sets its state to', checked)
    self.updated.emit(checked)

    def main():
    app = QApplication([])
    window = MainWindow()
    window.show()
    app.exec()

    if __name__ == '__main__':
    main()

    Continue reading...

Compartilhe esta Página