#Programming QT
###목차
- 설치: install.md
- Qt Creator: qt-creator.md
- 서브 프로젝트: subproject.md
- ui_*.h 에서 상속하기: inheritance-from-ui-class.md
- QObject
- signal and slot: signal-slot.md
- QWidget
- QDialog: widget-QDialog.md
- using gcov: using-gcov.md
#Programming QT
###목차
#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);
을 호출한다.