복붙노트

[PYTHON] 람다 식을 사용하여 pyqt의 슬롯 연결

PYTHON

람다 식을 사용하여 pyqt의 슬롯 연결

람다 함수로 슬롯을 연결하려고하는데 예상대로 작동하지 않습니다. 아래의 코드에서 처음 두 버튼을 올바르게 연결하는 데 성공했습니다. 루프로 연결되는 두 번째 두 경우에는 잘못되었습니다. 나보다 먼저 누군가가 같은 질문 (Qt - 람다를 사용한 인수를 가진 연결 슬롯)을 가지고 있지만,이 솔루션은 나를 위해 작동하지 않습니다. 30 분 동안 내 화면을 쳐다보고 있었지만 코드가 어떻게 다른지 알 수는 없습니다.

class MainWindow(QtGui.QWidget):
    def __init__(self):
        super(QtGui.QWidget, self).__init__()

        main_layout = QtGui.QVBoxLayout(self)

        # Works:
        self.button_1 = QtGui.QPushButton('Button 1 manual', self)
        self.button_2 = QtGui.QPushButton('Button 2 manual', self)
        main_layout.addWidget(self.button_1)
        main_layout.addWidget(self.button_2)

        self.button_1.clicked.connect(lambda x:self.button_pushed(1))
        self.button_2.clicked.connect(lambda x:self.button_pushed(2))

        # Doesn't work:
        self.buttons = []
        for idx in [3, 4]:
            button = QtGui.QPushButton('Button {} auto'.format(idx), self)
            button.clicked.connect(lambda x=idx: self.button_pushed(x))
            self.buttons.append(button)
            main_layout.addWidget(button)


    def button_pushed(self, num):
        print 'Pushed button {}'.format(num)

첫 번째 두 버튼을 누르면 '푸시 버튼 1'과 '푸시 버튼 2'가 나오고 나머지 두 버튼은 모두 '푸시 버튼 거짓'이됩니다.

나는 또한 람다 메커니즘을 완전히 이해하지 못했다. 정확히 무엇이 연결 되나요? 람다에 의해 생성 된 함수에 대한 포인터 (매개 변수가 치환 됨)이거나 신호가 발생할 때마다 평가되는 람다 함수입니까?

해결법

  1. ==============================

    1.QPushButton.clicked 신호는 단추의 상태를 나타내는 인수를 내 보냅니다. 람다 슬롯에 연결하면 idx에 할당하는 선택적 인수가 버튼의 상태로 덮어 쓰여집니다.

    QPushButton.clicked 신호는 단추의 상태를 나타내는 인수를 내 보냅니다. 람다 슬롯에 연결하면 idx에 할당하는 선택적 인수가 버튼의 상태로 덮어 쓰여집니다.

    대신에 다음과 같이 연결하십시오.

    button.clicked.connect(lambda state, x=idx: self.button_pushed(x))
    

    이렇게하면 단추 상태가 무시되고 올바른 값이 메서드에 전달됩니다.

  2. ==============================

    2.조심해! 자기 자신에 대한 참조로 람다 슬롯에 신호를 연결하자 마자 위젯은 가비지 수집되지 않을 것입니다! lambda가 위젯에 대한 또 다른 수집 할 수없는 참조로 클로저를 생성하기 때문입니다.

    조심해! 자기 자신에 대한 참조로 람다 슬롯에 신호를 연결하자 마자 위젯은 가비지 수집되지 않을 것입니다! lambda가 위젯에 대한 또 다른 수집 할 수없는 참조로 클로저를 생성하기 때문입니다.

    따라서, self.someUIwidget.someSignal.connect (람다 피 : self.someMethod (p))는 매우 악합니다 :)

  3. ==============================

    3.나는 정직하게 람다의 당신의 사용과 함께 잘못되고있는 것이 여기에서도 확실하지 않다. idx (자동 단추를 설정할 때 루프 인덱스)가 범위를 벗어나 더 이상 적절한 값을 포함하지 않기 때문이라고 생각합니다.

    나는 정직하게 람다의 당신의 사용과 함께 잘못되고있는 것이 여기에서도 확실하지 않다. idx (자동 단추를 설정할 때 루프 인덱스)가 범위를 벗어나 더 이상 적절한 값을 포함하지 않기 때문이라고 생각합니다.

    하지만 당신이 그렇게 할 필요는 없다고 생각합니다. 람다를 사용하는 유일한 이유는 button_pushed ()에 인수를 전달하여 어떤 버튼인지 식별 ​​할 수 있기 때문입니다. 버튼이 신호를 보낸 버튼을 식별하는 button_pushed () 슬롯에서 호출 할 수있는 sender () 함수가 있습니다.

    제가 생각하기에 당신이 뭘 쏘고 있는지를 보여주는 예가 있습니다 :

    from PyQt5.QtGui import *
    from PyQt5.QtCore import *
    from PyQt5.QtWidgets import *
    
    import sys
    
    class MainWindow(QWidget):
        def __init__(self):
            super(QWidget, self).__init__()
    
            main_layout = QVBoxLayout(self)
    
            self.buttons = []
    
            # Works:
            self.button_1 = QPushButton('Button 1 manual', self)
            main_layout.addWidget(self.button_1)
            self.buttons.append(self.button_1)
            self.button_1.clicked.connect(self.button_pushed)
    
            self.button_2 = QPushButton('Button 2 manual', self)
            main_layout.addWidget(self.button_2)
            self.buttons.append(self.button_2)
            self.button_2.clicked.connect(self.button_pushed)
    
            # Doesn't work:
            for idx in [3, 4]:
                button = QPushButton('Button {} auto'.format(idx), self)
                button.clicked.connect(self.button_pushed)
                self.buttons.append(button)
                main_layout.addWidget(button)
    
    
        def button_pushed(self):
            print('Pushed button {}'.format(self.buttons.index(self.sender())+1))
    
    
    app = QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())
    
  4. from https://stackoverflow.com/questions/35819538/using-lambda-expression-to-connect-slots-in-pyqt by cc-by-sa and MIT license