본문 바로가기

STUDY_CS

Qt#2 Qt Creator, Qt Base Class, Signal&Slot

1. Qt Creator 

Qt 프로젝트 생성 flow

File -> New project -> Application(QT) -> QT Widgets Application(GUI어플리케이션 포함됨) -> Build System(qmake || cmake) -> QMainWindow(메인윈도우 클래스; 메뉴, 도구, 상태란 포함) & QDialog(대화창 클래스) & Widget(가시화 클래스) -> Generate form -> Translation(None) -> Kits(MacBook 6.x) -> Summary(None) 

 

Qt Creator 메인 화면

.pro: 프로젝트 파일 //설정데이터 저장 

.ui: 사용자 인터페이스 //user interface 

하단 아래 3 버튼 차례로 RUN, DEBUG, COMPILE 

qt creator 첫 화면

Qt Designer 

mainwindow.ui 클릭 -> QT Designer호출

QT Designer

왼쪽은 유닛들을 grouping 팔레트입니다. Display Widgets에서 Label 컴포넌트를 디자인 창에 Drag & Drop하여 크기를 설정하고, 텍스트 내용을 더블클릭하여 편집하여 오른쪽 하단의 속성창에 속성값을 설정할 있습니다

 

Qt Program Compile

Method1. Qt Creator에서 직접 컴파일

Method2. 터미널에서 컴파일

프로젝트 목록에서 “qmake -project” 입력 -> .pro파일 생성 

“qmake”로 컴파일, 일반적으로 .pro파일을 디폴트로 잡고 컴파일하여 makefile생성 

makefile 컴파일규칙을 포함 -> Q_OBJECT 포함하고있는 Macro 헤더파일에 moc 컴파일러를 돌림 

qt Prgroam compile 과정

Program File

프로젝트 만들 때 자동 생성되는 파일 list

.pro: 세팅값 저장 

main.cpp: main()함수 

mainwindow.ui: XML형식의 파일 

mainwindow.h: 메인윈도우 클래스 헤더파일

mainwindow.cpp: 메인윈도우 클래스 실행파일

 

자동생성되는 파일외로 직접 클래스 생성할 수 있음

직접 클래스 생성: File -> new file or project: 상속받을 base class선택(.h/.cpp파일 자동생성) 

.pro 파일 

구성: Project module (QT), 설정값 (CONFIG), 소스코드 (SOURCES), 헤더파일 (HEADERS), 윈도우파일 (FORMS)

 

QT Creator로 새파일 생성 시, .pro 자동 업데이트

직접 새파일 추가 , .pro 직접 수정

 

main.cpp

Application 생성 

QApplication는 QT의 표준 Application Class

Line7에 a정의한 것은 Application의 Object

 

Window 생성

Line8에 MainWindow Class의 변수 w정의 

 

Window 띄우기 

w.show() 사용 

 

RUN 프로그램 

a.exec() 프로그램 실행 

 

2.Qt Base Class

<Qt의 Base Class List>

QObject: 핵심 Base Class

거의 모든 QT Class와 QWidget의 Base Class

*Copy constructor사용 금함 

Signal-slot의 통신체제, 사건처리 체제, 속성과 디폴트, 메모리 관리 시스템 등 실현 

 

(*Copy Constructor: 복사생성자, C++에서 복사 생성자란 자신과 같은 클래스 타입의 다른 객체에 대한 참조(reference)를 인수로 전달받아, 그 참조를 가지고 자신을 초기화하는 방법입니다. 복사 생성자는 새롭게 생성되는 객체가 원본 객체와 같으면서도, 완전한 독립성을 가지게 해줍니다. 왜냐하면, 복사 생성자를 이용한 대입은 깊은 복사(deep copy)를 통한 값의 복사이기 때문입니다. Reference: TCP School)

 

QApplication: 사건순환

프로그램의 시작, 종결, 회화관리 처리; 시스템과 프로그램의 매개변수 설정; 윈도우 시스템과 기타 소스의 사건을 처리

Qt프로그램에서 Window의 갯수와 상관없이 QApplication의 Object는 1개이며며 기타 Object 생성전에 생성되어야함

 

QWidget: 모든 인터페이스의 Base Class

Window sender은 window시스템에서 마우스, 키보드의 입력값을 받고 화면에 자기자신을 그림 

Window sender은 button, menu, scroll bars, frame등으로 구성되며 부품끼리 서로 포함할 수 있음 

Window Object가 생설될 때, show()함수를 사용해야 보임

 

QMainWindow&QDialog: 메인윈도우/대화창 (QWidget에서 상속받음)

QMainWindow는 menu, tools, condition을 포함한 메인윈도우를 생성할 때 사용됨 

centralWidget으로 포메이팅

Qdialog: 대화창 생성 

Qt Class 구조도

프로그램 Exit & Close

프로그램 Exit: 

quit() || exit(0) //exit시 모든 윈도우 off

 

윈도우 Close:
w.close() //윈도우 닫기 

a.closeAllWindows() //프로그램 닫기

QApplication::setQuitOnLastWindowCloase(false) //윈도우는 닫고 프로그램은 살리기 

 

3. Signal&Slot

Signal&Slot: Qt사건 처리및 인터페이스의 교신을 편리하게 함 

Signal: 특정상황에 발생한 사건 (함수 호출)

Ex) 마우스 클릭:  PushButton함수 -> clicked()시그널 보냄 

Slot: signal에 응답하는 함수 

signal이 보내지면 모든 관련 slot함수 자동 실행, signal에 응담하는 것 외, 일반 함수와 같음

Public/private/protected로 정의될 수 있고 매개변수을 지닐 수 있으며 직접 호출할 수 있음 

 

Signal&Slot 연결: 다대다의 관계

QObject::connect()함수로 실현가능 (Lamda함수 사용 가능)

코드로 연결하는 방법외로 Qt Designer설정을 통해 연결 할 수 있음 

 

Ex) Qt Designer로 Signal&Slot연결하기

Q:“Hello, QT!” 생성 후, 3개의 같은 기능의 ‘닫기’실현

A: 

Method1. Designer 기존의 signal&slot 직접 연결 

 

Method2. Designer에서 드래그로 signal&slog연결 

1)메뉴에서 signal/slot 편집모드로 진입

2)sender에서 receiver 드래그 

3)signal 맞는 slot선택

4)signal&slot편집창에서 결과 확인

 

Method3. Designer+Code

1)Edit Widgets 모드에서 okButton모듈 우클릭하여 Go to slot으로 넘어감

2)slot 맞는 signal선택

3)Designer는 slot함수의 code template생성, slot에 맞는 함수 code로 수정 

.h (자동생성)

.cpp (수정)

Code 실현하는 Signal/Slot 

Signal: 

Signals;에서 정의함 

리턴값이 없음 

함수체를 채울 필요가 없음 

emit로 시그널 발송 

signal 몇개의 Slot 연결할 있음 

 

Slot:

Slots;에서 정의함

signal이 있을떄 slot실행하지만 직접 slot함수를 사용 할 수 있음

클래스의 멤버함수로 함수체가 있어야함 

멤버함수이며 가상함수, 오버로딩 가능함, public,private,protect로 다 선언가능 

모든 유형의 매개변수를 사용할 수 있고 디폴트 값을 정해 사용할 수 있음 

다수의 signal slot 연결될 있음 

 

Signal&Slot 정의:

class Student : public QObject

{

         Q_OBJECT //매크로 선언 - signal&slot유효하게 함

public:

          Student() { myMark = 0; }

          int mark() const { return myMark; }

public slots:

          void setMark(int newMark);

signals:

          void markChanged(int newMark);

private:

          int myMark;

};

 

수동 시그널 발송:

Emit markChanged(myMark); 

 

QObject::connect()함수로 signal-slot연결: 

QPushButton *btn = new QPushButton;

 

connect(btn, SIGNAL(clicked(), this, SLOT(close())); //original

connect(btn, &PushButton::clicked, this, &MainWindow::close); //Qt5 

connect(btn, &PushButton::clicked, this, [&](){ this0>close(); }); //lamda

Connect 함수 사용법 

다수 Signal - 한 개 slot 

connect(lcd, SIGNAL(overflow()),

        this, SLOT(handleMathError()));

connect(calculator, SIGNAL(divisionByZero()),

        this, SLOT(handleMathError()));

 

한 개 signal - 다수 slot 

connect(slider, SIGNAL(valueChanged(int)),

        spinBox, SLOT(setValue(int)));

connect(slider, SIGNAL(valueChanged(int)),

        this, SLOT(updateStatusBarIndicator(int)));

 

Signal 끼리 연결

connect(lineEdit, SIGNAL(textChanged(const QString &)),

        this, SIGNAL(updateRecord(const QString &)));

 

연결 해제(잘 사용하지 않음, object를 삭제하면 연결이 자동으로 해제됨) 

connect(lineEdit, SIGNAL(textChanged(const QString &)),

        this, SIGNAL(updateRecord(const QString &)));

 

Signal&Slot 매커니즘 

Signal&slot의 실행:

1)signal이 실행된 순간 slot 실행

2)signal과 slot이 같은 스레드에 없다면 slot의 실행이 지연될 수 있음(next event loop)

3)signal과 관련있는 slot함수들이 다 실행되어야 이하 코드로 넘어감 

 

signal&slot 연결 시 만족해야하는 조건:

1)Q_OBJECT 매크로 선언필요 

2)signal&slot이 같은 매개변수유형과 순서를 지켜야함 

3)signal 매개변수는 slot 매개변수로 사용될 있으며 남는 매개변수는 생략, 반대로는 성립하지 않음