-- Contents --

    [*] 라즈베리파이 OS x64 설치하기 : https://makeutil.tistory.com/136

    [*] QT5 설치하기 : https://makeutil.tistory.com/138

    [*] QT5 Webengine 설치 : https://makeutil.tistory.com/166

     

    000. Prologue : https://makeutil.tistory.com/168

    001. HelloWorld Project : https://makeutil.tistory.com/169 

    002. HelloWorld 프로젝트 구경하기: <현재>

    003. BasicTextWidget Example : https://makeutil.tistory.com/173

    004. BasicTextWidget 내용 둘러보기 : https://makeutil.tistory.com/174

    005. LayoutExample : https://makeutil.tistory.com/175 

    006. RadiobuttonExample : https://makeutil.tistory.com/177

    007. CheckboxExample : https://makeutil.tistory.com/178 

    ------------------

     

     

      앞서 만든 HelloWorld 프로젝트를 살펴보는 시간을 가지도록 하자. 물론, 이 소스를 통해서 우리가 얻을 수 있는 것은 QT로 생성된 프로젝트가 어떤 모양으로 되어있는지 정도 밖에 되지 않겠지만 QT로 개발되는 작은 프로젝트 부터 어느정도 크기가 있는 프로젝트 모두 동일한 구조에서 출발하니 당연히 눈여겨 봐 두어야 되지 않을까?

     

    앞서 만든 프로젝트에서 왼쪽 사이드 메뉴에서 Edit를 클릭하면 소스트리를 확인할 수 있다.

     

    1. 프로젝트 리스트 확인

       HelloWorld 프로젝트는 아래와 같이 구성되어있다. 

     

    HelloWorld
        HelloWorld.pro
        - Headers
          mainwindow.h
        - Sources
          main.cpp
          mainwindow.cpp
        - Form
          mainwondow.ui

     

    아래는 실제 Qt Creator의 화면이다. 프로젝트 리스트를 클릭하면 오른쪽의 워크 스페이스에 해당 내용이 출력된다. 

     

    화면 좌측의 프로젝트 소스트리를 확인해보자. 파일명이 표시되지 않으면 각 항목을 클릭하여 세부 항목을 확인할 수 있다.

     

      프로젝트 리스트에 표시되는 Headers와 Sources, Froms는 프로젝트 파일에 의해서 구분된다. 따라서 실제 소스 디렉터리(/home/pi/QtWorks/HelloWorld)에 가보면 하나의 폴더에 모든 파일이 위치하고 있음을 확인할 수 있다. 

      아래의 그림은 라즈베리파이의 파일탐색기를 실행하여 소스가 저장된 디렉터리의 내용을 확인한 그림이다. 독자 여러분들이 나중에 사이즈가 조금 큰 프로젝트를 진행하게 되면, 소스 디렉터리 하위에 별도의 디렉터리를 만들고 기능별로 구분하여 사용하게 되는날도 언젠가는 찾아오겠지만, 본 블로그에 연재하는 내용에 한해서는 그럴일은 없을 것이다. 

    프로젝트 폴더에 생성된 소스파일들을 확인

     

    2. 구성파일 확인

    2.1. 프로젝트 파일 (HelloWorld.pro)

       프로젝트 파일의 내용은 아래와 같다. 내용을 정리하자면, 맨위의 QT는 본 프로젝트를 사용하는데 이용되는 QT라이브러리를 나타낸다. 초기의 QT라이브러리는 단일 파일로 구성되었던 적도 있지만, 라이브러리의 크기가 커지면서 필자의 기억으로는 QT4에 이르러서 기능별로 라이브러리들이 분리되었던것으로 기억한다. 따라서 아래의 내용은 QT라이브러리들 중에서 Core와 Gui 라이브러리를 포함한다는 것을 나타내며, QT라이브러들 중 다른 기능이 필요한 경우 사용자가 직접 추가해야 할 수 있다. 이는 나중에 겪에 되니 지금은 그정도만 이야기 하고, 컴파일러 설정은 시스템 컴파일러로 C++11로 지정되어있다. 라즈베리는 ARM플랫폼이므로 지로 CPP(GPP)를 실행하면 ARM에서 사용가능한 것으로 표시 된다. 다만, 라즈베리파이 입장에서는 Desktop 컴파일러이므로 c++로 표시되었다고 생각하면 된다.

     

      앞서 프로젝트 화면에 각 부분별로 구분되어있었는데, 그 구분은 아래와 같이 구분되어있기 때문에 QT Creator에서 SOURCES, HEADERS, FORM으로 나뉘어 표시될 수 있었다. 

     

    QT       += core gui

    greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

    CONFIG += c++11

    # You can make your code fail to compile if it uses deprecated APIs.
    # In order to do so, uncomment the following line.
    #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated ...
    SOURCES += \
        main.cpp \
        mainwindow.cpp

    HEADERS += \
        mainwindow.h

    FORMS += \
        mainwindow.ui

    # Default rules for deployment.
    qnx: target.path = /tmp/$${TARGET}/bin
    else: unix:!android: target.path = /opt/$${TARGET}/bin
    !isEmpty(target.path): INSTALLS += target

     

    2.2. Sources/main.cpp

      QT Application을 실행하기 위한 main()의 구현체이다. 리눅스든 어디든 단독으로 동작하는 모든 프로그램에는 단 하나의 main만 존재한다. Qt Creator를 통해 생성된 사용자의 클래스는 이 main()에 의해 호출된다. 물론, 예전 QT2.0나 3.0에서 처음 QT를 이용하여 단순한 응용을 개발하였을 때에는 이 main.cpp에 모든것을 기술하여 개발한 적도 있었지만 확인하고 관리하는데 더 힘들 뿐이다.

     

      어쨋든 독자들이 QtCreator를 이용하여 프로젝트를 생성할 때, HelloWorld 프로젝트 생성하고자한 Class 이름을 따로 지정하지 않았다면, 여러분들이 만들 클래스는 mainwindow라는 클래스이며, 이 mainwindow클래스는 main 함수에 의해 호출되어 실행되어진다. 정도만 이해하면 되겠다.

     

    #include "mainwindow.h"

    #include <QApplication>

    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;                   // 사용자가 만든 클래스(위젯)
        w.show();                             // 사용자가 만든 위젯을 표시(화면에 표시된다)
        return a.exec();
    }

      

    2.3. Sources/mainwindow.cpp

      독자가 프로젝트를 생성할 때 만든 클래스이다. 사용자가 만든 MainWondow클래스는 QMainWinWidow와 ui 클래스를 상속... 아니, 지금은 굳이 OOP개념이나 용어를 쓰지 않고, 가져다 쓴다라고만 생각해두자. OOP의 개념과 CPP 코딩과 관련된 부분중 연재물에서 다루지 않는 부분은 별도로 시간되면 공부하기 바란다. 

     

      그리고 가져온 ui개체의 메소드를 호출한여 화면을 구성한다. ui->setupUi(this)의 부분이다. 반대로 아랫쪽의 메소드에는 생성한 객체를 반환한다. delete ui 부분이다. 

     

      지금 당장 독자들은 이러한 부분에 대해서는 잠시 잊어두고 이렇게 생각해 두도록하자, 화면에 위젯이라는 윈도우를 출력하고, 종료시 메모리에서 제거하기 위해서는 아래 2개의 메소드(C에서는 함수라고 이야기 하는것과 유사하다.)가 필요하다. 즉, 무조건 들어가는 녀석이다.

     

    #include "mainwindow.h"
    #include "ui_mainwindow.h"

    MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) // 생성자
    {
        ui->setupUi(this);
    }

    MainWindow::~MainWindow() // 소멸자
    {
        delete ui;
    }

     

       하지만 언제 어떤 메소드가 호출되는지 정도는 알아둬야 하니까.  처음 나오는 MainWindow()는 CPP에서 생성자라 부르고, ~MainWindow()는 소멸자라 부른다. 일반적으로 ~MainWindow()를 별도로 지정하지 않아도 자동으로 처리가 되지만 가능하면 소멸자도 구현 할 것을 권한다. 말 뜻으로 간단하게 봐도 Class가 생성되면 가장 먼저 실행되는게 생성자이고, 종료되면 가장 마지막에 실행되는게 소멸자이다. 

     

    2.4. Headers/mainwindow.h

      MainWindow 클래스의 Header파일이다. Header는 CPP를 구성하는 기본 골격을 선언하는 파일이다. 따라서 mainwindow.h에 정의된데로 mainwindow.cpp에서 구현한다라고 생각하면 된다. 

     

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H

    #include <QMainWindow>

    QT_BEGIN_NAMESPACE
    namespace Ui { class MainWindow; }
    QT_END_NAMESPACE

    class MainWindow : public QMainWindow
    {
        Q_OBJECT

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

    private:
        Ui::MainWindow *ui;
    };
    #endif // MAINWINDOW_H

     

      class Mainwindow의 기본 구조이다. QT를 이용하는 애플리케이션이므로 클래스 내에 Q_OBJECT를 포함하고 있다. 그리고 public과 private는 CPP에서 나온 정보은익과 관련된 부분인데 이건 숙제로 따로 내주도록 하겠다. 처음에는 이러한 Class에서 별도로 수정할 내용은 없다. 관용적으로 쓴다고 생각하고넘어가자. 독자들이 이 헤더를 수정하기 위해 열 때에는 만들고자하는 프로그램에서 사용하는 멤버 변수가 필요한 경우 추가하는 것 이외에 직접 마구 고치는 일은 당분간 없을 것이기 때문이다. 

     

     

    2.5. UI 파일

      필자는 QT4에 대한 기억이 별로 없다. 3.x는 조금 해봤고, 4.x는 정말 쪼끔 손대봤고 이후로 안하다가 5.x에 이르렀다. 그전까지만해도 GUI를 표시하기 위해서 엄청난  헤더 타이핑을 했는데 UI객체를 사용하면서 너무심하게 편해졌다. 예를들어보면 다음과 같다.

     

    필자가 QT 3.x버전으로 개발할 때에는 화면에 텍스트에디터와 버튼 하나만 놓고 하더라도 다음과 같은 작업이 필요했다. 

    1) QtDesigner로 GUI 생성 (file.ui)

     

    2) uic 도구로 file.ui에서 class.cpp와 class.h를 생성

        클래스파일이 생성되며 내부에 디자이너에서 생성한 각 객체에 대한 변수들이 생성됨

     

        ex) 헤더
              public :
              QTextEdit* myText;
              QButton* myButton;
        이후 cpp 파일에서 new를 이용해서 생성후 좌표를 설정해주거나 해야 화면에 표시할 수 있었다.

     

    3) qproject 도구로 file.pro 파일 생성

     

    4) qmake -project 를 이용해서 Makefile 생성

     

    5) Makefile 수정(필요시)

     

    6) 프로그램 코딩

     

    7) make 명령으로 컴파일

     

      QT4인지 QT5부터인지 확실치는 않지만 기본적으로 ui객체를 사용할 수 있게 되었고, 이 UI객체를 이용하게 되면   QtCreator에서 디자인하고, 이름을 지정해준 다음 별도의 과정없이 cpp 파일에서 ui->myText, ui->myButton 형태로 접근하여 해당 객체의 멤버를 직접 제어할 수 있게 된다. 예전 3.x에 비하면 라인이 엄청나게 줄어들어 GUI를 위해서 해야할 일들이 많이 사라지게 된다. 

     

    mainwindow.ui 파일을 클릭하면 디자인 화면이 표시된다. 

    QtCreator 디자인화면

     

      아무것도 없는 디자인 화면이 표시된다. 그래서 우리가 실행했던 HelloWorld 프로젝트의 결과는 아무것도 없는 윈도우만 실행되었던 것이다. 

     

      실제 mainwindow.ui는 텍스트 에디터 등으로 열어서 확인할 수 있다. 파일탐색기에서 mainwindow.ui 파일에서 우측클릭 이후 아래의 그림과 같이 text editor로 열어보자.

    탐색기에서 Text Editor로 파일 열기

     

    그러면 xml 기반의 내용이 출력된다. 

     

    <?xml version="1.0" encoding="UTF-8"?>
    <ui version="4.0">
     <class>MainWindow</class>
     <widget class="QMainWindow" name="MainWindow">
      <property name="geometry">
       <rect>
        <x>0</x>
        <y>0</y>
        <width>800</width>
        <height>600</height>
       </rect>
      </property>
      <property name="windowTitle">
       <string>MainWindow</string>
      </property>
      <widget class="QWidget" name="centralwidget"/>
      <widget class="QMenuBar" name="menubar"/>
      <widget class="QStatusBar" name="statusbar"/>
     </widget>
     <resources/>
     <connections/>
    </ui>

     

       즉, 독자가 구현한 디자인은 xml로 ui파일로 저장되고, 해당 ui파일은 화면구성을 위한 ui 객체를 통해서 쉽게 접근할 수 있도록 제공된다라고 생각하면 되겠다. 

     

      간단하게 HelloWorld 프로젝트를 살펴봤는데, 잘 이해가 안되면 이후 코딩을 해보면서 관용적인 부분, 코딩해야 되는 부분을 직접 느끼면서 하다보면 이해가 된다. 뭐 필자도 QT를 따로 배우고 코딩을 시작한게 아니라서 몸으로 배웠는데 그게 좀더 오래 가는듯한 느낌이다. 아.. 물론, 필자가 QT를 잘한다는 이야긴 아니다. 프롤로그에 언급했듯 시키는 거 정도 하는 수준이라는거 명심하고, 자신만의 방법을 이용해서 학습하는걸 더 추천한다. 

     

    3. 과제

      가능하면 공부해 볼것을 추천한다. 코드적인 부분을 봐도 되지만 개념적인 부분이라도 이해해 두도록 하자. 

    1) OOP에 대해서 알아보자.

    2) 상속에 대해서 알아보자.

    3) 클래스는 무엇이며 어떻게 구현되는가

    4) 오버로딩과 오버라이딩에 대해서 알아보자.

     

    필자는 대충만 알고있다. 왜냐면 객체 울렁증이 있어서.. 말이다..

     

     

    반응형
    • 네이버 블러그 공유하기
    • 네이버 밴드에 공유하기
    • 페이스북 공유하기
    • 카카오스토리 공유하기