분석가 황규진 2024. 7. 10. 11:26

시그널과 함수

시그널(Signal)

  • 위젯의 상태가 바뀌었을 때 위젯에서 특정 시그널(이벤트)이 발생
    • 예로 버튼 위젯이 클릭되었을 때 어떤 동작(함수)을 수행 하거나 다이얼 위젯을 돌렸을 때 화면에 다른 값이 출력되게 하는 동작(함수)을 지정
  • 슬롯(Slot) - 함수
    • 위젯에서 특정 신호(시그널)가 발생 했을 때 해당 시그널(이벤트)를 처리할 슬롯(함수, 이벤트 핸들러)를 지정할 수 있음
    • 시그널에 처리를 위해 특정 시그널에 대해 슬롯(함수) 지정할 수 있음
  • 함수
    • 어떤 변화(이벤트, 시그널)가 없더라도 실행될 수 있는 코드
    • 함수는 보통 위젯의 값을 설정하거나 위젯의 값을 가져오거나 위젯의 속성을 변경할 때 사용
    • PyQt에서 대부분의 위젯들이 공통적으로 사용하는 함수들이 몇 가지 있음.
     

 

시그널

import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic

# UI 파일 연결
# 단, UI 파일은 Python 코드 파일과 같은 디렉토리에 있어야 함.
form_class = uic.loadUiType(‘Signal & Function.ui’)[0]

# 화면을 뛰우는데 사용되는 Class 선언
class WindowClass(QMainWindow, form_class):
   def __init__(self):
      super().__init__()
      self.setupUi(self)
      #
      # 이 부분에 시그널을 입력
      #
if __name__ == ‘__main__’:
   app = QApplication(sys.argv)
   myWindow = WindowClass( )
   myWindow.show( )
   app.exec_( )

Button - QPushButton

  • 왼쪽 PushButton의 objectName : Button1, 오른쪽 PushButton의 objectName : Button2
  • 파일명 : pushbuttonTest2.ui

QPushButton의 시그널과 활용

import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic

form_class = uic.loadUiType(“pushbuttonTest2.ui”)[0]

class WindowClass(QMainWindow, form_class):
   def __init__(self):
      super().__init__()
      self.setupUi(self)
      # Button1 위젯에서 클릭 시그널(이벤트) 발생하면
      # button1Function slot(함수) 호출하라고 클릭 시그널과 slot을 연결
      self.Button1.clicked.connect(self.button1Function)
      
   def button1Function(self):
      print(‘button1 Clicked’)

if __name__ == ‘__main__’:
   app = QApplication(sys.argv)
   myWindow = WindowClass( )
   myWindow.show( )
   app.exec_( )

Button - QPushButton

  • QPushButton의 시그널과 활용
    • self.Button1.clicked.connect(함수명1)
    • Self.Button2.clicked.connect(함수명2)

이벤트 루프

  • app.exec_( )
    • 루프를 돌며 ‘닫기‘ 이벤트가 발생하기 전까지 GUI 프로그램을 실행시키는 코드
# 파일 이름 : PushButtonTest.py
import sys 
from PyQt5.QtWidgets import * 
from PyQt5 import uic
#UI파일 연결
#단, UI파일은 Python 코드 파일과 같은 디렉토리에 위치
form_class = uic.loadUiType("./signal_slot/PushButton_Test2.ui")[0]
#화면을 띄우는데 사용되는 Class 선언 
class WindowClass(QMainWindow, form_class) : 
    def __init__(self) :
        super().__init__() 
        self.setupUi(self)
        # Button1 위젯에서 클릭 시그널(이벤트) 발생하면
        # button1Function slot(함수) 호출하라고 클릭 시그널과 slot을 연결
        self.Button1.clicked.connect(self.button1Function)
        self.Button2.clicked.connect(self.button2Function)
        
    def button1Function(self):
        print('button A Clicked!')
        self.Label1.setText('Button A Clicked!')
    def button2Function(self):
        print('button B Clicked!')
        self.Label1.setText('Button B Clicked!')
      
      

if __name__ == "__main__" : 
   #QApplication : 프로그램을 실행시켜주는 클래스
   app = QApplication(sys.argv)

   #WindowClass의 인스턴스 생성
   myWindow = WindowClass()

   #프로그램 화면을 보여주는 코드
   myWindow.show() 

   #프로그램을 이벤트루프로 진입시키는(프로그램을 작동시키는) 코드
   app.exec_()

 

  • Button - QRadioButton
  • 라디오 버튼 - 다음중 하나만 고르시오
  • 체크박스 - 여러개 고르시오
    • QRadioButton의 시그널과 활용
      • self.radio버튼이름.clicked.connect(함수명)
      • 생성자 안에서 버튼에 기능을 연결해주고 기능을 클래스의 메서드로 작성
      • RadioButton은 여러 개 중에서 하나를 선택하여 특정 기능을 수행하도록 하기 때문에 모든 RadioButton에 같은 함수를 연결
      • self.radio버튼이름.clicked.connect(함수명)
      • 생성자 안에서 버튼에 기능을 연결해주고 기능을 클래스의 메서드로 작성
      • RadioButton은 여러 개 중에서 하나를 선택하여 특정 기능을 수행하도록 하기 때문에 모든 RadioButton에 같은 함수를 연결.
      import sys
      from PyQt5.QtWidgets import *
      from PyQt5 import uic
      
      form_class = uic.loadUiType(“radiobuttonTest.ui”)[0]
      
      # 화면을 뛰우는데 사용되는 Class 선언
      class WindowClass(QMainWindow, form_class):
         def __init__(self):
            super().__init__()
            self.setupUi(self)
            self.radioButton_1.clicked.connect(self.groupboxRadFunction)
            self.radioButton_2.clicked.connect(self.groupboxRadFunction)
            self.radioButton_3.clicked.connect(self.groupboxRadFunction)
            self.radioButton_4.clicked.connect(self.groupboxRadFunction)
          
         def groupboxRadFunction(self):
            if self.radioButton_1.isChecked(): print(‘radioButton_1 Checked’)
            elif self.radioButton_2.isChecked(): print(‘radioButton_2 Checked’)
            elif self.radioButton_3.isChecked(): print(‘radioButton_3 Checked’)
            elif self.radioButton_4.isChecked(): print(‘radioButton_4 Checked’)
      
      if __name__ == ‘__main__’:
         app = QApplication(sys.argv)
         myWindow = WindowClass( )
         myWindow.show( )
         app.exec_( )
      
     

이벤트 핸들러

  • GUI 프로그램에서 버튼이 클릭되거나 콤보박스에서 아이템이 선택되거나 하는 것 같이 어떤 일이 발생하는 것을 이벤트(event)라 부름
  • 이러한 이벤트들이 발생하면 특정 코드를 실행하도록 하는데, 이러한 이벤트 처리 코드(함수)를 이벤트 핸들러(event handler)라고 부름 Qt에서는 이벤트를 Singal이라고 부르며 이벤트 핸들러를 Slot이라 부름
  • 이벤트 핸들러 추가하기
    • 버튼이 클릭되었을 때 버튼 클릭 이벤트가 핸들링 되는 코드를 추가하는 예제 코드를 옆에 보이고 있음.
    • 이벤트 핸들링을 정의하는 것은 문법적으로 특정한 이벤트를 이밴트 핸들러 함수와 연결시키면 됨. 즉, 버튼의 경우 QPushButton 버튼 클래스에 있는 clicked라는 이벤트를 특정한 함수와 연결(connect)시키는 것임.
    • “UI 객체.이밴트명.connect(핸들러함수명)” 형태의 코드로 구현할 수 있음.(옆 코드에서는 btnOk 버튼에서 클릭 이벤트가 발생하면 self.btnOkClicked( ) 함수가 실행됨)
    • 주의 : 생성자가 아닌 다른 메서드에서 위젯을 사용하기 위해서는 해당 위젯을 “self.위젝객체”와 같이 self를 붙여서 인스턴스 변수로 만들어야 함. 옆 예제 코드에서 editName은 btnOkClicked( )라는 다른 메서드에서 사용됨으로 self.editName으로 표기하였음. lblName이나 btnOk는 생성자 이외의 메서드에서 사용되지 않음으로 인스턴스 변수로 만들지 않았고 로컬 변수로 사용하였음.
    • btnOkClicked( ) 메서드를 보면 editName 텍스트 박스로부터 텍스트를 읽어와서 이를 메시지 박스로 보내고 있음. 텍스트는 editName.text( ) 메서드를 사용하여 읽어 오고 QMessageBox 클래스의 information( ) 메서드를 사용하여 메시지를 전달하게 된다.
    • QMessageBox.Information( ) 메서드의 첫번째 파라미터는 부모 위젯을 표시으로 보통 self를 쓰면 되고 두 번째 파마메터는 메시지 박스의 타이틀, 세번째 파라미터는 실제 메시지를 넣어 준다.
import sys 
from PyQt5.QtWidgets import * 
class MyDialog(QDialog):
    def __init__(self):
        QDialog.__init__(self)
        lblName = QLabel('Name')
        self.editName = QLineEdit( )
        btnOk = QPushButton('OK')
        layout = QVBoxLayout( )
        layout.addWidget(lblName)
        layout.addWidget(self.editName)
        layout.addWidget(btnOk)
        self.setLayout(layout)
        btnOk.clicked.connect(self.btnOkClicked)
        
    def btnOkClicked(self):
        name = self.editName.text( )
        QMessageBox.information(self, 'Info', name)
if __name__ == "__main__" : 
   app = QApplication(sys.argv)
   myWindow = MyDialog()
   myWindow.show() 
   app.exec_()