Skip to content

Instantly share code, notes, and snippets.

@onmoving
Last active December 27, 2015 11:46
Show Gist options
  • Save onmoving/4617807 to your computer and use it in GitHub Desktop.
Save onmoving/4617807 to your computer and use it in GitHub Desktop.

#ui_*.h 에서 상속하기

Qt Designer를 사용해서 생성한 *.ui 파일은 Qt User Interface Compiler에 의해 ui_*.h 파일이 생성된다. 파일 안에는 Ui_* 이름을 가지는 클래스가 생성된다.

Qt는 기본적으로 aggregation의 방법을 사용하여 이 클래스의 객체를 생성한다. 이 때 참조하는 멤버 변수는 ui로 포인터 변수이다.

이렇게 사용해도 괜찮지만 클래스를 기본 클래스로 하여 상속하는 방법을 쓰면 ui 멤버 변수를 통하지 않고서 직접 클래스의 멤버에 접근할 수 있다. 어느 방법을 쓸 지는 프로그래머의 선택이다.

예를 들어 form과 관련된 파일들이 아래와 같이 있다고 가정하자.

  • createtorrent.ui: Qt Designer로 생성된 파일이다. xml형식으로 되어있다.
  • ui_createtorrent.h: 이 파일 안에 정의 되어 있는 클래스의 이름은 Ui_TorrentCreatorDlg이다.
  • torrentcreatordlg.h: 디자인 한 폼을 사용하는 클래스 헤더 파일이다.

폼 디자인 후 아래 코드와 같이 만들어 진다.

#ifndef TORRENTCREATORDLG_H
#define TORRENTCREATORDLG_H

#include <QDialog>

namespace Ui {
  class TorrentCreatorDlg;
}

class TorrentCreatorDlg : public QDialog {
  Q_OBJECT
  
public:
  explicit TorrentCreatorDlg(QWidget *parent = 0);
  ~TorrentCreatorDlg();

private:
  Ui::TorrentCreatorDlg *ui;
};

#endif // TORRENTCREATORDLG_H
  • torrentcreatordlg.cpp: 디자인 한 폼을 사용하는 클래스 정의 파일이다.

폼 디자인 후 아래 코드와 같이 만들어 진다.

#include "torrentcreatordlg.h"
#include "ui_createtorrent.h"

TorrentCreatorDlg::TorrentCreatorDlg(QWidget *parent) :
  QDialog(parent),
  ui(new Ui::TorrentCreatorDlg)
{
  ui->setupUi(this);
}

TorrentCreatorDlg::~TorrentCreatorDlg()
{
  delete ui;
}

기본으로 만들어진 이들 파일을 aggregation이 아닌 직접 상속하는 방법으로 고쳐보자

  • 우선 ui_createtorrent.h을 열어 상속하고자 하는 클래스의 이름을 기억해 둔다. 우리의 예제에서는 클래스의 이름이 Ui_TorrentCreatorDlg 이다.
  • torrentcreatordlg.h 파일을 연다.

아래와 같이 Ui_TorrentCreatorDlg 클래스에서 상속하도록 고친다.

#ifndef TORRENTCREATORDLG_H
#define TORRENTCREATORDLG_H

#include "ui_createtorrent.h"  // 추가

class TorrentCreatorDlg : public QDialog, 
  private Ui::TorrentCreatorDlg {	// 추가
  Q_OBJECT
  
public:
  explicit TorrentCreatorDlg(QWidget *parent = 0);
  ~TorrentCreatorDlg();
};

#endif // TORRENTCREATORDLG_H

제거된 라인은 아래와 같다.

#include <QDialog>		// ui_createtorrent.h 에서 <QDialog>를 인클루드 하므로 제거한다.

// 아래 3줄도 ui_createtorrent.h에서 선언하고 있으므로 제거한다.
namespace Ui {
  class TorrentCreatorDlg;
}

// 상속하도록 Ui::torrentCreatorDlg 클래스에서 상속하므로 포인터 형식의 멤버변수인 ui는 제거한다.
private:
  Ui::TorrentCreatorDlg *ui;
  • torrentcreatordlg.cpp을 연다.

아래의 코드로 수정한다.

#include "torrentcreatordlg.h"
// #include "ui_createtorrent.h"  // torrentcreatordlg.h로 옮겼으므로 제거한다

TorrentCreatorDlg::TorrentCreatorDlg(QWidget *parent) :
  QDialog(parent)
  // ,
  // ui(new Ui::TorrentCreatorDlg) // ui멤버는 제거하여서 필요 없으므로 제거한다
{
  // ui->setupUi(this);  // ui 멤버는 제거되었다
  setupUi(this);         // 상속하였으므로 setupUi()를 직접 호출한다
}

TorrentCreatorDlg::~TorrentCreatorDlg()
{
  // delete ui;  // ui 멤버는 제거되었다
}

참고:

http://harmattan-dev.nokia.com/docs/library/html/qt4/designer-using-a-ui-file.html

qt도움말(위 url)애서는 aggregation 방법을 single inheritance를 사용하는 방법, 위에서 설명한 Ui_* 클래스에서 상속하는 방법을 multiple inheritance 방법으로 설명하고 있다.

참고: 자식 윈도우에서 segmentation error가 발생하는 경우

mainwindow에서는 aggregation 방식을 사용하고 자식 윈도우에서는 상속 방법을 사용할 경우 mainwindow에서 ui 멤버를 사용한다. 이 경우 segmentation error가 발생한다. 이 경우 mainwindow 역시 상속 방법으로 수정하면 오류가 발생하지 않는다.

#installing in fedora

##개발에 필요한 Libraries & tools 설치

$ sudo yum groupinstall "Development Tools" "Development Libraries"

##QT Createor 설치

$ sudo yum install qt-creator

##qmake를 이용한 빌드

qmake는 Makefile을 자동으로 생성하기 위한 QT 유틸리티이다.

qmake의 위치: /usr/lib/qt4/bin/qmake

$ qmake -project # .pro 생성
$ qmake 위에서생성된.pro # Makefile 생성
$ make # 실행파일 빌드
g++ -c -pipe -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fstack-protector
...
g++ -Wl,-O1 -Wl,-z,relro -o making-app main.o    -L/usr/lib -lQtGui -lQtCore -lpthread 

#Qt Creator

##단축키

  • <Ctrl>+1~7: 왼편 가장 자리의 Welcom, Edit, Design, Debug, Project, Analyze, Help 뷰간의 전환
  • <F4>: Souce와 header간의 전환 토글
  • <Shift>+<F2>: 함수의 선언과 정의 사이를 전환(Switch betwwen Method Declaration/Definition)

#signal and slot

##slot을 암시적으로 연결하기

testButton 버튼을 디자이너에서 추가 했다고 가정하자.

class TorrentCreatorDlg : public QDialog {
  Q_OBJECT

...
  
public slots:
  void on_testButton_clicked();
  
...

};

public slots:을 선언하고 on__clicked()와 같이 signal에 대한 slot을 만든다.

cpp에서 on_testButton_clicked()에 대한 정의를 추가한다.

void TorrentCreatorDlg::on_testButton_clicked()
{
  close();
}

#sub project

프로그램이 복잡해 지면서 프로젝트를 구조화 시키기 위해서 서브프로젝트가 필요해짐.

##sub project 만들기

$ mkdir <sub project name>
$ cd <sub project name>
$ touch <sub proejct name>.pri

컴파일 시 sub project의 헤더 파일들이 인클루드 될 수 있도록 아래 내용을 .pri 파일에 추가한다.

INCLUDEPATH += $$PWD

메인 프로젝트의 .pro 파일을 열어 include를 추가한다.

include(<sub project name>/<sub project name>.pri)

참고: 메인 프로젝트의 .pro 파일에서 include를 추가하면 Qt Creator를 띄어 놓은 경우(혹은 Qt Creator에서 직접 .pro 파일을 편집한 경우) 잠시 뒤 프로젝트 정보가 다시 갱신되어 프로젝트 탐색창에서 sub project 노드가 추가된 것을 확인할 수 있다.

###Qt Crator를 통한 방법: TODO

Note: 아직 Qt Creator에서 sub project인 .pri 파일을 만들고 추가하는 방법은 알아내지 못하였다.

#Using gcov

.pro 혹은 .pri 파일에서 아래의 내용을 추가한다.

QMAKE_CXXFLAGS += -fprofile-arcs -ftest-coverage
QMAKE_LFLAGS_APP += -fprofile-arcs -ftest-coverage
LIBS += -lgcov

빌드된 프로그램을 실행하고 종료하면 *.gcda와 *.gcno(qtcreator를 사용하는 경우 그 전에 생성된다) 가 만들어진다.

gcov [file_name].cpp

위 명령을 실행하면 커버리지 정보를 출력하고, *.h.gcov와 *.cpp.gcov 파일이 생긴다. 이 파일을 텍스트 편집기에서 열어 볼 수 있으며, 각 소스파일의 커버리지 정보를 표시한다.

#QDialog

##보이기 show()

화면에 QDialog 객체를 보이도록 하려면 show() 메소스를 사용한다. QDialog의 상속 객체의 생성자등에서 호출하면 객체 생성과 동시에 화면에 보이도록 할 수 있다.

TorrentCreatorDlg::TorrentCreatorDlg(QWidget *parent) :
  QDialog(parent),
  ui(new Ui::TorrentCreatorDlg)
{
  ...
  show();
}

##화면이 닫힐 때 소멸자가 호출되도록 함

상속객체에서 속성 중 Qt::WA_DeleteOnClose속성을 부여함.(Makes Qt delete this widget when the widget has accepted the close event)

TorrentCreatorDlg::TorrentCreatorDlg(QWidget *parent) :
  QDialog(parent),
  ui(new Ui::TorrentCreatorDlg)
{
  ui->setupUi(this);
  setAttribute(Qt::WA_DeleteOnClose);
  show();
}

##Modal로 보여주기

생성자에서

setModal(true);

을 호출한다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment