Qt Creator 를 실행 후 New Project 를 실행하면 아래 창을 볼수 있다.

먼저 템프릿을 첫번째인 Application(Qt)를 클릭하면 두개의 템플릿을 볼 수 있다. 나는 Widget를 다루지 않을 것이므로 간단히 콘솔기반인 두번째를 선택하여 Qt 의 핵심적이 부분에 대해서 설명할 것이다.

두번째를 선택하면 Quick 버전에 따라 창의 구성이 조금씩 달라지긴 하지만 대동 소이하다. 전부 QML을 이용한 것이고 Empty 프로젝트에 추가적인 기능을 보완한것이다. 이 정리에서 기본적인 부분을 위해 Console과 Empty 프로젝트만으로 설명하고 실무적인 부분을 설명할때 다시 추가적인 Template에 대해 설명하겠다.

  • 무엇을 정리할 것이가?

먼저 이 게시물을 클릭했다면 Qt 가 뭔지 정도는 알고 있을 것이므로 특별히 QT의 역사나 용도에 대해서는 설명하지 않겠다. 이 정리(혹은 강좌)를 통해 먼저 QML 이전에 Qt 에 대해 전반적으로 정리한 후 QML을 짚어간뒤 실무적인 부분에 생겼던 문제들에 대해서 풀어갈 것이다.

 

Qt를 이용하여 GUI를 구성하는 또다른 방법인 Widget은 다루지 않는다. 이 부분에서 한가지 이야기 하고 싶은것은 몇몇 Qt 관련 글에서 QML은  GUI가 터치 스크린을 사용하고 그래픽 효과를 많이 사용하는 안드로이드나 iOS와 같은 경우 적합하고 데스크탑에서는 C++의 Widget 방식이 더 효율적이라고 평하는 것을 보았다. 사실 전혀 동의하기 어려운게 적어도 데스크탑 개발을 하는 환경에서는 QML이 생산성면에서 그리고 GUI의 유연함에서 Widget과 비교할 바가 안된다. C#의 WPF를 보듯이 보다 진보한 GUI Toolkit은 모든 QML 과 같은 선언적 언어를 이용하고 있음 보면 알 수 있을 것이다. 

QT로 개발을 시작할 때 Widget 과 QML을 고민한다면 그냥 QML을 해라. 그것이 미래다. 아니 현재다. 학습곡선이 좀더 높다고 할 수 있지만 그래봐야 GUI Toolkit 하나 익히는 정도의 학습곡선일  뿐이다. 나중에 피눈물 흘리지 말고 그냥 QML 로 가라.

피씨의 성능이 나쁘면 Widget이 더 좋다던데요? 그 피씨의 성능 나쁘다는 기준이 한 15년전 아톰(?) 피씨 기준일 것이다. 생각해보면 황당하지 않은가 QML은 안드로이드에 적합하다더니, 아무리 후진 피씨도 안도로이드 기반보다는 몇배 이상의 성능 우위를 가질텐데 뭔가 앞뒤가 맞지 않는다. 한번 물어 봐라 QML로 문제가 될만한 피씨 사양은 어느정도인가요? 아마 어버버 할 것이다. 그리고 솔직한 사람이라면 전 위젯만 해봐서 잘 모릅니다 하겠지.

프로그램 시작할 때 좀 더 느리게 뜬다는 데요? 그거 빠르게 할 방법도 있고. 그거 약간 빠르게 하자고  Widget을 써봐야 다시 이야기 하지만 생산성면에서 비교가 안된다. 강조한다. QT를 이용하여 개발을 시작한다면 고민하지 말고 QML로 GUI를 구현하라

좀 강하게 이야기 하는 이유는 C#으로 GUI 을 구현하는 방식은 Winform 과 WPF 가 있는데 이 둘중 어떤것으로 개발해야 할까요 할때 지겹게 나오는 이유가 간단한 것을 개발하거나 성능이 떨어지는 피씨일때는 Winform이 낫습니다 라고 말하는 많이 본다는 것이다.  일단 두 프레임웍에 모두 익숙하다는 전제하에 간단한 것을 개발할때는 둘다 크게 차이가 없다. 반면 복잡한 것을 구현할때는  Winform은 불가능에 가까운 경우가 대부분이다. Winform 은 Window base control에 기반하고 있기 때문이다. 간단한 체크 박스  크기 하나 크게 만들려고 해서 별 괴랄한 방식을 써야한다. 성능 이슈도 QML과 마찬가지로 한 10년은 훌쩍 넘은 피씨가 아니라면 문제가 되지 않는다. 매번 성능나쁜  피씨 타령해서 물어보면 자기도 그렇게 들었다는게 다였다. 그리고 대개 그렇게 이야기 말했던 분들은 Winform을 오래 써와서 매우 익숙한 상태에서 WPF는 배우고 있거나 WPF의 선언적 프로그래밍 방식에 거부감이 있는 경우였다. 좀 이야기가 옆으로 셋지만 QT로 개발하려면 QML을 C#으로 개발하려면 WPF를 해라. 끝!

 

  • QT Version 과 개발환경.

2021년 5월 현재 QT는 중대한 메이저 버전이 변경되었다. 8년간의 QT5의 시대가 끝나고 QT6가 출시 되었다. 아직은 QT5로 개발해야할 일이 많은 것이므로 QT5으로 정리하고  QT5와 QT6의 차이와 마이그레이션에 대해서는 추가로 정리해보겠다.(나도 아직 모름. 공부하고 정리하겠다는 의미^^)

Qt 사이트에서 오픈 소스버전으로 5.13 이후 버전으로 받으면 이 정리를 읽으면서 따라 해보는데 어려움이 없을 것이다. 사이트 찾고 다운 받는 것은 무수히 많은 사이트에서 알려주고 있으니 다시 반복하진 않겠다. 나는 현재 5.13.0 버전과 6.1 버전 두가지를 다운 받았으며 5.13을 실무에서 활용중이고 6.1은 개인적 학습을 위한 것이다.(아까 나중에 마이그레이션 알려준다고 했으니 공부 따로 해야겠지)

 

나는 개발할때 Visual Studio를 이용하지만 정리는 Qt Creator를 이용할 것이다. Qt Creator와 Visual Studio 를 혼횽해서  사용하는 방식에 대해서도 별도 게시물로 정리하겠다. 

 

  • 독자 수준

나두 실무에서 필요한 부분만 쓰다가 한번 전반적으로 정리를 하고자 함이니 혹시나 이문서를 읽는 분들은 다음과 같다고 가정한다.

- C++, Modern C++에 대해 기본적으로 알고 있어 C++문법, 자료구조등을 알고 있어야 한다.

- 영어로 된 기술 개발 문서를 읽고 해독할 수 있어야 한다.

 

 

Do C++17을 지원하도록 각 프로젝트의 속성에서 아래와 같이 옵션을 추가하라.

/await /std:c++latest

'Language & Toolkit > C++' 카테고리의 다른 글

STL container - other containers  (0) 2019.03.10
STL container - std::list  (0) 2019.03.10
STL container - std::queue & stack  (0) 2019.03.10
STL container - std::map & set  (0) 2019.03.10
STL container - std::vector  (0) 2019.03.09

multi-set

중복 키를 허용하지만 요소를 수정할 수 없다.


multi-map

중복 키를 허용한다.


deque

Double Ended queue로 양쪽 끝에서 삽입 삭제를 허용한다.


priority-queue

자동으로 정렬되는 큐이다.

'Language & Toolkit > C++' 카테고리의 다른 글

visual studio 에서 c++17 지원  (0) 2019.05.03
STL container - std::list  (0) 2019.03.10
STL container - std::queue & stack  (0) 2019.03.10
STL container - std::map & set  (0) 2019.03.10
STL container - std::vector  (0) 2019.03.09

1. std::list 기초

양방향 연결리스트(Double Linked List)로 양쪽 끝에서 삽입 삭제가 가능하다. 따라서 reserver 같은 함수가 있을 수 없다.

operator[] 를 정의할 수 없다.

삽입과 제거에 어디든 가능하고 걸리는 시간이 상수다.


iterator insert(iterator position, const value_type& value)

position 이 가리키는 위치에 삽입.


void push_front(const value_type& value)

처음에 요소 삽입


void push_back(const value_type& value)

마지막에 요소 삽입


void pop_front()

첫번째 요소 삭제


void pop_back()

마지막 요소 삭제


iterator erase(iterator position)

position이 가리키는 요소 삭제


void remove(const value_type& value)

요소와 같은 값을 전부 삭제





'Language & Toolkit > C++' 카테고리의 다른 글

visual studio 에서 c++17 지원  (0) 2019.05.03
STL container - other containers  (0) 2019.03.10
STL container - std::queue & stack  (0) 2019.03.10
STL container - std::map & set  (0) 2019.03.10
STL container - std::vector  (0) 2019.03.09

1. queue 기초

선입선출(First-in, First-out, FIFO) 자료구조이다.


std::queue<string> myQueue;


push(const value_type& val)

요소를 추가한다.


value_type& front()

가장 처음에 삽입되었던 요소를 반환.


value_type& back()

가장 마지막에 삽입되었던 요소를 반환


pop

처음 삽입요소를 삭제한다.


size()

요소의 수를 반환한다.


empty()

queue가 비어있으면 true를 반환한다.


2. stack 기초


후입선출(Last-in, First-out, LIFO) 자료 구조이다.

push(const value_type& val)

요소를 추가한다.


value_type& top()

마지막 삽입되었던 요소를 반환.


pop

마지막 삽입요소를 삭제한다.


size()

요소의 수를 반환한다.


empty()

queue가 비어있으면 true를 반환한다.

'Language & Toolkit > C++' 카테고리의 다른 글

STL container - other containers  (0) 2019.03.10
STL container - std::list  (0) 2019.03.10
STL container - std::map & set  (0) 2019.03.10
STL container - std::vector  (0) 2019.03.09
Beginning C++17 - Chapter 7: Working with Strings  (0) 2019.02.06

1. map 기초

- key, value의 쌍 저장.

- key는 중복될 수 없다.

- 키 기준으로 binary search tree 로 자동 정렬한다.


insert

키는 중복으로 삽입할 수 없고 삽입의 결과 iterator를 반환한다.


operator[]


key 에 대응하는 값을 참조로 반환하고, 키가 없으면 새 요소를 삽입한다.


map<string, int> scoreMap;

int value = scoreMap["coco"]; 일 경우 예외가 발생하진 않으므로 안전하지 않다.


find

키를 기준으로 반복자를 검색한다. 못찾을 경우 end iterator를 반환한다.


swap

두 맵의 키와 값을 바꿔준다.


clear

전체 맵을 삭제한다.


erase

한 요소를 제거한다.


2. set 기초

map과 거의 같지만 key가 아니라 value 자체가 키가 됨으로 중복되지 않아야 한다.


3. map 활용

- 키값으로 클래스를 사용할 수 있지만 정렬을 해야함으로 operator< 연산자를 클래스에 만들어야 한다.

- 다른 사람이 만든 구조체나 클래스를 키로 사용할 경우 연산자를 재정의 할 수 없으므로 별도의 연자 구조체를 만들어야 한다.

struct Comparer

{

bool operator()(const className& left, const className& right) const

{

....

return ...

}

}

1. 기본 함수


reserve 와 resize의 차이.

reserve는 vector의 용량을 늘리는 것으로 적절한 필요 공간을 알경우 새로운 저장 공간 재할당을 막을 수 있으니 잘 사용하자.

실제 값이 할당되는 것은 아니다. 이지 크기가 더 큰 경우에는 용량을 줄여도 허용되지 않는다.


resize는 vector의 크기을 조정하는데 reserve와는 이미 값을 있는 경우에 값을 삭제해 버리니 주의해야 한다.


operator[](size_t n)

지정된 위치의 요소를 참조로 반환한다. 즉 값을 변경할 수 있다.


iterator

STL container 를 순회할 때는 반복자를 쓰는게 좋다.


for(std::vector<int>::iterator iter = scores.begin(0; iter != scores.end(); ++iter)

{

std::cout << *iter << " ";

}


루프를 거꾸로 돌 경우에는 rbegin(), rend() 를 사용한다.


insert

값을 삽입할 수 있다. 아래와 같이 하면 첫번째로 80 이 삽입된다.


std::vector<int>::iterator it = scores.begin();

it = scores.insert(it, 80);


assign

입력값을 연속으로 대입한다. 아래와 같이 하면 숫자 100 이 7개가 추가된다.


vector<int> scores;

scores.assign(7, 100);


swap

두 vector의 값을 서로 교환할 수 있다.


vector<int> scores1;

...

vector<int> scores2;

...


scores1.swap(scores2);


clear

vector를 지운다. 크기는 0이 되지만 용량은 줄이지 않는다.


erase

특정 iterator에 있는 값을 삭제한다.


*iterator

iterator 의 값을 얻을 수 있다. iterator 자체는 포인터 처럼 사용할 수 있다.


2. 사용

- vector 에 개체를 직접 보관할 경우 메모리 복사 발생 시 비용이 높아지게 됨으로 포인터를 저장하는 것이 일반적이다. 물론 이때 메모리 해제를 관리해야 한다.


vector<Score*> scores;

...


for(Score* pScore : scores)

{

delete pScore;

}


scores.cleare();


+ Recent posts