PyQt 예제 1.8.3

미자막 방법을 소개하겠다. 이것은 메소드 자체에서 시그널을 구분하는 방법이다.
-__version__ = "1.8.2"
+__version__ = "1.8.3"
 
 class Form(QDialog):
     def __init__(self, parent=None):
@@ -92,11 +92,11 @@ class Form(QDialog):
                         signal_spinCountLabel3.setText)
 
         self.connect(connect_button1, SIGNAL("clicked()"),
-                lambda name="Button1": self.Connect_ButtonClick(name))
+                        self.Connect_ButtonClick)
         self.connect(connect_button2, SIGNAL("clicked()"),
-                lambda name="Button2": self.Connect_ButtonClick(name))
+                        self.Connect_ButtonClick)
         self.connect(connect_button3, SIGNAL("clicked()"),
-                lambda name="Button3": self.Connect_ButtonClick(name))
+                        self.Connect_ButtonClick)
 
         self.setWindowTitle("Main Dialog")
 
@@ -117,8 +117,11 @@ class Form(QDialog):
         self.simple_lineEidt.setText("This is LineEdit Widget")
         self.simple_label.setText("Hello, PyQt!")
 
-    def Connect_ButtonClick(self, buttonName):
-        self.connect_label.setText(buttonName)
+    def Connect_ButtonClick(self):
+        button = self.sender()
+        if not (button and isinstance(button, QPushButton)):
+            return
+        self.connect_label.setText(button.text())
     
 class MySignalSpinBox(QSpinBox):
     changedCount = 0
connect를 먼저 보면, 모두 같은 메소드를 그냥 연결해주고 있다. connect 자체에서 버튼을 구분하고 있지 않다.

다음으로 메소드를 보면 self.sender() 를 호출하고 있는데, 이것은 시그널을 보낸 객체의 포인터를 리턴하게 된다. 다만, 시그널 없이 일반적으로 사용된 경우에는 None 객체를 리턴하게 된다.

메소드 쪽을 보면, 인자 없이 메소드가 사용되고 있는데, if 문에서 button 의 속성을 다루어주고 있다.

button 이 None 객체인지, 그리고 button 객체가 QPushButton의 인스턴스 인지 확인하는 것이다. 이들이 아니라면 메소드가 실행되지 말아야 하기 때문이다.

이제 sender 를 통해서 시그널을 보낸 버튼을 얻었기 때문에, 어떤 버튼인지는 구분이 가능하므로 이를 이용해서 레이블에 텍스트를 넣어주면 된다.

이렇게 3가지의 방식이 있는데, 이 외에도 QSignalMapper라는 것을 이용해서 구분하는 방법도 있다.



이렇게 해서 시그널과 슬롯에 대해서 많이 알아 보았다. 마지막으로 시그널과 슬롯을 사용하면서 주의해야 할 것으로, 시그널과 슬롯이 무한 루프에 빠지지 않는 가를 주의 해야 한다.

예를 들어, 어떤 두 객체가 서로를 connect 하고 있는데, 시그널로부터 오는 값을 설정 한다고 하자.

이때, 1번 객체의 값이 변경되어 2번 객체의 값을 설정하게 되고, 이 변경은 또 다시 1번 객체에 시그널을 보내게 되어 1번 객체의 값을 설정하도록 하게 된다. 또, 이것이 2번 객체에 시그널을 보내게 하는 무한 루프가 발생할 수 있다.

이를 방지하기 위해서는 값이 같을 때는 시그널을 보내지 않도록 하는 것이 있을 수 있다.

PyQt의 대부분 시그널-슬롯에서는 이러한 문제를 방지하도록 미리 구현되어 있다. 위에서 말했 듯이 값이 변경되지 않을 때는 시그널을 보내지 않도록 하거나, 다른 하나는 사용자에 의해서만 시그널이 발생하도록 되어 있다.

전자의 예로는 QSpinBox 와 같은 것이 있고, 후자의 예로는 QLineEdit 이 있다.

만일, 직접 시그널-슬롯을 작성하게 된다면 이러한 점을 조심해야 할 것이다. 그리고 시그널-슬롯을 사용할 때, 이러한 관계가 논리적인지 확인해야 할 것이다.

마지막으로, 시그널-슬롯을 사용하면서 시그널을 잠시 중단하고 싶다면 QObject.blockSignals() 메소드를 이용해서 시그널 생성을 중단 시키거나 다시 재개 시킬 수 있다.

댓글 없음:

댓글 쓰기