본문 바로가기

My Project/교통정리로봇

[교통정리로봇] 프로젝트 문서 2. 관련연구(네번째)

   나. User Interface(QT-Design)

(1) QT에 대한 소개

1996년 초 노르웨이의 Trolltech사에서 발표한 GUI 프로그램 개발용 라이브러리로 Windows, Linux, Max, Solaris 등에 지원됩니다. 어플리케이션 개발자는 QT의 최신기술을 이용하여 GUI(Graphical User Interface)를 구축하는 데 필요한 기능을 모두 얻을 수 있습니다. QT는 완전 객체지향으로, 용이하게 확장할 수가 있어 진정한 컴포넌트(Component) 프로그래밍이 가능합니다. QT는 리눅스 Desktop의 기본(KDE의 기본 라이브러리)을 구성하는 라이브러리이고 거의 모든 리눅스 배포 판에 기본으로 포함되어 있습니다. 풍부한 양의 위젯을 제공하여 사용하기 쉽고 화려한 인터페이스를 제공하며 객체지향으로 프로그램의 개발이 쉽고 쉽게 확장할 수 있습니다. QT는 푸쉬버튼, 메뉴, 다이얼로그와 같은 그래픽 객체(Graphical Object)와 이것들을 구현하기 위해 필요한 함수들의 모임(Library)입니다. 그래픽 객체들은 위젯(Widget)이라고도 불리며 이 위젯에 대응하는 함수들을 합한 것을 툴킷(Toolkit)이라고 합니다.


(2) QT의 장점

■ QT를 사용한다면 윈도우에서 코딩을 하여, 이것을 다른 여러 가지 유닉스에서는

   다시 컴파일만 해서 간단히 프로그램을 구동시킬 수 있음(이식성)

■ QT를 이용한 프로그램은 속도가 매우 빠른데 이렇게 빠른 이유는 QT를 개발한

   프로그래머가 QT를 최적화 하는데 많은 노력을 기울였기 때문(속도가 빠름)

■ 다른 툴킷보다 훨씬 사용하기 쉬움(사용하기 쉬움)

(3) QT의 라이센스

기존의 1.xx대에서는 GPL(General Public Licens : 일반공중라이센스)을 따를 수 없었지만 2.xx대에서부터 QPL(Q Public License)과 GPL을 선택해서 사용할 수 있게 되었습니다. QT의 라이센스는 다음과 같은 3가지의 다른 라이센스가 존재합니다.

■ QT Enterprise Edition and QT Professional Edition(QT Commercial License)

   이 버전으로 상용 소프트웨어의 개발을 할 수가 있습니다. 상용으로 소프트웨어

   를 개발하여 배포가 가능하고, 무료의 업그레이드와 기술지원(Technical

   Support)서비스가 포함됩니다. 기업판(Enterprise Edition)에서는 상용판

   (Professional Edition)에는 없는 확장 모듈이 포함됩니다.

■ QT Free

   자유롭게 개발되는 Open source 소프트웨어의 개발에만 이용할 수 있는 QT의

   Unix/X11 버전입니다. 이것은 Q Public License와 GNU General Public License

   에 근거해, 무료로 이용할 수 있습니다.

■ QT/Embedded Free Edition

   자유(free) 소프트웨어의 개발에만 이용할 수 있는 QT의 Embedded 버전입니다.

   이것은 GNU General Public License에 근거해, 무료로 이용할 수 있습니다.

■ 기타

   • 윈도우와 맥용의 경우에는 자유(free)판은 없고 상용판만이 존재하며, 물론

     평가판(Evaluation Version)은 제공됩니다.

   • Unix의 경우 상용판과 자유 판이 모두 존재하며, 자유 소프트웨어로 라이센스

     (Open Source로 개발 하는 경우)에 따라서 자유 판을 사용할 수 있습니다.

   • 다른 툴킷과는 다르게 QT자유 버전을 이용해서 프로그램을 개발하다가 상업적

     으로 판매를 하기 위해서는 QT 상업용 버전을 구입하면 되기 때문에, 다른 툴

     킷의 라이센스에 비해서 보다 자유롭습니다. 프로그램의 실행파일의 배포에는

     따로 라이센스가 필요로 하지 않습니다.


(4) QT 버전

버전

다른 버전과의 차이점

비고

1.xxx

KDE 프로젝트에 기본 라이브러리 사용

Netscape Plug - in

자동 레이아웃(Automatic Layout)

KDE 1.xxx

2.xxx

최초의 국제화 기능 지원(Unicode 기본지원)

테마기능의 지원

MDI 기능 지원

QT Designer 제공(QT 3.3 부터)

멀티 쓰레드 (Multi-thread) 기능

KDE 2.xxx

3.xxx

2.xx 버전에 대해서 많은 수의 위젯의 추가 및 수정

Mac OS X 지원

데이터베이스에 관련된 API 지원

KDE 3.xxx

(5) QT가 가지는 특징

■ 다양한 플랫폼(Platform)을 지원

   다른 라이브러리에서 프로그램을 개발하는 것과는 다르게 포팅이 자유롭습니다.

   단지 해당 플랫폼 에서 재컴파일 하는 것으로 유닉스 / Mac OS X 및 윈도우 환

   경에서 실행됩니다. MS/Windows(95, 98, NT 4.0, ME and 2000), Unix/X11

   (Linux), Sun Solaris, HP-UX, Digital Unix, IBM AIX, SEI IRIX, 그 외 많은

   다른 제품 Macintosh : MacOS X(QT 3.0부터 지원)

   Embedded : 프레임버퍼(framebuffer)를 지원하는 리눅스 플랫폼

■ C++ 기반의 객체지향 클래스 라이브러리

   QT의 모든 구현이 C++ 클래스로 캡슐화 되어 있어 배우기 쉽고 사용하기 쉽습니

   다. 그리고 상속을 이용하여 기능을 쉽게 확장할 수 있습니다. MS Windows의

   MFC와 비슷하며 기존의 C에 비해서 개발이 훨씬 쉽고, 기능 확장이 편리해서 생

   산성이 높습니다.

■ 국제화 기능 지원(2.0부터 i18N 기본 제공)

   QT 2.0부터 16비트인 유니코드를 완벽하게 지원합니다. 또한 다양한 ISO 변환

   규격과 지역화 (Localization)을 지원합니다. 각 나라의 언어로 작성된 메시지

   파일만 있으면, 해당 언어로 변역된 프로그램을 쉽게 사용할 수 있습니다.

   QT 3.0부터는 메시지의 번역을 쉽게 하기 위해서 QT Linguist라는 유틸리티를

   제공하고 아랍어나 희랍어를 위해서 오른쪽에서 왼쪽으로 글을 쓰는 것을 지원

   합니다.

■ Signal / Slot 방식(Signals/Slots Mechanism)

   QT 에서는 QObject라고 불리는 클래스에 신호(Unix에서 말하는 신호는 아님)를

   내는 기구와 그 신호를 슬롯(멤버함수)에서 받는 기구가 갖춰져 있습니다. 객체

   (Object)의 신호(Signal)를 다른 객체의 슬롯(Slot)에 연결함으로써 프로그램의

   동작을 결정합니다. 기존의 Motif에서 사용하는 Callback 방식이 아닌

   Signals/Slots Mechanism을 사용 합니다. 기존의 Event Model도 제공합니다.

■ 표준 GUI를 구성할 수 있는 풍부한 양의 위젯(Widget) 제공

   표준 User Interface(Push button, list, menu, check box......)를 제공하고

   표준 Look과 Feel을 제공(Theme 기능도 제공)합니다. 최초의 OSF Motif 스타일

   이 가장 아름답고 화려한 GUI 스타일이라고 생각하는 사람의 거의 없을 것입니

   다. 그 때문에 위 스타일을 좀 더 개량하려고 하는 시도가 몇 번이나 이루어졌

   습니다. 그중 하나가 CDE스타일로 이것은 QT의 버전 2.0이상부터 지원되고 있습

   다. 2.2부터는 IRIX워크스타일의 SGI스타일이 지원되고 있습니다. 이것보다

   근사한 3D의 기울기나 마우스 아래를 하이라이트 하는 효과 등이 있어 매우 매

   력적입니다. 또 리눅스 사용자들을 위하여 Motif 플러스 스타일도 추가가 되었

   습니다. 그리고 3.0 부터는 매킨토시 사용자들을 위하여 아쿠아 스타일도 추가

   가 되었습니다.

(6) QT 사용을 위한 C++

■ 객체와 클래스

   QT 역시 클래스를 사용하는데 정확한 의미로는 QT는 클래스 라이브러리 입니다.

   그러므로 C++ 객체지향의 기본지식이 필요합니다.

■ 접근 메서드

   QT는 많은 접근 메서드를 사용하는데, 이러한 메서드는 비공개 클래스 변수 값

   설정하거나 가지고 올 때 이용하는 것들입니다. 설정을 위한 메서드는

   “set" 으로 시작하는 이름을 갖고 있는 반면, 변수 값을 가져오는 메서드는 이

   러한 접두어를 갖고 있지 않습니다.

■ 다형성과 가상함수

   QT는 저수준 이벤트에 대한 정보를 객체에게 알리기 위해서 가상 함수를 사용하

   므로 이에 대한 지식이 필요합니다. 다른 툴킷이나 클래스 라이브러리와는 달리

   QT는 객체 간의 주요 통신 수단으로 가상 함수를 사용하지 않고 시그널과 슬롯

   기법을 사용합니다.

■ 상속

   QT 역시 상속을 사용하지만 대부분 시그널 상속에 관련된 부분에만 적용하고

   있습니다.

■ 연산자 오버로딩

   QT는 기초적인 부분에서 연산자 오버로딩을 사용합니다. 예를 들어 Qstring 객

   체를 const char*을 인자로 사용하는 함수에게 보낼 수 있는데 이는 오버로딩

   된 특정 연산자가 Qstring 객체를 문자 상수 포인터로 넘겨주기 때문입니다

■ 템플릿(Templastes)

   QT는 콜렉션 클래스를 위해 템플릿을 사용을 합니다. 그러므로 템플릿을 지원하

   지 않거나, 지원이 완전하지 않은 컴파일로 QT를 컴파일 할 수 없습니다.

■ Bool 데이터형

   QT는 bool이라는 새로운 데이터 형을 사용합니다. 그러나 오래된 컴파일러들은

   이를 지원하지 못할 수도 있습니다.

■ 다른 기능들

   QT는 C++에서 특정 범위를 지정하는 키워드인 네임스페이스와 런타임형 검증,

   새로운 형태의 캐스트 등과 같이 최신 C++기능은 지원하지 않습니다.


(7) QT 사용을 위한 기본예제

■ 첫 번째 예제

   C언어에서 제일 처음 배우는 “Hello World"를 출력하는 것과 같은 예제입니다.

   이 예제를 통해서 QT 프로그래밍의 전반적인 구조를 이해 할 수는 없지만 가장

   기본이 되는 내용이므로 차근차근 이해를 하고 넘어가야 할 것 같습니다.

================================================================================================

////////////////////////////////////////////////////////////////////////////////////////////////

qapplication.h : QApplication 클래스를 사용할 때 선언하는 헤더파일

qwidget.h : QWidget 클래스를 사용할 때 선언하는 헤더파일

qlabel.h : QLabel 클래스를 사용할 때 선언하는 헤더파일

////////////////////////////////////////////////////////////////////////////////////////////////

#include <qapplication.h>

#include <qwidget.h>

#include <qlabel.h>

 

class Myclass : public QWdidget

// 모든 클래스는 QWidget에서 상속받아야 함

{

public :

        Myclass();

      // 생성자 : 프로그램이 실행될 때 클래스가 구동되면서 자동으로 생성

private :

        QLabel *label;

};


Myclass::Myclass()

{

        setCaption("Hello World!!");

        // 실행창의 타이틀 바에 “Hello World!!"를 출력

        label->setText("Hello World~~");

        // label에 “Hello World~~”를 출력

}


int main(int argc, char **argv)

{

        QApplication app(argc, argv);

        // app는 프로그램의 QApplication으로 main 함수에서 받은 인자를 넘겨받음

        Myclass my; 

        // 클래스의 선언부. 정의한 클래스(Myclass())를 my라는 변수로 선언


        app.setMainWidget(&my);

        // Main control로 my이라고 되어있는 위젯을 사용

        my.resize(150, 100); // form의 크기. 실행창 화면의 크기(픽셀단위)

        my.show(); // 화면에 선언한 위젯이 나타나게 함


        return app.exec(); // 프로그램 종료 시 제어권을 QT에게 넘겨줌

}

================================================================================================

■ 두 번째 예제

   Push Button을 사용하여 Show를 클릭하면 "Hello World~!!"가 보이도록하고,

   Hide를 클릭하면 "Hello World~!!"가 보이지 않도록 하는 예제입니다. 이 예제

   를 이해하기 위해서는 signal(시그널)과 slot(슬롯)의 개념을 알아야 합니다.

   signal(시그널)은 Unix계열 운영체제에서 이벤트나 메시지와 동일한 방식으로

   처리하는 것을 말하고, slot(슬롯)은 signal이 발생했을 때 처리되어야 하는 대

   상체를 말합니다. 모든 QT프로그램들은 시그널과 슬롯을 가질 수 있으며, 어떠

   한 위젯이 자신의 내부 상태가 변경되었다면 시그널을 발생 시킵니다. 그리고

   필요한 곳에서 슬롯으로 시그널을 받게됩니다. connect()함수 또한 중요한 역할

   을 하는데, 이 함수는 Signal(시그널)과 Slot을 연결시키는 역할이라고 할 수

   있습니다. 즉, 해당 위젯의 이벤트(signal)와 슬롯에서의 수행동작을 연결시키

   는 것입니다.


================================================================================================

////////////////////////////////////////////////////////////////////////////////////////////////

qapplication.h : QApplication 클래스를 사용할 때 선언하는 헤더파일

qwidget.h : QWidget 클래스를 사용할 때 선언하는 헤더파일

qpushbutton.h : QPushButton 클래스를 사용할 때 선언하는 헤더파일

qlabel.h : QLabel 클래스를 사용할 때 선언하는 헤더파일

////////////////////////////////////////////////////////////////////////////////////////////////

#include <qapplication.h>

#include <qwidget.h>

#include <qpushbutton.h>

#include <qlable.h>


class Myclass : public QWidge // 모든 클래스는 QWidget의 상속을 받아야 함

{

public :

        Myclass(); // 생성자. 클래스의 이름과 동일해야 함


private :

        QPushButton* button1;

        QPushButton* button2;


        QLabel* label1;

};


Myclass::Myclass()

{

        resize(250, 250); // 실행창의 크기, form의 크기(가로, 세로)


        setCaption("QT Programming");

        // 실행창타이틀바에“QTProgramming" 출력


        label1 = new QLabel(this); // Label생성

        label1->setText("Hello World~!!");

        // label1에 “Hello World~!!" 출력

        label1->setGeometry(20, 120, 120, 20);

        // label1을 위젯의 특정 위치에 표시


        button1 = new QPushButton("Show", this);

        // button1에 “Show”로 표시

        button2 = new QPushButton("Hide", this);

        // button2에 “Hide”로 표시


        button1->setGeometry(20, 20, 80, 40);

        // button1을 위젯의 특정 위치에 표시

        button2->setGeometry(20, 70, 80, 40);

        // button2를 위젯의 특정 위치에 표시

////////////////////////////////////////////////////////////////////////////////////////////////

setGeometry(20, 20, 80, 40) : pushbutton이나 label을 특정위치에 표시하는 함수

공백(가로, 세로) ↲     ↳ 크기(가로, 세로)

////////////////////////////////////////////////////////////////////////////////////////////////


        connect(button1, SIGNAL(clicked()), label1, SLOT(show()));

        // button1에서 clicked()이라는 Signal이 발생하면 label1에서 show()함수 실행

        connect(button2, SIGNAL(clicked()), label1, SLOT(hide()));

        // button2에서 clicked()이라는 Signal이 발생하면 label1에서 hide()함수 실행


////////////////////////////////////////////////////////////////////////////////////////////////

connect( button1, SIGNAL(clicked()), label1, SLOT(show()) )

         근원객체     발생이벤트    대상객체   처리기능

⇨ 근원객체에서 발생이벤트가 발생하면 대상객체에서 이런 처리기능을 수행하도록 하라는 것

////////////////////////////////////////////////////////////////////////////////////////////////

}


int main( int argc, char **argv )

{

        QApplication app(argc, argv);

        Myclass my;

        

        app.setMainWidget(&my);

        my.show();


        return app.exec

}

================================================================================================