본문 바로가기

난 이 분야 전문가야!/Qt

Qt :: Signal과 Slot 정리

728x90

1. Signal과 Slot이란?

  • Signal (신호):
    • 객체가 어떤 이벤트가 발생했음을 알리기 위해 발송하는 메시지입니다.
    • 주로 클래스 내부에서 정의되며, 특정 조건이 만족될 때 emit키워드를 사용해 발송됩니다.
    • Signal은 함수처럼 호출되지만, 직접 실행되지 않고 연결된 Slot을 호출합니다.
    • 예시:
signals:
    void clicked();  // 버튼이 클릭되었을 때 신호
    void valueChanged(int newValue);  // 값이 변경되었을 때 신호

 

  • Slot (슬롯):
    • Signal과 연결되며, Signal이 발송되었을 때 실행되는 함수입니다.
    • 일반 멤버 함수처럼 정의되지만, 특별히 slots: 접근 한정자를 사용하여 정의됩니다.
    • 예시:
public slots:
    void onClicked();  // 클릭 이벤트 처리
    void setValue(int newValue);  // 값 변경 이벤트 처리

 

2. Signal-Slot 메커니즘의 작동 원리

  • Signal 정의: 클래스에서 signals 접근 한정자를 사용하여 정의합니다.
  • Slot 정의: 슬롯 함수는 public slots, private slots, 또는 protected slots 접근 한정자 아래 정의됩니다.
  • Signal-Slot 연결: QObject::connect() 함수를 사용하여 SignalSlot을 연결합니다.
    • 연결 시, Signal을 발송하는 객체와 이를 처리할 Slot이 포함된 객체를 지정해야 합니다.
    • 예시: 위 코드는 버튼이 클릭되면 애플리케이션이 종료되도록 연결합니다.
QPushButton *button = new QPushButton("Click Me");
QObject::connect(button, &QPushButton::clicked, &app, &QApplication::quit);

 

  • Signal 발송: 특정 조건이 만족되면 Signal을 emit 키워드를 사용해 발송합니다.
    • 예시:
emit clicked();

 

  • Slot 호출: 연결된 Slot 함수가 호출되어 작업을 수행합니다.

 

3. Signal-Slot의 특징

  1. 유연성: Signal과 Slot은 함수의 매개변수만 맞다면 어떤 객체에서도 서로 연결할 수 있습니다.
  2. 타입 안정성: Signal-Slot은 컴파일 시간에 타입 체크를 수행하여 안전성을 보장합니다.
  3. 비동기 처리: Signal은 발송된 후, Slot은 이벤트 루프를 통해 호출되므로 기본적으로 비동기적으로 동작합니다.
  4. 다중 연결: 하나의 Signal은 여러 Slot에 연결할 수 있으며, 하나의 Slot은 여러 Signal에 연결될 수 있습니다.

 

728x90



4. Signal - Slot 사용조건

  • QObject 상속
    • SignalSlot 메커니즘을 사용하려면 클래스가 반드시 QObject를 상속받아야 합니다.
    • 이는 SignalSlotQt의 메타 객체 시스템 (MOC)에 의해 동작하기 때문입니다.
    • QObject를 상속하지 않은 클래스에서는 SignalSlot을 사용할 수 없습니다.
  • Q_OBJECT 매크로
    • 클래스 내부에서 Signal을 정의하거나, Slot을 사용하려면 Q_OBJECT 매크로가 필요합니다.
    • 이 매크로는 Qt의 MOC에 의해 메타 객체 정보를 생성하도록 지시합니다.
    • 예를 들어, Signal 및 Slot을 사용하는 아래 코드에서 Q_OBJECT가 없다면 컴파일이 실패합니다.
class MyClass : public QObject 
{
    Q_OBJECT  // 이 매크로가 없으면 Signal과 Slot이 동작하지 않음

public:
    MyClass(QObject *parent = nullptr) : QObject(parent) {}

signals:
    void mySignal();

public slots:
    void mySlot();
};

 

 

 

5. Signal-Slot의 연결 방식

  • Qt 5 이상 스타일 (람다 함수 지원)
connect(sender, &Sender::signal, receiver, &Receiver::slot);

// 람다 함수 연결
connect(button, &QPushButton::clicked, []() {
    qDebug() << "Button clicked!";
});

 

  • Qt 4 이하 스타일
connect(sender, SIGNAL(signalName()), receiver, SLOT(slotName()));

 

 

두 스타일의 장단점

 

특성 Qt 5 이상 스타일 Qt 4 스타일
타입 안정성 컴파일 타임에 타입 체크 가능 런타임에만 확인 가능
디버깅 용이성 IDE를 통한 함수 추적 가능 문자열 기반으로 추적 어려움
호환성 Qt 4 코드와 혼합 사용 제한적 모든 Qt 버전에서 동작 가능
람다 지원 지원 미지원
오버로딩된 함수 처리 명시적 static_cast 필요
(5.7 이상부턴 QOverload )
필요없음

 

5. 추가 사항

  • Disconnected 연결 해제
    • 연결된 Signal-Slot을 해제하려면 QObject::disconnect()를 사용합니다.
QObject::disconnect(sender, &Sender::signal, receiver, &Receiver::slot);

 

  • Signal 간 연결
    • Signal끼리 연결하여 이벤트 체인을 만들 수 있습니다.
connect(sender, &Sender::signal, receiver, &Receiver::anotherSignal);

 

728x90