그래픽 & 멀티미디어
QT4에서 hello 프로그램을 작성해 보겠습니다. QT4에서는 QT3와는 달리 폼 디자인 뿐이 안됩니다. 제가 설치한 것은 free source 라서 그런 것인지 모르겠습니다만 QT4에서는 프로젝트 메뉴부터 없습니다. 가능한 것은 폼 디자인 뿐이라 프로젝트 파일부터 폼을 위한 헤더와 소스 파일까지 만들어 주어야 합니다.
이 시간에는,
- QT4에서 프로그램을 작성하고 실행하는 방법을 소개하는 것이므로
- 예제를 매우 간단히 작성하겠습니다.
- 그리고 같은 프로그램을 임베디드용으로 다시 컴파일해서
- 임베디드 보드에서 실행해 보겠습니다.
폼디자인
우선 폼 디자인부터 하겠습니다. X11 용으로 파일을 먼저 만들어야 하므로 X11 환경을 세팅합니다.
]$ soruce /qt4/.qtx // X11로 환경을 설정합니다. ]$ designer // 디자이너를 실행합니다.
디자이너를 실행하면 생성할 폼 형태를 선택하는 윈도우가 출력됩니다. "Dialog with Buttons Bottom"을 선택합니다. 그리고 [Create] 버튼을 클릭합시오.
Create 버튼을 클릭하시면 아래와 같이 폼 하나가 생성됩니다. 속성 에디터에서 폼의 이름을 TfrmMain 이라고 입력했습니다.
이 폼에는 벌써 [OK] 와 [Cancel] 버튼의 클릭 시그널에 대한 처리가 되어 있는 상태입니다. Ctrl-R 키를 누르신 후 [OK] 나 [Cancel] 버튼을 클릭해 보세요. 버튼을 클릭할 때 폼이 닫히지요.
생성된 폼에 라벨 위젯을 배치하고 거기에 Hello, Forum Falinux 라고 입력하겠습니다. 폰트도 좀 크게하구요.
예제 프로그램은 여기까지로해서 간단히 하겠습니다. 이제 디자인한 폼을 저장합니다. 저는 폼 이름에 맞추어 frmMain.ui 로 저장했습니다.
필요 파일 생성
한 개의 폼으로 구성되는 프로그램이라도 하더라도 아래의 파일을 만들어 주셔야 합니다.
- frmMain.h // frmMain.ui 에 디자인된 폼을 이용하기 위한 헤더 파일
- frmMain.cpp // frmMain.ui 에 사용자 코드를 넣는 파일
- main.cpp // main() 함수가 들어갈 소스 파일
frmMain.h
frmMain.h 부터 만들겠습니다.
#ifndef __FRM_MAIN__ #define __FRM_MAIN__ #include "ui_frmMain.h" class frmMain : public QDialog { Q_OBJECT private: Ui::TfrmMain ui; public: frmMain( QWidget* parent = NULL); }; #endif
내용을 보니가 알지도 못하는 "ui_frmMain.h" 파일을 include 했습니다. 그리고 frmMain 객체를 선언했고, TfrmMain 의 디자인 정보를 이용하기 위한 ui 변수를 선언했습니다.
ui_frmMain.h는 앞으로 컴파일 과정 중에 생성될 파일이빈다. 지금은 없고 앞으로 만들어질 것을 예상하면서 코드를 한다는 것이 익숙하지는 않습니다만, 이렇게 디자이너로 ui 파일을 만들고 다시 .cpp와 .h 와 같이 소스 파일을 만드는 이 이유는, 물론 제 개인적인 생각입니다만 디자인 파일을 이용하더라도 사용자 코드를 보호하기 위함입니다.
즉, 디자인은 frmMain.ui 에 모두 넣었는데, 여기에 프로그램 코드를 넣을 수 없습니다. 넣는다고 해도 문제입니다. 왜냐하면 나중에 디자이너로 폼을 수정하면 사용자 코드는 사라질 수 도 있기 때문이죠.
혹시, 제가 이전에 올렸던 "QT - QT 2.x.x 디자이너 사용 방법" 글을 보셨나요? 2.x.x 에서도 디자이너로 폼을 생성하고, 그 폼에서 .cpp파일과 .h 파일이 생성되는데, 생성된 .cpp 나 .h 파일에 사용자 코드를 넣으면 컴파일에서 실행파일까지 이상없이 만들어 지지만 폼을 다시 디자이너로 수정한 후에 다시 .cpp 나 .h 파일을 생성하면 어렵게 넣었던 사용자 코드가 사라집니다.
그러므로 폼에서 만들어진 .cpp 나 .h 파일은 손을 대지 말고 대신에 그 폼의 클래스를 상속받아, 상속 받은 파일에 사용자 코드를 넣습니다.
QT4 도 비슷한 방법입니다.. frmMain.ui 에서 TfrmMain의 디자인 정보를 가져와서 그 디자인에 따라 frmMain을 구성하겠다는 것입니다. frmMain.h 내용을 다시 보면 UI::TfrmMain ui; 를 보실 수 있습니다.
class frmMain : public QDialog { Q_OBJECT private: Ui::TfrmMain ui; // TfrmMain의 UI를 사용할 수 있도록 ui를 선언 public: frmMain( QWidget* parent = NULL); };
frmMain.cpp
frmMain.h 에 frmMain()을 초기화하는 부분이 있습니다. frmMain.cpp 에 내용을 넣습니다.
#include <QMessageBox> #include "frmMain.h" frmMain::frmMain(QWidget* parent/*=NULL*/) : QDialog( parent ) { ui.setupUi( this); }
초기화 부분에 ui 를 현재의 폼을 지정해 주고 있습니다. 아직 QT의 세부 구조까지는 자세히 모르겠습니다만, 어째든 사용자는 frmMain.ui 의 디자인 파일을 이용하면서 프로그램에 코드는 frmMain.ui에 입력하는 것이 아니라 frmMain.cpp 나 frmMain.h 에 넣는다는 것이죠.
그래서 결국 디자이너에 의해 ui 파일일 수정되더라도 프로그램 코드는 손상받지 않습니다.
main.cpp
자, 디자인된 폼을 이용할 수 있는 frmMain.cpp와 frmMain.h 파일을 만들었습니다. 이제 C 프로그램 답게 main() 함수가 있어야 겠지요. main()함수가 있는 만큼 파일 이름도 main.cpp 라고 하겠습니다. 그리고 main() 안에 frmMain 객체를 생성하고 화면에 출력하겠습니다.
#include <qapplication.h> #include "frmMain.h" int main( int argc, char **argv) { QApplication app( argc, argv); frmMain frm; frm.show(); return app.exec(); }
프로젝트 파일 생성
이제 컴파일을 해서 실행 파일을 만들어 내면 되겠습니다. 그렇게 하기 위해서는 Makefile이 필요한데, Makefile을 만들기 위해서는 프로젝트에 대한 정보 파일이 필요합니다. QT는 다중 플랫폼을 지원하기 때문에 같은 파일을 가지고 서로 다른 프랫폼에서 실행되는 프로그램을 만들 수 있습니다.
그러므로 어떤 파일로 프로젝트를 구성하는지를 얄려 주는 프로젝트 파일인 .pro 를 먼저 만듭니다. 또한 .pro 파일 이름이 실행파일 이름이 되므로 적당한 이름으로 만드러야 겠습니다.
]$ qmake -project -o hello.pro
qmake 는 -project 옵션을 받으면 그 디렉토리에 있는 모든 파일 정보를 가지고 프로젝트 파일을 생성합니다. -o hello.pro 를 주어 프로젝트 이름을 지정해 주었습니다.
이상없이 작업이 끝나면 hello.pro 파일이 생성됩니다.
이 hello.pro 파일을 만들고 나며 이 파일을 가지고 Makefile을 만들어야 겠습니다. X11용 실행 파일을 만들기 위해서는 qmake 라고만 실행합니다.
]$ qmake
파일 목록을 확인해 보시면 Makefile이 생성된 것을 보실 수 있습니다.
이제 make 를 실행하여 실행파일을 생성합니다.
]$ make
컴파일이 완료되면 프로젝트 이름과 같은 hello 실행파일이 생성됩니다. 실행합니다.
]$ ./hello
그러면 화면 중앙에 실행된 프로그램을 보실 수 있습니다.
[OK]나 [Cancel] 버튼을 클릭하시면 프로그램이 종료됩니다.
임베디드 보드에서 실행
이번에는 같은 소스를 가지고, 소스 수정없이 실행 파일을 만들고 임베디드 보드에서 실행해 보겠습니다. 우선 x11을 위한 작업 내용을 없애야 겠습니다.
]$ make clean
테스트에 사용된 임베디드 보드는 ESP-MMI입니다. ESP-MMI는 모니터와 연결할 수 있는 RGB 포트가 있어서 학습하기에 매우 편리한 보드라서 여러 차례 강좌에서 소개한 보드입니다.
Makefile을 새로 생성 및 컴파일
소스 파일은 그래도 사용할 것이므로 프로젝트 파일은 변경하실 필요가 없습니다. 대신에 Makefile을 다켓 보드에 맞추어 새로 생성해야 합니다. 일단 컴파일러부터 크로스 컴파일러를 이용해야 하니까 말이죠.
아래와 같이 qmake 를 이용하여 타켓 보드에 맞춘 Makefile을 생성합니다.
]$ source /qt4/.qte ]$ qmake -spec $QTDIR/mkspecs/qws/linux-arm-g++ hello.pro
에러가 없다면 타겟 보드를 위한 Makefile 이 생성되었습니다. make 를 실행하여 타겟 보드용 실행 파일을 만들어 냅니다.
]$ make
타켓 보드에 라이브러리 복사
타켓 보드에서 QT 프로그램을 실행시키기 위해서는 리눅스 PC에서와 같이 /qt4/qt-arm/lib 디렉토리에 있는 QT 라이브러리가 필요합니다. 그러므로 다켓보드에도 PC에서처럼 똑 같이 복사해 주어야 하는데 그냥 cp 복사 명령을 이용하면 링크 파일까지 원본으로 복사되어 매우 커집니다. 그러므로 tar로 압축한 후, 타켓 보드에 복사해 넣고 풀기를 합니다.
]$ su 암호: ]# tar zcvf qt4-arm-lib.tar.gz lib ]# mv qt4-arm-lib.tar.gz /home/jwjw/public/
타겟보드에 텔넷으로 연결합니다.
여기는 타겟 보드에서 작업하는 내용입니다. falinux login: root ]$ mount -t nfs -o nolock 192.168.10.50:/home/jwjw /mnt/nfs lib 파일을 리눅스 PC와 똑 같이 /qt4/qt-arm 에 풀어 놓겠습니다. ]$ cd / ]$ mkdir qt4 ]$ cd qt4 ]$ mkdir qt-arm ]$ cd qt-arm ]$ tar zxvf /mnt/nfs/public/qt4-arm-lib.tar.gz
프로그램 실행
이제 라이브러리도 복사했으므로 프로그램을 실행할 일만 남았습니다.
]$/mnt/nfs/qt4/01_hello/hello -qws
잠시 후에 짜잔~ 프로그램이 실행된 것을 보실 수 있습니다.
QT 3까지는 저도 nfs 를 이용해서 실행했습니다만
QT 4부터는 QT 라이브러리를 보드에 복사해 놓고 사용하고 있어서
nfs 서버 응답 없음에 대해서는 아는바가 없네요. ^^;
혹, 참고가 될 것 같아서 말씀을 드렸습니다만,
QT 4는 QT3 이전버전과는 달리 QTDIR 과 같은 환경 변수값이 적용이 안되더라구요.
리눅스 호스트 시스템에 설치된 디렉토리 그대로
임베디드 보드에 복사해서 실행해야 실행이 되더군요.
아~ 넵..
그래서 보드에 복사를 하려고 해봤습니다만.. 라이브러리를 복사하는도중에 멈추는 현상이 나타납니다.
압축된파일이 12메가나 되어 압축안하고 파일을 하나씩 복사해보아도 똑같이 다운이 됩니다.
한번 램디스크에 라이브러리를 올려서 올려보겠습니다.
램디스크에 라이브러리를 올리려 했는데 램디스크 이미지가 커져서 문제가 발생하네요
EZBOOT에서 NAND파티션을 조절하였더니 부팅시에 Kernel, Ramdisk Bad Block이(1)이 뜨면서
커널을 카피가 되는데 램디스크가 카피가 안되네요
set 모드 들어가서
파티션F[1:15:48]와
K 부분만 수정[initrd=0xa0800000,15M root=/dev/ram ramdisk=36864]하여 저장하였습니다.
QT을 올리려고 하니 이거 쉽지가 않네요.. 3.4대 버전으로 다시 설치해봐야겠습니다. ㅜㅜ
NFS에서 관련 부분을 링크를 이용해서 컴파일 했던 그 디렉토리 그대로 잡으면 됩니다.
/mnt/nfs 에 qt관련 부분을 링크 혹은 복사를 해 두시구요.
보드에서도 NFS로 마운트한 부분을 ln -s /mnt/nfs/qt4.3.3 /usr/local/qt-core/4.3.3
과 같이 하시고 개발 보드에서 실행 하실 수 있습니다.
복사를 하시려면 임베디드 에서는 용량이 부족할 수도 있습니다. 그렇기 때문에 개발 기간에는 링크로 작업을 하시고요 실제 배포 할때는 라이브러리 사이즈를 줄이는 방법을 강구 하셔야 합니다.
네.. 저도 NFS로 마운트하여 링크로 작업을 하려고 하는데 EZ-X5보드에서는 NFS로 마운트하여 작업해도 먹통이 되고 그래서 복사하여 사용하려고하는데 먹통이 됩니다.
EZ-X5로 해결해보신분이 있으시면 좋겠는데 아직은 없으신건지 아니면 EZ-X5보드가 문제가 있는건지 모르겠습니다.
ㅜㅜ
평상시 EZ-X5를 사용하면서 nfs를 자주 사용하고 있어서서
EZ-X5가 NFS에 문제가 있다고 생각한 적은 없었습니다.
그러나 PC 호스트보다 EZ 보드가 느린 시스템이기 때문에
간혹 EZ보드에서는 패킷을 잃어 버리는 문제가 있다고 합니다.
혹, 이문제라면 전송되는 패킷 사이즈의 크기를 조정해 보면 어떨까요?
즉, NFS 명령의 옵션 중 wsize와 rsize를 이용하여
한번에 주고 받는 데이터량을 조절해 주는 방법입니다.
일단 rsize와 wsize를 작은 값으로 해 보세요.
]$ mount -t nfs -o nolock,rsize=1024,wsize=1024 xxx.xxx.xxx.xxx:/nfs /mnt/nfs
앞 쪽에 있는 -o 옵션 끝 부분에 공백없이 ,(콤마)를 넣고
역시 공백없이 rsize=1024,wsize=1024를 적습니다.
그리고 한칸 띄어서 host 주소:/공유 /mnt/nfs 식으로 넣어 주면 됩니다.
이렇게 해서 문제가 없다면 rsize와 wsize 크기를 바꾸어 가면서
가급적이면 안정되고 빠른 패킷 크기를 확인하셔서 사용하시면 됩니다.
참고로 rsize, wsize의 최대 크기는 8Kbyte입니다.
위에 말씀하신데로 하니 2M가 넘는 화일도 카피가 잘됩니다.^^
감사합니다.
이거 그동안 축처졌다가 다시 살아나는 느낌입니다.
이게 계속 다시 해보도록 하겠습니다^^
감사합니다!!
QT 4.3.3
EZ-X5사용중입니다.
qt라이브러리를 cp 하는데 nfs서버 응답없다고 메세지 표시하면서 멈추어 버립니다. 어떻게 해야될까요?
이것때문에 몇일동안 삽질만 하고 있습니다. 라이브러리 용량이 커서 그럴까요?