0. 학습 목표

더보기

이번 단계에서는 사용자 정의 Signal을 직접 만들어 사용하는 방법을 학습합니다.

 

이전 단계에서는

QSlider의 valueChanged(int) Signal을 사용하여 슬라이더 값이 Slot 함수로 전달되는 구조를 살펴보았습니다.

 

이번 단계에서는

한 단계 더 나아가, Slot 함수 안에서 값을 처리한 뒤 새로운 Signal을 직접 발생시키는 구조를 구현합니다.

 

즉, Qt가 미리 제공하는 Signal만 사용하는 것이 아니라,

개발자가 필요한 목적에 맞게 Signal을 직접 정의하고 emit()으로 발생시키는 방법을 이해합니다.

학습 목표 내용
사용자 정의 Signal 이해 PySide6에서 개발자가 직접 Signal을 선언하는 방법을 이해합니다.
Signal 선언 위치 이해 Signal은 인스턴스 변수가 아니라 클래스 변수로 선언해야 함을 이해합니다.
emit() 이해 사용자 정의 Signal을 발생시키고 값을 전달하는 emit() 메서드를 학습합니다.
@Slot 데코레이터 이해 Slot 함수의 인자 타입을 명확히 표시하는 @Slot 사용법을 이해합니다.
Signal / Slot 확장 구조 구현 QSlider 값 변경 → 값 처리 → 사용자 정의 Signal 발생 → Label 갱신 흐름을 구현합니다.

이번 단계의 핵심
사용자 정의 Signal은 클래스 변수로 선언하고, emit()으로 값을 전달하며, connect()로 Slot 함수와 연결합니다.

1. Signal / Slot 개념 이해하기

더보기

1.1 사용자 정의 Signal이 필요한 이유

지금까지는 Qt가 미리 제공하는 Signal을 사용했습니다.

예를 들어 QPushButton에는 clicked Signal이 있고, QSlider에는 valueChanged Signal이 있습니다.

 

하지만 실제 프로그램을 만들다 보면 Qt가 제공하는 Signal만으로는 부족할 때가 있습니다.

예를 들어 슬라이더에서 받은 값을 그대로 사용하는 것이 아니라, 값을 가공한 뒤 다른 함수나 위젯에 전달하고 싶을 수 있습니다.

슬라이더 값 변경
        ↓
valueChanged(int) Signal 발생
        ↓
Slot 함수에서 값 처리
        ↓
처리된 값을 사용자 정의 Signal로 emit
        ↓
다른 Slot 함수에서 처리된 값 사용

이처럼 프로그램 내부에서 새로운 이벤트 흐름을 만들고 싶을 때 사용자 정의 Signal을 사용할 수 있습니다.

 

 

1.2 Signal, Slot 가져오기

사용자 정의 Signal과 Slot 데코레이터는 PySide6.QtCore에서 가져옵니다.

from PySide6.QtCore import Signal, Slot
이름 역할
Signal 사용자 정의 Signal을 선언할 때 사용합니다.
Slot Slot 함수의 인자 타입을 명확히 표시할 때 사용합니다.
emit() Signal을 실제로 발생시키고 값을 전달할 때 사용합니다.
connect() Signal과 Slot을 연결할 때 사용합니다.

참고
PySide6에서는 Signal, Slot을 사용합니다. PyQt에서는 보통 pyqtSignal, pyqtSlot이라는 이름을 사용합니다.

 

 

1.3 Signal 선언 문법

사용자 정의 Signal은 다음과 같은 형식으로 선언합니다.

mysignal = Signal(자료형)

예를 들어 정수 하나를 전달하는 Signal은 다음과 같이 선언합니다.

mysignal = Signal(int)

이번 예제에서는 처리된 정수 값을 전달하기 위해 다음 Signal을 사용합니다.

processedValueSignal = Signal(int)
Signal 선언 의미
Signal() 값을 전달하지 않는 Signal입니다.
Signal(int) 정수 값을 하나 전달하는 Signal입니다.
Signal(str) 문자열 값을 하나 전달하는 Signal입니다.
Signal(int, str) 정수와 문자열을 함께 전달하는 Signal입니다.

 

 

1.4 Signal은 클래스 변수로 선언해야 합니다

사용자 정의 Signal에서 가장 중요한 점은 Signal을 클래스 변수로 선언해야 한다는 것입니다.

즉, __init__() 안에서 self.mysignal 형태로 만들면 안 됩니다.

정상 구조

class MyObject(QObject):
    mysignal = Signal(int)

    def __init__(self):
        super().__init__()
잘못된 구조

class MyObject(QObject):
    def __init__(self):
        super().__init__()
        self.mysignal = Signal(int)

Qt는 클래스가 정의되는 시점에 클래스 내부의 Signal을 확인하고 등록합니다.

따라서 Signal은 객체가 만들어진 뒤에 인스턴스 변수처럼 추가하는 것이 아니라, 클래스 자체가 가진 기능으로 선언해야 합니다.

중요한 점
Signal은 객체마다 달라지는 데이터가 아니라, 클래스가 공통으로 가지는 이벤트 기능입니다. 그래서 클래스 변수로 선언합니다.

 

 

1.5 Slot과 @Slot 데코레이터

Slot은 Signal이 발생했을 때 실행되는 함수입니다.

PySide6에서는 일반 함수도 Slot처럼 사용할 수 있습니다.

def slot_function(self, value):
    print(value)

하지만 Slot 함수의 타입을 더 명확하게 표현하고 싶다면 @Slot() 데코레이터를 사용할 수 있습니다.

@Slot(int)
def slot_function(self, value):
    print("받은 값:", value)
구분 설명
@Slot 사용 Slot 함수가 어떤 자료형을 받을지 명확하게 표시합니다.
@Slot 생략 작은 예제나 단순 이벤트 처리에서는 생략해도 동작합니다.
@Slot(int) 정수 값을 받는 Slot 함수임을 나타냅니다.
@Slot(int, str) 정수와 문자열을 받는 Slot 함수임을 나타냅니다.

정리
@Slot은 필수는 아니지만, 사용자 정의 Signal이 많아지거나 프로젝트 규모가 커질수록 코드의 의미를 명확하게 만드는 데 도움이 됩니다.

 

 

1.6 connect()와 emit()

사용자 정의 Signal을 사용할 때는 두 가지 흐름을 구분해야 합니다.

메서드 역할
connect() Signal이 발생했을 때 실행할 Slot 함수를 연결합니다.
emit() Signal을 실제로 발생시키고 값을 전달합니다.
Signal 선언
        ↓
Signal과 Slot 연결 connect()
        ↓
필요한 시점에 Signal 발생 emit()
        ↓
연결된 Slot 함수 자동 실행

2. 예제 코드

더보기

2.1 실습 준비

이번 예제는 PyCharm에서 진행합니다.

새 Python 프로젝트를 만들고, 프로젝트 가상환경에 PySide6가 설치되어 있는 상태에서 진행합니다.

예제 파일명은 main.py로 작성합니다.

 

2. PyCharm 프로젝트 생성

 

2. PyCharm 프로젝트 생성

1. 일반 프로젝트 생성하기더보기 2. 커스텀 가상환경으로 프로젝트 시작하기 더보기 PyCharm에서 Custom environment를 선택하는 이유 기본 Project venv를 그대로 사용하지 않고, Virtualenv, Conda, Poetry, uv 같

basiclike.tistory.com

 

 

2.2 main.py 예제 코드

import sys
from PySide6.QtCore import Qt, Signal, Slot
from PySide6.QtWidgets import QApplication, QWidget, QSlider, QVBoxLayout, QLabel

class SliderExample(QWidget):

    processedValueSignal = Signal(int)

    def __init__(self):
        super().__init__()

        self.setWindowTitle("사용자 정의 Signal 예제")
        self.resize(300, 150)

        self.label_original = QLabel("원본 값: -")
        self.label_processed = QLabel("처리된 값(×2): -")

        self.slider = QSlider(Qt.Horizontal)
        self.slider.setMinimum(1)
        self.slider.setMaximum(100)
        self.slider.setValue(25)

        self.slider.valueChanged.connect(self.respond_to_slider)
        self.processedValueSignal.connect(self.on_processed_value)

        layout = QVBoxLayout(self)
        layout.addWidget(self.slider)
        layout.addWidget(self.label_original)
        layout.addWidget(self.label_processed)

    @Slot(int)
    def respond_to_slider(self, value):
        print("슬라이더 값 변경 :", value)

        self.label_original.setText(f"원본 값: {value}")

        processed_value = value * 2
        self.processedValueSignal.emit(processed_value)

    @Slot(int)
    def on_processed_value(self, value):
        print("커스텀 시그널 :", value)
        self.label_processed.setText(f"처리된 값(×2): {value}")

if __name__ == "__main__":
    app = QApplication(sys.argv)

    window = SliderExample()
    window.show()

    sys.exit(app.exec())

이 코드를 실행하면 슬라이더와 두 개의 Label이 표시됩니다.

 

슬라이더를 움직이면 원본 값이 표시되고, 사용자 정의 Signal을 통해 처리된 값도 함께 표시됩니다.

슬라이더 값 변경 : 26
커스텀 시그널 : 52

슬라이더 값 변경 : 27
커스텀 시그널 : 54

 

 

2.3 예제에서 확인할 핵심 구조

코드 의미
processedValueSignal = Signal(int) 정수 값을 전달하는 사용자 정의 Signal을 선언합니다.
valueChanged.connect() 슬라이더 값 변경 Signal과 Slot 함수를 연결합니다.
processedValueSignal.connect() 사용자 정의 Signal과 처리 결과를 받는 Slot 함수를 연결합니다.
emit(processed_value) 사용자 정의 Signal을 발생시키고 처리된 값을 전달합니다.
@Slot(int) 정수 값을 받는 Slot 함수임을 명확하게 표시합니다.

 

 

2.4 예제 파일

예제 파일은 main.py로 저장합니다.

CustomSignal_01.zip
0.00MB

3. 코드 분석

더보기

3.1 주석 포함 전체 코드

import sys                                      # [1] 파이썬 인터프리터 관련 기능을 제공하는 sys 모듈을 가져옴
from PySide6.QtCore import (                    # [2] PySide6의 핵심 기능 관련 클래스들 중에서
    Qt,                                         #     - Qt: 방향, 정렬, 키 값 등 Qt에서 사용하는 공통 상수 제공
    Signal,                                     #     - Signal: 사용자 정의 Signal을 선언할 때 사용하는 클래스
    Slot                                        #     - Slot: Slot 함수의 인자 타입을 명확히 표시할 때 사용하는 데코레이터
)
from PySide6.QtWidgets import (                 # [3] PySide6의 위젯 관련 클래스들 중에서
    QApplication,                               #     - QApplication: 전체 어플리케이션(프로그램)을 관리하는 클래스
    QWidget,                                    #     - QWidget: 화면에 보이는 기본 창(위젯)의 부모 클래스
    QSlider,                                    #     - QSlider: 값을 조절할 수 있는 슬라이더 위젯 클래스
    QVBoxLayout,                                #     - QVBoxLayout: 위젯들을 세로 방향으로 배치하는 레이아웃 클래스
    QLabel                                      #     - QLabel: 화면에 텍스트를 표시하는 위젯 클래스
)


class SliderExample(QWidget):                   # [4] QWidget을 상속받아 사용자 정의 창 클래스 생성

    processedValueSignal = Signal(int)          # [5] 사용자 정의 Signal 선언
                                                #     - 정수(int) 값을 전달하는 Signal
                                                #     - Signal은 반드시 클래스 변수로 선언해야 함
                                                #     - __init__() 안에서 self.processedValueSignal로 만들면 안 됨

    def __init__(self):                         # [6] SliderExample 객체가 생성될 때 자동 실행되는 초기화 메서드
        super().__init__()                      # [7] 부모 클래스(QWidget)의 초기화 기능 실행

        self.setWindowTitle("사용자 정의 Signal 예제")  # [8] 창 제목 설정
        self.resize(300, 150)                   # [9] 창 크기 설정

        self.label_original = QLabel("원본 값: -")       # [10] 원본 슬라이더 값을 표시할 Label 생성
        self.label_processed = QLabel("처리된 값(×2): -") # [11] 처리된 값을 표시할 Label 생성

        self.slider = QSlider(Qt.Horizontal)    # [12] 가로 방향 슬라이더 생성
        self.slider.setMinimum(1)               # [13] 슬라이더의 최소값을 1로 설정
        self.slider.setMaximum(100)             # [14] 슬라이더의 최대값을 100으로 설정
        self.slider.setValue(25)                # [15] 슬라이더의 초기값을 25로 설정

        self.slider.valueChanged.connect(       # [16] QSlider의 valueChanged(int) Signal과
            self.respond_to_slider              #      respond_to_slider Slot 메서드를 연결
        )                                       #      - 슬라이더 값이 변경되면 현재 값이 value로 전달됨

        self.processedValueSignal.connect(      # [17] 사용자 정의 Signal과
            self.on_processed_value             #      처리된 값을 받는 Slot 메서드를 연결
        )                                       #      - emit()으로 전달한 값이 on_processed_value(value)로 전달됨

        layout = QVBoxLayout(self)              # [18] 현재 창에 세로 방향 레이아웃 생성
        layout.addWidget(self.slider)           # [19] 레이아웃에 슬라이더 추가
        layout.addWidget(self.label_original)   # [20] 레이아웃에 원본 값 Label 추가
        layout.addWidget(self.label_processed)  # [21] 레이아웃에 처리된 값 Label 추가

    @Slot(int)                                  # [22] 정수 값을 받는 Slot 함수임을 명시
    def respond_to_slider(self, value):          # [23] 슬라이더 값이 변경될 때 실행되는 Slot 메서드
                                                #      - valueChanged(int) Signal이 전달한 값이 value로 들어옴
        print("슬라이더 값 변경 :", value)        # [24] 현재 슬라이더 값 출력

        self.label_original.setText(             # [25] 원본 값 Label 텍스트 변경
            f"원본 값: {value}"
        )

        processed_value = value * 2              # [26] 전달받은 값을 2배로 처리

        self.processedValueSignal.emit(          # [27] 사용자 정의 Signal 발생
            processed_value                      #      - 처리된 값을 Signal로 전달
        )

    @Slot(int)                                  # [28] 정수 값을 받는 Slot 함수임을 명시
    def on_processed_value(self, value):         # [29] 사용자 정의 Signal을 받는 Slot 메서드
                                                #      - emit(processed_value)로 전달한 값이 value로 들어옴
        print("커스텀 시그널 :", value)           # [30] 처리된 값 출력

        self.label_processed.setText(            # [31] 처리된 값 Label 텍스트 변경
            f"처리된 값(×2): {value}"
        )


if __name__ == "__main__":                      # [32] 이 파일을 직접 실행할 때만 아래 코드 실행
    app = QApplication(sys.argv)                 # [33] QApplication 객체 생성

    window = SliderExample()                     # [34] 사용자 정의 창 객체 생성
    window.show()                                # [35] 창을 실제로 화면에 표시

    sys.exit(app.exec())                         # [36] 이벤트 루프(Event Loop) 시작
                                                #      - 마우스 클릭, 슬라이더 이동, 창 닫기 등
                                                #        GUI 이벤트를 계속 처리함
                                                #      - 창을 닫으면 프로그램이 종료됨

 

 

3.2 단계별 분석

1단계: 라이브러리 가져오기

import sys
from PySide6.QtCore import Qt, Signal, Slot
from PySide6.QtWidgets import QApplication, QWidget, QSlider, QVBoxLayout, QLabel

사용자 정의 Signal을 만들기 위해 Signal을 가져오고, Slot 함수의 타입을 명확히 표시하기 위해 Slot을 가져옵니다.

이름 역할
Qt Qt.Horizontal 같은 방향 설정에 사용합니다.
Signal 사용자 정의 Signal을 선언할 때 사용합니다.
Slot Slot 함수가 받을 인자 타입을 명확히 표시합니다.
QSlider 값을 조절할 수 있는 슬라이더 위젯을 만듭니다.
QLabel 화면에 텍스트를 표시합니다.
QVBoxLayout 위젯들을 세로 방향으로 배치합니다.

 

2단계: 사용자 정의 Signal 선언

class SliderExample(QWidget):

    processedValueSignal = Signal(int)

processedValueSignal은 개발자가 직접 만든 사용자 정의 Signal입니다.

이 Signal은 정수 값을 하나 전달합니다.

 

여기서 가장 중요한 점은 Signal이 클래스 변수로 선언되어 있다는 것입니다.

중요한 점
Signal은 __init__() 안에서 self.processedValueSignal = Signal(int)처럼 만들지 않습니다. 클래스 본문에서 클래스 변수로 선언해야 합니다.

 

3단계: UI 구성

self.label_original = QLabel("원본 값: -")
self.label_processed = QLabel("처리된 값(×2): -")

self.slider = QSlider(Qt.Horizontal)
self.slider.setMinimum(1)
self.slider.setMaximum(100)
self.slider.setValue(25)

화면에는 슬라이더와 두 개의 Label을 배치합니다.

첫 번째 Label에는 슬라이더의 원본 값을 표시하고, 두 번째 Label에는 2배로 처리된 값을 표시합니다.

위젯 역할
QSlider 사용자가 값을 조절하는 위젯입니다.
label_original 슬라이더에서 전달된 원본 값을 표시합니다.
label_processed 사용자 정의 Signal로 전달된 처리 값을 표시합니다.

 

4단계: 기본 Signal과 Slot 연결

self.slider.valueChanged.connect(self.respond_to_slider)

QSlider의 valueChanged(int) Signal과 respond_to_slider Slot 메서드를 연결합니다.

사용자가 슬라이더를 움직이면 현재 슬라이더 값이 respond_to_slider(value)의 value로 자동 전달됩니다.

 

5단계: 사용자 정의 Signal과 Slot 연결

self.processedValueSignal.connect(self.on_processed_value)

사용자 정의 Signal인 processedValueSignal과 on_processed_value Slot 메서드를 연결합니다.

나중에 processedValueSignal.emit(값)이 실행되면 on_processed_value(value)가 자동으로 실행됩니다.

 

6단계: 슬라이더 값을 받는 Slot 함수

@Slot(int)
def respond_to_slider(self, value):
    print("슬라이더 값 변경 :", value)

    self.label_original.setText(f"원본 값: {value}")

    processed_value = value * 2
    self.processedValueSignal.emit(processed_value)

respond_to_slider()는 QSlider의 valueChanged(int) Signal이 전달한 값을 받는 Slot 함수입니다.

이 함수 안에서는 세 가지 작업을 수행합니다.

순서 동작
1 슬라이더에서 전달된 원본 값을 출력합니다.
2 원본 값을 Label에 표시합니다.
3 원본 값을 2배로 처리한 뒤 사용자 정의 Signal로 emit합니다.

여기서 핵심은 다음 코드입니다.

self.processedValueSignal.emit(processed_value)

이 코드는 사용자 정의 Signal을 발생시키고, 처리된 값을 Slot 함수로 전달합니다.

 

7단계: 사용자 정의 Signal을 받는 Slot 함수

@Slot(int)
def on_processed_value(self, value):
    print("커스텀 시그널 :", value)
    self.label_processed.setText(f"처리된 값(×2): {value}")

on_processed_value()는 사용자 정의 Signal이 전달한 값을 받는 Slot 함수입니다.

emit(processed_value)로 전달된 값이 value 매개변수로 들어옵니다.

이 함수는 전달받은 처리 값을 콘솔에 출력하고, Label에도 표시합니다.

 

8단계: 전체 실행 흐름

사용자가 슬라이더 이동
        ↓
valueChanged(int) Signal 발생
        ↓
respond_to_slider(value) 실행
        ↓
원본 값 Label 갱신
        ↓
processed_value = value × 2
        ↓
processedValueSignal.emit(processed_value)
        ↓
on_processed_value(value) 실행
        ↓
처리된 값 Label 갱신

이 구조를 통해 하나의 기본 Signal에서 시작된 흐름이 사용자 정의 Signal을 통해 다시 확장되는 것을 확인할 수 있습니다.

4. Qt Designer에서 구현할 때의 구조

더보기

4.1 코드 방식과 Designer 방식의 차이

앞의 예제에서는 Python 코드로 슬라이더와 Label을 직접 만들었습니다.

self.slider = QSlider(Qt.Horizontal)
self.label_original = QLabel("원본 값: -")
self.label_processed = QLabel("처리된 값(×2): -")

Qt Designer를 사용하는 경우에는 슬라이더와 Label을 Designer 화면에서 배치한 뒤, Python 코드에서 해당 위젯에 접근합니다.

self.ui.horizontalSlider
self.ui.labelOriginal
self.ui.labelProcessed

하지만 사용자 정의 Signal을 선언하고 emit()으로 발생시키는 구조는 코드 방식과 동일합니다.

 

 

4.2 Qt Designer 기반 작업 흐름

Qt for Python 프로젝트 생성
        ↓
Qt Designer에서 Horizontal Slider와 Label 배치
        ↓
form.ui 파일 저장
        ↓
form.ui 파일을 ui_form.py로 변환
        ↓
Widget 클래스에서 사용자 정의 Signal 선언
        ↓
self.ui.horizontalSlider.valueChanged.connect(self.respond_to_slider)
        ↓
self.processedValueSignal.connect(self.on_processed_value)
        ↓
emit()으로 처리된 값 전달
구분 코드 방식 Qt Designer 방식
슬라이더 생성 QSlider(Qt.Horizontal) Designer에서 Horizontal Slider 배치
슬라이더 접근 self.slider self.ui.horizontalSlider
Label 생성 QLabel() Designer에서 Label 배치
사용자 정의 Signal Signal(int) Signal(int)
값 전달 emit(value) emit(value)

 

 

4.3 GUI Designer 작업

Qt Designer에서 다음 위젯을 배치합니다.

위젯 objectName 예시 역할
Horizontal Slider horizontalSlider 값을 조절합니다.
Label labelOriginal 원본 값을 표시합니다.
Label labelProcessed 처리된 값을 표시합니다.

 

 

4.4 form.ui를 ui_form.py로 변환하기

Qt Designer에서 만든 form.ui 파일은 그대로 Python 코드에서 사용할 수 없습니다.

일반적으로 다음 명령으로 form.ui → ui_form.py 파일로 변환합니다.

pyside6-uic form.ui -o ui_form.py

변환이 끝나면 ui_form.py 파일이 생성됩니다.

이 파일 안에는 Designer에서 배치한 슬라이더와 Label 정보가 Python 코드로 들어 있습니다.

 

 

4.5 ui_form.py 파일 적용하기

Qt Designer 방식에서는 화면 구성을 담당하는 ui_form.py를 가져온 뒤,

Widget 클래스 안에서 기본 Signal과 사용자 정의 Signal을 연결합니다.

import sys
from PySide6.QtCore import Signal, Slot
from PySide6.QtWidgets import QApplication, QWidget

from ui_form import Ui_Widget

class Widget(QWidget):

    # [1] 사용자 정의 Signal 선언
    #  - 처리된 정수 값을 전달하기 위해 사용
    #  - Signal은 반드시 클래스 변수로 선언해야 함
    processedValueSignal = Signal(int)

    def __init__(self, parent=None):
        super().__init__(parent)

        self.ui = Ui_Widget()
        self.ui.setupUi(self)

        # [2] QSlider의 valueChanged(int) Signal과 Slot 연결
        #  - Designer에서 배치한 horizontalSlider를 사용
        #  - 슬라이더 값이 바뀌면 respond_to_slider(value)가 실행됨
        self.ui.horizontalSlider.valueChanged.connect(self.respond_to_slider)

        # [3] 사용자 정의 Signal과 Slot 연결
        #  - emit()으로 처리된 값이 전달되면 on_processed_value(value)가 실행됨
        self.processedValueSignal.connect(self.handle_processed_value)

    # [4] 슬라이더 값 변경 Signal을 받는 Slot
    @Slot(int)
    def respond_to_slider(self, value):
        print("슬라이더 값 변경 :", value)

        self.ui.labelOriginal.setText(f"원본 값: {value}")

        processed_value = value * 2

        # [5] 사용자 정의 Signal 발생
        #  - 처리된 값을 다른 Slot 함수로 전달
        self.processedValueSignal.emit(processed_value)

    # [6] 사용자 정의 Signal을 받는 Slot
    @Slot(int)
    def handle_processed_value(self, value):
        print("커스텀 시그널 :", value)

        self.ui.labelProcessed.setText(f"처리된 값(×2): {value}")

if __name__ == "__main__":
    app = QApplication(sys.argv)

    widget = Widget()
    widget.show()

    sys.exit(app.exec())

 

 

4.6 Designer 방식에서 주의할 점

Qt Designer 방식에서는 화면 위젯이 ui_form.py 안에 만들어집니다.

따라서 슬라이더와 Label은 다음처럼 self.ui를 통해 접근합니다.

self.ui.horizontalSlider
self.ui.labelOriginal
self.ui.labelProcessed

하지만 사용자 정의 Signal은 화면 위젯이 아니라 Widget 클래스의 기능이므로 다음처럼 클래스 변수로 선언합니다.

processedValueSignal = Signal(int)

중요한 점
Designer에서 만든 위젯은 self.ui로 접근하지만, 사용자 정의 Signal은 클래스 내부의 클래스 변수로 선언합니다.

코드 설명
self.ui.horizontalSlider Designer에서 배치한 슬라이더 위젯에 접근합니다.
processedValueSignal 처리된 값을 전달하기 위해 직접 만든 사용자 정의 Signal입니다.
emit(processed_value) 사용자 정의 Signal을 발생시키고 값을 전달합니다.
@Slot(int) 정수 값을 받는 Slot 메서드임을 명확히 표시합니다.

5. 정리

더보기

이번 단계에서는 PySide6에서 사용자 정의 Signal을 선언하고 사용하는 방법을 살펴보았습니다.

핵심 흐름은 다음과 같습니다.

사용자 정의 Signal 선언
    ↓
processedValueSignal = Signal(int)

Signal과 Slot 연결
    ↓
self.processedValueSignal.connect(self.on_processed_value)

필요한 시점에 Signal 발생
    ↓
self.processedValueSignal.emit(processed_value)

연결된 Slot 함수 실행
    ↓
on_processed_value(value)
개념 정리
Signal 이벤트를 알리고 값을 전달하는 신호입니다.
사용자 정의 Signal 개발자가 직접 선언하여 사용하는 Signal입니다.
클래스 변수 선언 Signal은 반드시 클래스 본문에서 클래스 변수로 선언해야 합니다.
connect() Signal과 Slot 함수를 연결합니다.
emit() Signal을 실제로 발생시키고 값을 전달합니다.
@Slot(int) 정수 값을 받는 Slot 함수임을 명확히 표시합니다.

이번 단계에서 기억할 문장
사용자 정의 Signal은 클래스 변수로 선언하고, emit()으로 값을 전달하며, connect()로 연결된 Slot 함수가 그 값을 받아 처리합니다.

 

이 구조를 사용하면 Qt가 제공하는 기본 Signal뿐만 아니라, 프로그램 내부 흐름에 맞는 새로운 이벤트 구조도 직접 만들 수 있습니다.