그래픽 & 멀티미디어
사용자 슬롯을 만들기 위해서는 MOC(Meta Object Compiler) 에 대해 좀 알아야 합니다. qt 는 qt 컴파일러가 따로 있는 것이 아니라 한단계 거쳐서 c++ 컴파일러로 컴파일됩니다. 문제는 시그널에 대한 슬롯 처리는 qt 에서 처리할 수 없기 때문에, 작성한 프로그램을 가지고 컴파일해서는 시그널 처리를 하실 수 없습니다.
번거롭지만, 슬롯 처리를 할 수 있도록 소스를 다시 만들어 주어야 합니다. 그러나 프로그래머가 직접 만들어야 한다면 너무 성가신 일이겠죠. 이 성가신 일을 대신해 주는 것이 MOC 입니다.
MOC 를 사용하지 않고 바로 컴파일해 버리면 링크까지 이상없이 끝나지만 실행 시에 시그널, 즉 이벤트가 발생해도 슬롯 함수로의 호출이 이루어지지 않습니다.
그러므로 qt 로 만들어진 소스에다가 컴파일하기 전에 MOC 를 호출해서 소스를 다시 만들고, 그리고 난 후에 컴파일하도록 처리해 주어야 하는데, 이 때 사용하는 것이 Q_OBJECT 라는 매크로 함수입니다.
아래와 같이 MOC 사용을 위해 내용을 추가합니다.
- 클래스 선언부에 Q_OBJECT 를 넣어 주어야 하고,
- 접근 제한자에 slot 키워드를 추가해 주어야 합니다.
아래의 소스는 MOC 를 사용하기 위해서 위의 2가지를 처리한 코드입니다. 그러나 내용을 보면 아무 이상이 없지만 링크 시에 에러가 발생합니다.
▶ 링크시에 에러 발생하는 main.cpp
#include <qapplication.h> #define kor(str) QString::fromLocal8Bit(str) class TForm:public QWidget TForm::TForm() void TForm::OnClicked() int main(int argc, char **argv) app.setMainWidget( &frm); return app.exec(); 코드에 이상이 없지만, 링크시에 아래와 같은 이상한 에러가 발생합니다. 정말 황당하죠.
|
결론부터 말씀 드리면 클래스 선언부를 헤더파일로 이동하시고 다시 컴파일하시면 됩니다.
참고로 프로그램은 가급적 모듈화해서 작성하시는 것이 좋습니다.
▶ 클래스 선언부를 헤더파일로 이동
main.cpp |
#include <qapplication.h> #define kor(str) QString::fromLocal8Bit(str) class TForm:public QWidget TForm::TForm() void TForm::OnClicked() int main(int argc, char **argv) app.setMainWidget( &frm); return app.exec(); |
main.h |
#ifndef JWSLOT_H #define kor(str) QString::fromLocal8Bit(str) class TForm:public QWidget #endif |
자 이제 progen 과 tmake 로 makefile 을 만들고 컴파일하겠습니다.
그런 컴파일하면 또 같은 undefined reference to 'vtable for TForm' 에러가 발생합니다.
# progen -o app.pro main.cpp
# tmake -o Makefile app.pro
왜일까요? MOC 를 거치면서 나오는 c 소스파일들을 보면 예상이 되는데요, 만들어진 main.h 도 MOC 에 정보로 주어야 합니다. 그러므로 프로젝트 파일에 main.h 헤더 내용을 추가하고 Makefile 을 다시 만들면 됩니다.
# progen -o app.pro main.cpp main.h
# tmake -o Makefile app.pro
이제 컴파일해 보면 아무 이상없이 컴파일되고 실행파일이 생성됩니다.
프로그램 모듈을 만들 때, main.cpp 와 main.h 로 분리하기 보다는 main.cpp 는 "클래스 생성" 에서 언급했듯이,
- 위젯을 생성하고,
- 메인위젯을 지정한다.
- 프로그램을 실행한다.
와 같은 내용으로 구성하고, 클래스에 대한 선언과 구현은 따로 파일로 만드는 것이 좋습니다. 즉, 위와 같은 소스는
- main.cpp
- main.h
보다는
- main.cpp
- form.cpp
- form.h
로 나누는 것이 좋습니다.
main.cpp |
#include <qapplication.h> int main(int argc, char **argv) app.setMainWidget( &frm); return app.exec(); |
form.cpp |
#include <qapplication.h> #define kor(str) QString::fromLocal8Bit(str) TForm::TForm() void TForm::OnClicked() |
form.h |
#ifndef JWSLOT_H class TForm:public QWidget #endif |
아래와 같이 Makefile 을 만들고 컴파일합니다.
# progen -o app.pro main.cpp form.cpp form.h
# tmake -o Makefile app.pro
태그: *QT *그래픽