Qt프로그램

Signal and Slot

Barbarian developer 2024. 10. 8.

잠깐 알고 갑시다!!

 

Qt는 이벤트를 처리하기 위한 메커니즘으로 시그널(Signal)슬롯(Slot)을 사용한다.

예로 어떤 버튼이 클릭했다는 행위는 Qt에서 시그널(Signal) 이라고 한다. 

그리고 시그널이 발생하면 호출 하는 함수를 슬롯(Slot) 함수라고 한다. 

시그널 이라는 이벤트가 발생하면 시그널과 연결된 슬롯 함수가 호출된다.

 

네트워크 채팅 프로그램을 Qt의 시그널 슬롯을 사용하지 않고 채팅 프로그램을 개발한다고 가정해보자. 여러 개의 쓰레드(Thread) 구조의 프로그램을 개발해야 한다.

 

하지만 Qt에서 시그널과 슬롯을 사용하면 쓰레드를 사용하지않고도 간단하게 채팅 프로그램을 구현할 수 있다.

 

Qt에 제공하는 모든 GUI 위젯은 미리 정해진 다양한 시그널을 가지고 있다.

 

  • 예를 들어 A라는 버튼이 있으면 A라는 버튼의 오브젝트 명이 첫 번째 인자이고 두 번째 인자는 A버튼의 클릭 또는 더블클릭이 시그널이 될 수 있다. 
  • 따라서 클릭 이벤트를 두번째 인자로 명시한다. 
  • 세 번째 인자는 시그널과 호출할 슬롯 함수 있는 오브젝트의 이름을 명시한다. 
  • 네 번째 인자는 발생한 시그널 발생 시 호출할 슬롯 함수를 명시한다.

Signal 과 Slot 예제

이 예제 소스코드는 시그널이 발생하면 윈도우 상에 배치된 라벨의 텍스트를 출력하는 예제이다.

 

<widget>

class SignalSlot : public QObject
 {
     Q_OBJECT

 public:
    void setValue(int val) {
        emit valueChanged(val);
    }

 signals:
     void valueChanged(int newValue);

 private:
     int m_value;
};
  • 위의 예제에서 보는 것과 같이 signals: 키워드 하단에 valueChanged( ) 라는 함수가 있다. 이 함수가 시그널 함수이다.
    Signal 함수는 구현 부는 없으며 소스코드에서 보는 것과 같이 헤더에 정의 부만 구현하면 된다. 
  • valueChanged( ) Signal 함수는 int 인자를 명시하였다. 이 인자는 시그널을 발생할 때 값을 Slot함수에게 인자로 전달할 수 있다. 여기서는 하나의 값을 사용하였다. 
  • 필요에 따라 인자를 사용하지 않거나 여러 개를 인자로 사용할 수 있다. 위의 예제 소스코드의 SignalSlot 이라는 클래스의 public 키워드에 setValue( ) 멤버 함수이다. 
  • 이 멤버 함수가 호출되면 함수 내에 emit 이라는 키워드를 사용한 소스코드를 확인할 수 있다. emit 키워드는 시그널 이벤트를 발생한다.

<widget.h>

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    QLabel *lbl;

public slots:
    void setValue(int val);

};
  • Widget 클래스의 하단에 보면 public 키워드에 slots 키워드를 함께 사용한 것을 확인할 수 있을 것이다. 
  • slots 키워드는 private 또는 public 키워드와 함께 사용할 수 있다.
Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    // QLabel 위젯을 동적 할당으로 생성, 부모는 현재 Widget(this)
    // QLabel의 텍스트는 빈 문자열로 초기화
    lbl = new QLabel("", this);

    // QLabel의 위치와 크기를 지정 (x=10, y=10, 너비=250, 높이=40)
    lbl->setGeometry(10, 10, 250, 40);

    // SignalSlot 클래스의 객체를 생성
    SignalSlot myObject;

     // New Style
    // myObject의 valueChanged 시그널을 Widget의 setValue 슬롯과 연결
    connect(&myObject, &SignalSlot::valueChanged,
            this,      &Widget::setValue);
 
    /*Old Style
    connect(&myObject, SIGNAL(valueChanged(int)),
            this,      SLOT(setValue(int)));
    */

    // myObject 객체의 값을 50으로 설정, 이로 인해 valueChanged 시그널이 발행됨
    myObject.setValue(50);
}

// Widget 클래스의 슬롯, 시그널에 의해 호출됨
void Widget::setValue(int val)
{
    // val 값을 사용해 QLabel의 텍스트를 업데이트
    QString labelText = QString("Signal emmit, Value : %1").arg(val);
    lbl->setText(labelText);  // QLabel에 텍스트 설정
}

// Widget 클래스의 소멸자
Widget::~Widget()
{
    // 동적으로 생성한 lbl은 부모 위젯인 this가 삭제될 때 자동으로 삭제되므로,
    // 명시적으로 delete 할 필요 없음
}
  • Signal 과 Slot을 연결하는 방법에는 두 가지 방법을 제공한다. 
  • 주석으로 New Style 이라고 되어 있는 방식은 Qt 5.5 이상 버전에서 추가된 Signal과 Slot을 연결하는 방식이다. 
  • New Syntax 과Old Style모두 사용할 수 있다. 
  • Qt 5.5 이하버전에서는 Old Style 방식만을 사용할 수 있다. 
  • New Style 스타일은 여러 개의 인자를 사용할 수 없다. 
  • 그리고 New Style 은 Slot함수 뿐만 아니라 일반 멤버 함수도 Slot 함수와 같이 connect( ) 함수에서 4번째 인자로 사용할 수 있다.
  • Signal 은 Slot 함수 외에도 Signal을 호출할 수 있다.

 

'Qt프로그램' 카테고리의 다른 글

다이얼로그  (0) 2024.10.08
Qt Designer 를 이용한 GUI 설계  (3) 2024.10.08
Layout  (0) 2024.10.08
Qt GUI widgets(2)  (1) 2024.10.08
Qt GUI Widgets  (0) 2024.10.07

댓글