Initialize PyQt Signal from a python dictionary with unique arguments passed to the slot

22 views Asked by At

I have a nested Python dictionary of QSpinBoxes

self.roi_spin_boxes = dict(
            horizontal=dict(start=None, stop=None),
            vertical=dict(start=None, stop=None),
        )

I want to instantiate the signals from these QSpinBoxes to two different slots. The first slot is for when a spinbox changes. The second is for when the editing for a spinbox is complete.

I instantiate the signals by looping through the dictionaries.

for orientation, spnbxs in self.gui.roi_spin_boxes.items():
    for pos, box in spnbxs.items():
        box.valueChanged.connect(self.roi_spinbox_changed)
        box.editingFinished.connect(
            lambda: self.roi_spinbox_finished_editing(
            str(orientation), str(pos)
        )
    )

The valueChanged signal is fine as is.

However, the issue I'm having occurs when editingFinished is tripped. I want to pass the orientation and position values that were created from iterating through the dictionaries.

The orientation and position values are always the very last values of the loop. I don't know the technical reason behind it, but I know it has to do with the looping variable not being a unique value each iteration, rather it's a singular object that just updates its value each loop. The object itself is what is passed as an argument, rather than the value. So the object will always be whatever the last value was. At least, that's what I think that is happening.

The simple solution is to ditch the loop and just instantiate them separately. So at this point, it's a puzzle.

Is there a way for me to instantiate the signals with the slot, and be able to pass the expected values by using the looping method?

I did try to pass it as a deep copy and that didn't work.

here is a working block of code.

import sys
    
    from PyQt6.QtWidgets import (
        QApplication,
        QHBoxLayout,
        QSpinBox,
        QVBoxLayout,
        QWidget,
    )
    
    
    class GroupBox(QWidget):
    
        def __init__(self):
            QWidget.__init__(self)
    
            self.setWindowTitle("GroupBox")
            layout = QVBoxLayout()
            self.setLayout(layout)
    
            self.roi_spin_boxes = dict(
                horizontal=dict(start=None, stop=None),
                vertical=dict(start=None, stop=None),
            )
    
            layout.addLayout(self.set_row(self.roi_spin_boxes, "horizontal"))
            layout.addLayout(self.set_row(self.roi_spin_boxes, "vertical"))
    
            for orientation, spnbxs in self.roi_spin_boxes.items():
                for pos, box in spnbxs.items():
                    print(f"\tOrientation: {orientation}, Position: {pos}")
    
                    box.valueChanged.connect(self.value_changed)
                    box.editingFinished.connect(
                        lambda: self.finished_editing(orientation, pos)
                    )
    
        def set_row(self, boxes, lbl):
    
            boxes[f"{lbl}"]["start"] = QSpinBox()
            boxes[f"{lbl}"]["stop"] = QSpinBox()
            layout = QHBoxLayout()
            layout.addWidget(boxes[f"{lbl}"]["start"])
            layout.addWidget(boxes[f"{lbl}"]["stop"])
    
            return layout
    
        def value_changed(self):
            print("Value Changed")
    
        def finished_editing(self, orientation, position):
            print(
                f"Finished:\n\tOrientation: {orientation}\n\tPosition: {position}"
            )


app = QApplication(sys.argv)
screen = GroupBox()
screen.show()
sys.exit(app.exec())
0

There are 0 answers