QT의 주요 특징 중 하나가 signal & slot 이라는 개념일 것입니다.
아마 위의 제목처럼 link에러 뜨는 것을 보고 '뭐 이래!!' '뭔 문제야!' 라고 한참 google 사이트를 뒤진적이 있으셨다면
잘 오셨습니다. ㅋ 저도 그런 사람 중 하나였고 뭐 그리 좋은 답은 없더군요.
또한 signal 함수를 Header만 선언하고도 빌드가 되네 라고 생각하신 분들도 잘 오셨습니다.
답을 말하면 결론적으로 [signal function을 사용자가 임의로 구현하면 안된다] 입니다.
무슨 뜻이냐..
그렇다면 signal과 slot에 대해 기본 개념과 목적을 다시 살펴보면 쉽게 알 수 있습니다.
QT에서 signal은 특정 Q_OBJECT가 자신의 멤버 변수나 상태 등이 변경되어 외부로 보내지는 신호라는 개념이고
Slot은 signal 신호를 받아 뭔가를 처리하기 위한 곳의 개념이죠.
자 그럼.. signal 함수를 추가해볼까요..
Header file은 이렇게 구현을 했다고 하겠습니다.
class MyWidget : public QWidget
{
Q_OBJECT
public:
explicit MyWidget(QWidget *parent = 0);
public slots:
void SetColor(int color);
signals:
void ColorChanged(int color);
protected :
int m_color;
};
그럼 Cpp도 구현해 볼까요
#include "MyWidget.h"
MyWidget ::MyWidget (QWidget *parent) :
QWidget(parent)
{
}
void MyWidget ::ColorChanged(int color)
{
qDebug() << "aaa";
}
void MyWidget ::SetColor(int color)
{
m_color = color;
emit ColorChanged(color);
}
우선 잘못된 예를 보이려고 위와 같이 ColorChanged() 라는 함수도 구현 했습니다.
음.. 이렇게 빌드해서 보니
multiple definition of `MyWidget::ColorChanged(int)'
이렇게 에러가 발생되네요. 왜냐..
moc_MyWidget.cpp가 빌드 시에 자동 생성되면서
void MyWidget::ColorChanged(int _t1)
{
void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
QMetaObject::activate(this, &staticMetaObject, 0, _a);
}
이런 놈을 생성시켜버렸기 때문이죠..
자 우선 만들어진 코드를 볼까요..
코드를 보면 QMetaObject::activate(this, &staticMetaObject, 0, _a); 라는 코드를 호출하게 되어 있죠.
실제 이 호출로 connect 함수로 연결된 slot 함수로 _a 변수의 _t1 파라미터가 전달되게 됩니다.
제가 임의로 signal 함수를 보면 실제로 log를 출력하는 것 이외에 다른 하는 일은 없습니다.
결국 signal 함수의 용도는 다른 Q_OBJECT 객체로 어떤 내용를 보내준다는 것이죠.
그런데 그 signal 함수를 임의로 작성하면 signal함수의 역할을 잃어버리게 되겠죠.
그럼 임의로 우리가 만든 코드에 임의로
자동으로 생성된 함수를 지워버리고 아래와 같이 그 기능을 작성해서 넣으면 되지 않느냐.. ?? 이렇게???
void MyWidget::ColorChanged(int color)
{
qDebug() << "aaa";
void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&color)) };
QMetaObject::activate(this, &staticMetaObject, 0, _a);
}
뭐 물론 이렇게 해도 됩니다.
하지만 clean 후 build하면 무조건 자동으로 moc_MyWidget.cpp 파일이 만들어지고 ColorChanged() 함수는 만들어 집니다.
굳이 이렇게 새로 함수를 만들 이유는 없겠죠..
결국 우리가 필요한 signal함수는 Header file에만 선언하고 실제 구현은 컴파일러에게 맡기면 됩니다.
추가적으로 signal 함수를 사용해야겠죠.
물론 아시겠지만
다른 Q_OBJECT가 알게해주고 싶다.! 그러면
void MyWidget::SetColor(color)
{
...
emit ColorChanged(color);
...
}
이런 식으로 호출해 다른 Q_OBJECT객체에 전달해 주면 되겠죠.
결과적으로 정리를 하면
QT에서 Signal function은 한 객체에서 다른 객체로 약속된 형태의 parameter들을 전달하는 역할을 하고, connect 함수를 이용한 slot과의 기본 interface를 위해 컴파일러는 자동으로 그 파라미터를 전달할 수 있는 signal 함수를 생성한다.
그리고 signal을 보내려는 객체는 emit 이라는 keyword 이용할 수 있다.
PS : MFC 경험이 있으신 분이라면 공감하시겠지만 signal은 notify message와 비슷한 개념입니다. MFC에서는 기본적으로 window를 기반으로 message를 처리하게 되어 있지만 QT의 signal & slot은 O_OBJECT형태의 객체라면 어떤 것이든 연결가능하다는 것이 장점이겠죠.
'Qt' 카테고리의 다른 글
QML Plugin QmlType 생성 (0) | 2018.06.10 |
---|---|
QT TextEdit Block & Char Formatting (0) | 2016.08.08 |
QT build static library (0) | 2015.06.05 |
QT : 특정 디렉토리의 하위 디렉토리 포함한 파일 검색 (0) | 2014.02.14 |
QT : stylesheet의 property사용하여 widget 그리기 (0) | 2014.02.05 |