예제

시그널이 발생하면 윈도우 상에 배치된 라벨의 텍스트를 출력하는 예제를 만들어 보자.

 


widget.h의 SignalSlot 클래스

...

class SignalSlot: public QObject{
    Q_OBJECT

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

signals:
    void valueChanged(int newValue);

private:
    int value;
};
...

 

 

Signal 함수

signals:
    void valueChanged(int newValue);
  • 시그널 함수는 구현부가 없으며, 헤더에 정의부만 구현한다.
  • 위의 예제에서는 시그널 함수에 int 인자를 명시했지만, 이 인자는 시그널 발생 시 값을 슬롯 함수에게 인자로 전달하는 역할(필요에 따라 인자를 사용하지 않거나 여러개 사용할 수도 있다.)

 

멤버 함수

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

 

  • 이 멤버 함수가 호출되면, 함수 내 emit이 시그널을 발생시킨다.

widget.h의 Widget클래스

...

class Widget : public QWidget
{
    Q_OBJECT

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

private:
    QLabel *label;

public slots:
    void setValue(int val);
};

...

 

Slots

public slots:
    void setValue(int val);
  • slots의 접근제한자는 private 또는 public과 함께 사용이 가능하다.
  • slots라는 키워드를 사용하여 명시한 멤버 함수는 Slot 함수를 정의가 가능하다.

widget.cpp

#include "widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    label = new QLabel("",this);
    label->setGeometry(10,10,250,40);

    SignalSlot myObject;

    // new style
    connect(&myObject, &SignalSlot::valueChanged, this, &Widget::setValue);

    // old style
    //connect(&myObject, SIGNAL(valueChanged(int)), this, SLOT(setValue(int)));

    myObject.setValue(50);
}

void Widget::setValue(int val){
    QString labelText = QString("Signal emmit, Value : %1").arg(val);
    label->setText(labelText);
}

Widget::~Widget()
{
}

connect() 함수

    // new style
    connect(&myObject, &SignalSlot::valueChanged, this, &Widget::setValue);

    // old style
    connect(&myObject, SIGNAL(valueChanged(int)), this, SLOT(setValue(int)));
  • 첫 번째 인자: 이벤트가 발생한 오브젝트(클래스 인스턴스)
  • 두 번째 인자: 오브젝트의 시그널(이벤트)
  • 세 번째 인자: 시그널과 호출할 슬롯 함수가 있는 오브젝트 이름
  • 네 번째 인자: 시그널 발생 시, 호출 할 슬롯 이름

 

new style

  • Qt 5.5 이상 버전에서 추가된 방식
  • 여러 개의 인자 사용 불가능
  • Slot 함수 뿐만 아니라 일반 멤버 함수도 Slot 함수와 같이 connect() 함수에서 4번째 인자로 사용 가능

 

흐름

1. cpp 코드에서 Signal 선언된 클래스 선언

SignalSlot myObject;

 

2. Signal과 Slot을 connect

connect(&myObject, &SignalSlot::valueChanged, this, &Widget::setValue);

  

2. myObject 객체의 멤버 함수 호출

myObject.setValue(50);

 

3. 멤버 함수의 emit이 시그널 발생

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

 

4. 시그널이 발생하면 연결된 슬롯이 실행

public slots:
    void setValue(int val);
    
...

void Widget::setValue(int val){
    QString labelText = QString("Signal emmit, Value : %1").arg(val);
    label->setText(labelText);
}

 

5. 결과

 

6. 흐름도

 

요약

  • emit이 호출되면 시그널을 발생시킨다.
  • 시그널은 함수 구현부가 없으며, 헤더에만 정의 구현만 한다.
  • 예제와 같이 Signal고 Slot 함수는 다른 클래스에만 구현되어 있어야 되는 것은 아니다.
  • 동일한 클래스에 존재하는 Signal이 Slot 함수를 호출 할 수 있다.
  • Signal이 Signal을 호출 할 수 있다.
  • Signal과 Slot을 사용하려면 class 내부에 무조건 Q_OBJECT를 선언해야된다.

 

'🌠Development > QT' 카테고리의 다른 글

QT - Dialog  (0) 2024.07.12
QT - Signal and Slot (3)  (0) 2024.07.12
QT - Signal and Slot (1)  (0) 2024.07.11
QT - Layout  (1) 2024.07.11
QT - 계산기 만들기  (0) 2024.07.11