ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Day 2. PyQt5 (Signal and Slot)
    <개인공부> - IT/[Python] 2021. 2. 9. 03:31
    반응형

    책에서는 Signal과 Slot에 대해 간략하게 설명하고 있다.

     

    원문을 그대로 옮기면 아래와 같다.

     

    Signals are notifications emitted by widgets when something happens.

    Slots is the name Qt uses for the receivers of signals.

     

    즉, signal이라고 하면 키보드를 누르거나 마우스를 클릭하거나 input box에 어떤 내용이 입력되거나 하는 등의 액션을 생각하면 쉽다. 그리고 slot은 앞서 설명된 signal을 수신하여 처리하는 method로 생각하면 쉽다. 

    import sys
    
    from PyQt5.QtCore import Qt
    from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton
    
    class MainWindow(QMainWindow):
        def __init__(self):
            super().__init__()
            
            self.setWindowTitle("My App")
            self.button = QPushButton("Press Me!")
            
            self.button.clicked.connect(self.the_button_was_clicked)
    
            self.setCentralWidget(self.button)
    
        def the_button_was_clicked(self):
            self.button.setText("You already clicked me")
            self.button.setEnabled(False)
    
            self.setWindowTitle("My Oneshot App")
    
    app = QApplication(sys.argv)
    
    window = MainWindow()
    window.show()
    
    app.exec_()

    예제 코드를 봐보자.

     

    Mainwindow에 PushButton 위젯이 위치하고 있으며 버튼이 눌려졌을 때 처리하는 method가 정의되어 있다. 버튼이 click되는 signal이 발생하면 the_button_was_clicked라는 method가 호출되고 그에 따른 동작을 수행하는 간단한 프로그램이다. 

     

    그렇다면 QMainWindow는 어떠할까? Mainwindow에서 갖고 있는 시그널에 대한 간단한 예제를 보도록 하자.

    import sys
    from random import choice
    
    from PyQt5.QtCore import Qt
    from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton
    
    window_titles = [
    'My App',
    'My App',
    'Still My App',
    'Still My App',
    'What on earth',
    'What on earth',
    'This is surprising',
    'This is surprising',
    'Something went wrong'
    ]
    
    class MainWindow(QMainWindow):
        def __init__(self):
            super().__init__()
            self.n_times_clicked = 0
            self.setWindowTitle("My App")
            self.button = QPushButton("Press Me!")
            
            self.button.clicked.connect(self.the_button_was_clicked)
            self.windowTitleChanged.connect(self.the_window_title_changed)
            self.setCentralWidget(self.button)
    
        def the_button_was_clicked(self):
            print("Clicked.")
            new_window_title = choice(window_titles)
            print(f"Setting title: {new_window_title}")
            self.setWindowTitle(new_window_title)
        
        def the_window_title_changed(self, window_title):
            print(f"Window title change: {window_title}")
    
            if window_title == 'Something went wrong':
                self.button.setDisabled(True)
    
    app = QApplication(sys.argv)
    
    window = MainWindow()
    window.show()
    
    app.exec_()

    ※ 책과는 다르게 나는 f-string을 사용했다. 책에서는 % operator을 사용. print("Setting title: %s" % new_window_title)

     

    해당 코드에서는 Mainwindow의 창 타이틀이 변경될 경우 처리하는 method가 정의되어 있다. 즉, 랜덤으로 타이틀이 선택되게 되는데 기존의 창 타이틀이 랜덤으로 선택된 경우와 다를 경우에만 the_window_title_changed method가 호출되는 것이다. 그리고 Something went wrong이 선택된 경우 버튼이 disable된다.

     

    결론적으로 이 챕터에서 알아야 할 중요한 내용은 signal이 언제 발생하는지 알아야 한다는 점이다.  다시 말해서 랜덤하게 선택된 제목이 Mainwindow의 기존 타이틀과 다른 경우에만 해당 signal이 발생된다는 점.

     

    그렇다면 특정 widget에서 발생시키는 signal을 다른 widget가 바로 연결시킨다면 어떨까? 이번 예제에서는 QLineEdit에서 textChange라는 signal을 와 QLabel의 method와 바로 연결해본다.

    import sys
    
    from PyQt5.QtCore import Qt
    from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QLineEdit, QVBoxLayout, QWidget
    
    class MainWindow(QMainWindow):
        def __init__(self):
            super().__init__()
            self.setWindowTitle("My App")
    
            self.label = QLabel()
            self.input = QLineEdit()
            self.input.textChanged.connect(self.label.setText)
    
            layout = QVBoxLayout()
            layout.addWidget(self.input)
            layout.addWidget(self.label)
    
            container = QWidget()
            container.setLayout(layout)
            
            self.setCentralWidget(container)
    
    app = QApplication(sys.argv)
    
    window = MainWindow()
    window.show()
    
    app.exec_()

    아래 화면에서 위에 보이는 box에 특정값을 입력하게 되면 아래의 Label 섹션에 동일한 내용이 입력되는 것을 확인할 수 있다. 

    즉, 대부분의 Qt Widget들은 다양한 slots을 갖고 있으며 widgets이 발생시키는 signal들과 연결 시킬 수 있다.

     

    Referce book: Create GUI Applications with Python & Qt5: The hands-on guide to making apps with Python

    반응형
Designed by Tistory.