Checkbox keeps initial state even after it has been changed
-
This widget I created is just a vBox of 16 checkboxes. The problem I am stuck on is the checkbox always returns the initial state it was assigned. I have attached the full code of the widget and a screenshot before/after checking it.
Windows: 10
Python: 3.10.5
PySide6: 6.3.0from typing import Dict from PySide6.QtCore import Qt, Signal from PySide6.QtWidgets import ( QWidget, QCheckBox, QVBoxLayout, ) class SwarmTable(QWidget): def __init__(self, parent=None): super().__init__(parent) self.parent = parent self.layout = QVBoxLayout() self.layout.setContentsMargins(10, 10, 10, 10) self.layout.setSpacing(1) self.add_rows() self.setLayout(self.layout) self.layout.addStretch(1) def add_rows(self): for port in range(1, 17): cb = QCheckBox(self) cb.setText(f"Port {port}") cb.setCheckState(Qt.Unchecked) cb.setEnabled(port < 15) self.layout.addWidget(cb, 0, Qt.AlignLeft | Qt.AlignVCenter) def get_active_ports(self) -> Dict[int, bool]: for c in self.children(): if isinstance(c, QCheckBox): print(f"{c.text()} is {c.checkState()}")
Initializes as expectedSwarmTable.get_active_ports()
returns:Port 1 is PySide6.QtCore.Qt.CheckState.Unchecked Port 2 is PySide6.QtCore.Qt.CheckState.Unchecked Port 3 is PySide6.QtCore.Qt.CheckState.Unchecked Port 4 is PySide6.QtCore.Qt.CheckState.Unchecked Port 5 is PySide6.QtCore.Qt.CheckState.Unchecked Port 6 is PySide6.QtCore.Qt.CheckState.Unchecked Port 7 is PySide6.QtCore.Qt.CheckState.Unchecked Port 8 is PySide6.QtCore.Qt.CheckState.Unchecked Port 9 is PySide6.QtCore.Qt.CheckState.Unchecked Port 10 is PySide6.QtCore.Qt.CheckState.Unchecked Port 11 is PySide6.QtCore.Qt.CheckState.Unchecked Port 12 is PySide6.QtCore.Qt.CheckState.Unchecked Port 13 is PySide6.QtCore.Qt.CheckState.Unchecked Port 14 is PySide6.QtCore.Qt.CheckState.Unchecked Port 15 is PySide6.QtCore.Qt.CheckState.Unchecked Port 16 is PySide6.QtCore.Qt.CheckState.Unchecked
However when I click a port, it shows visually correct butSwarmTable.get_active_ports()
still returns the same incorrect information.Port 1 is PySide6.QtCore.Qt.CheckState.Unchecked Port 2 is PySide6.QtCore.Qt.CheckState.Unchecked Port 3 is PySide6.QtCore.Qt.CheckState.Unchecked Port 4 is PySide6.QtCore.Qt.CheckState.Unchecked Port 5 is PySide6.QtCore.Qt.CheckState.Unchecked Port 6 is PySide6.QtCore.Qt.CheckState.Unchecked Port 7 is PySide6.QtCore.Qt.CheckState.Unchecked Port 8 is PySide6.QtCore.Qt.CheckState.Unchecked Port 9 is PySide6.QtCore.Qt.CheckState.Unchecked Port 10 is PySide6.QtCore.Qt.CheckState.Unchecked Port 11 is PySide6.QtCore.Qt.CheckState.Unchecked Port 12 is PySide6.QtCore.Qt.CheckState.Unchecked Port 13 is PySide6.QtCore.Qt.CheckState.Unchecked Port 14 is PySide6.QtCore.Qt.CheckState.Unchecked Port 15 is PySide6.QtCore.Qt.CheckState.Unchecked Port 16 is PySide6.QtCore.Qt.CheckState.Unchecked
Any ideas or suggestions would be appreciated. Been stuck on this for a few hours. Thanks!
-
Hi,
Where and how are you calling get_active_ports ?
-
@SGaist
I have an object that holds all my external process communication. When I click the purple "play" button in the toolbar, it calls the slotProcManager.start_process
seen in the following.class ProcManager(QObject): status_fwd = Signal(str) result_fwd = Signal(dict) uut_pt_fwd = Signal(dict) ref_pt_fwd = Signal(np.float64) active_uut_fwd = Signal(dict) active_step_fwd = Signal(dict) all_steps_fwd = Signal(dict) def __init__(self, parent): super().__init__(parent) self.parent = parent self.passive_cal = QProcess() self.passive_cal.setProcessChannelMode(QProcess.MergedChannels) self.passive_cal.setProgram("cal_passive_ion") self._timer = QTimer() self._timer.setInterval(100) self._timer.timeout.connect(self.read_stdout) def __init__(self, parent): super().__init__(parent) self.parent = parent self.pool = QThreadPool.globalInstance() self.passive_cal = QProcess() self.passive_cal.setProcessChannelMode(QProcess.MergedChannels) self.passive_cal.setProgram("cal_passive_ion") self._timer = QTimer() self._timer.setInterval(100) self._timer.timeout.connect(self.read_stdout) @Slot() def start_process(self): # get_active_ports() returns Dict[int, bool] # where int is the port number and bool is whether it is active # Don't need to go past here to observer issue. _a = json.dumps(self.parent.main_activity.tabs.ports_view.get_active_ports()) self.passive_cal.setArguments([f"--active-ports={_a}"]) self.passive_cal.start() self._timer.start() @Slot() def stop_process(self): self.passive_cal.terminate()
and for reference heres my
Mainwindow
andMainActivity
class MainActivity(QWidget): def __init__(self, parent=None): super().__init__() self.parent = parent layout = QHBoxLayout() layout.addWidget(self.tabs, 2) layout.addWidget(self.chart, 8) self.setLayout(layout) @cached_property def tabs(self): return DetailsTabs(self) @cached_property def chart(self): return PressurePlot(self) class MainWindow(QMainWindow): def __init__(self): super().__init__() self.session = Session(self) self.settings = Settings(self) self.proc_man = ProcManager(self) self.toolbar.start_calibration.connect(self.proc_man.start_process) self.toolbar.stop_calibration.connect(self.proc_man.stop_process) self.addToolBar(self.toolbar) self.setCentralWidget(self.main_activity) @cached_property def toolbar(self): return Toolbar(self) @cached_property def main_activity(self): return MainActivity(self) if __name__ == "__main__": app = QApplication(sys.argv) app.setStyle("Fusion") window = MainWindow() window.resize(QSize(1400, 947)) window.show() sys.exit(app.exec())
-
One issue I can see is that your widget explicitly grabs data from an unrelated widget through the parent which is a bad sign.
It should rather be the other way around, the widget should be configured externally or through signals and slots.
-
One issue I can see is that your widget explicitly grabs data from an unrelated widget through the parent which is a bad sign.
It should rather be the other way around, the widget should be configured externally or through signals and slots.
@SGaist I am not sure what you mean by "your widget explicitly grabs data from an unrelated widget through the parent" but I removed any use of
self.parent...
madeget_active_ports
into a slot that emits a signal. I then observed the same issue.So just out of curiosity I wanted to remove the
cached_property
decorator to see if that was part of the issue, and I noticed the table widget was aproperty
, not acached_property
. So now my main widget looks like this:class MainActivity(QWidget): def __init__(self, parent=None): super().__init__() self.parent = parent layout = QHBoxLayout() layout.addWidget(self.tabs, 2) layout.addWidget(self.chart, 8) self.setLayout(layout) @cached_property # <-- was @property def tabs(self): return DetailsTabs(self) @cached_property def chart(self): return PressurePlot(self)
That was a typo on my part. Everything works fine now. Better, actually, because I think the change to signal/slot is more consistent.
Thanks for you help help @SGaist , wouldn't have seen my if I didn't go to change that method call to a signal/slot. :)