티스토리 뷰
(교재 예제 공유해주심. Qt구버전이라 호환되지 않을수 있음)
QMainWindow
widget보다 복잡한 구성을 UI 구현하기 위해 사용

title bar
menu bar
tool bar
dock widget: 상하좌우에 달라붙는거
status bar
MDI(Multi Document Interface)는, QMainWindow에 QMdiArea 클래스를 사용하여 만들 수 있다
남이 만든 프로젝트를 가져왔을 때, (운이 좋다면 문제없겠지만) 개발 환경을 맞추는 것이 시작이다

경로 한글 없애고 cmake 다시 실행, 프로젝트 다시 빌드해도 여전히 발생한다


캐시 이미 만들었으니 다른 디렉토리에서 cmake re-run하라고 한다
근데 폴더 바꾸기 싫은데? 프로젝트 폴더 내부로 들어가본다
C:\Qt\Projects\downloaded_examples\ch12\00_MDIMainWindow\build\Desktop_Qt_6_11_0_MinGW_64_bit-Debug
캐시 어쩌구파일이 보인다. 역시 이전에 있던 한글 경로가남아있다 (prev에도 역시 있다)
따라서 두 파일을 모두 휴지통으로 여행보내고 cmake run을하면?
프로젝트가 제대로 실행된다

new Action으로 아이콘과 &New로 생김.
숏컷(단축키 연결
스테이터스팁: 팁을 보여줘라
conenct: 뉴액트에서 트리거 시그널 발생하면 → 이 객체의 newFile을 해라
(액션 트리거: 어떠한 동작의 시발점)


(실제론 qDebug 위치에 파일 다이얼로그 열어서 위치 찾거나 등등 하면 되겠지)
dockwidget을 사용해서, 좌/우에 붙일 수 있게 하는 코드(보통은 상하좌우긴함)
QDockWidget *dock = new QDockWidget(tr("Target"), this); dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);

리스트 아이템 추가하고, dock에 리스트 위젯을 추가한다
그리고 dock을 MainWindow의 오른쪽에 붙여둔다
메뉴바랑 툴바는 결국 같음. 메뉴바에 계층적으로 기능 만들어두고, 자주쓰는걸 툴바에 배치하면 됨
(=메뉴바 먼저 만들고 툴바 만들기)
가운데 위치하는게 CentralWidget
setCentralWidget(new MDIMainWindow());
메인윈도우 다 봤으니 MDI윈도우로 넘어간다


setGeometry 대신 resize가 사용되었다
실습: newFile 하면 서브윈도우로 윈도우 띄우기

리시버를 MDIwin으로 하니까, newFile이 자동으로 MDIMainWindow를 찾아간다
(명시적으로 써봤더니 두 번 가려고 해서 오류났엇다)

area→show()가 아니라 뉴서브윈도우를 보여줘야 한다!!!!!!!!
내 직관이랑 달라서 삽질함…
나는 slots에 등록해서 시그널로 수행
cf. MDI객체가 이름이 없어서 멤버변수로 뺐는데, 안빼도 가능하다..>!
(생각보다 자주쓰는 방법임)
setCentralWidget(new MDIMainWindow);
다운캐스팅을 이용하면 됨 (원래는 위험해서 컴파일러가 허락 안하지만, 진짜로 있는 것을 아니까 우리가 명시적으로 할 수 있음)
MDIMainWindow *main = (MDIMainWindow*)this→centralWidget();
main→createNewWindow(); // 나는 newFile로 만든 함수
마찬가지로 (area=new QMdiArea, setCentralWidget(area)인 상황)에서
void MDIMainWindow::createNewWindow(){
QMdiSubWindow* subWindow = new QMdiSubWindow();
subWindow→resize(100, 100);
((QMdiArea*)centralWidget())→addSubWindow(subWindow);
subWindow→show();
// 일반적으로는 ((MDIMainWindow*)centralWidget())→createNewWindow();
의문… 그러면 왜 area를 함수 내 로컬변수로 한거지? 함수에서 쓰고 버리는게 아니라, mdiwindow객체에서 계속 관리하는거 아닌가? (⇒ 멤버변수와 로컬변수로 지정하는 기준…이 궁금)
마즘. 재활용할거면 멤버변수로 바꾸는거임
재활용 안할거면? 로컬변수로 두는거
Stream
당연히 text / byte로잇고, text는 형변환/인코딩 주의해야한다
텍스트만 쓸때는 변환을 생략할 수 있으므로 qtextstream이 편하다
QByteArray encoding()
{
quint32 value1 = 123;
quint8 value2 = 124;
quint32 value3 = 125;
QByteArray outData;
QDataStream outStream(&outData, QIODevice::WriteOnly);
outStream << value1;
13. Stream예수님은 당신을 사랑합니다.
페이지 157 13. Stream
outStream << value2;
outStream << value3;
qDebug() << "outData size : " << outData.size() << " Bytes";
return outData;
}
void decoding(QByteArray _data)
{
QByteArray inData = _data;
quint32 inValue1 = 0;
quint8 inValue2 = 0;
quint32 inValue3 = 0;
QDataStream inStream(&inData, QIODevice::ReadOnly);
inStream >> inValue1; // 123
inStream >> inValue2; // 124
inStream >> inValue3; // 125
qDebug("[First : %d] [Second : %d] [Third : %d]"
, inValue1, inValue2, inValue3 );
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QByteArray encData = encoding();
decoding(encData);
return a.exec();
}
c.f.)
explicit: 생성자에서 많이 보이는 키워드. 명시적이라는 뜻
이 생성자에서는 묵시적인 형변환을 지원하지 않겠습니다 → 상속받은애들만 형변환 가능
파일 입출력
일반적으로는 i/o스트림을 사용하는 것이 좋다(특히 큰 파일을 다룰 때에는 buffer가 필요함)
(뭐가 버퍼가 있고 좋다고 설명하시는건지 모르겠어서 검색함)

그렇다고 한다
그럼 file클래스는 왜필요함? FAT 관련 작업용
이름 바꾸기, 삭제 등은 바로 하는 것이 아니라, fat테이블 상에서만 바꾸어서 원본 파일은 유지하기 때문
toInt() 같은 변환 함수는 많이 나옴
c에서는 atoi(문자열 주소); (아스키 to int라는 뜻)
c++부터는 .toInt32(); 등의 객체 함수를 사용함 (따라서 함수에 인자 안넘겨주게됨)
Qt Property (매크로)
getter setter를 편하게 쓸 수 있게 하는 시스템임
(C++에서 제공하는 property랑 비슷하다고 하는데 안해봐서 몰루)


(setProperty() / (get없이) property()로 사용)
강사님 개인적으로는 property를 선호하지 않음 (쓰는사람은 잘 쓴다고 함)
Model & View
MVC 아키텍쳐를 구현하기 위함
QListWidget, QTableWidget, … : 모델과 뷰를 구분하지 않음 (직접 조작)
QListView, QTableView, … : 데이터를 관리하는 ‘모델’을 지정함 (UI와 Data 분리)
(엥 그럼 ui designer랑은 관계가 어캐되는거지)
나중엔 결국 데이터 관리 로직과, 화면 표시 로직을 분리하게 되니까 모델 뷰를 사용하게 될 것
(근데 프로젝트로 하면 거의 위젯쓰게될거임 편하자너,,,)
그래서 보통 커스텀 리스트뷰 등을 만들어서 쓸 때 모델-뷰를 사용하고,
아닌 경우는 기존 리스트 위젯을 사용한다
데이터를 바꾸(고 업데이트 시그널을 보내)면, 연결된 모든 뷰의 모습이 바뀐다

delegate: 위임이라는 뜻
간접적으로 호출 (실제로는 virtual function pointer로 만듦)

이 중 일반적으로 많이 쓰는건 stringlistmodel
db연동하면 sqlquery/tablemodel도 많이 씀
모델과 뷰는 이렇게 연결할 수 있다


순서대로 QListView, QTableView, QTreeView를 사용하는 것이 좋다

ui designer를 가보면 좌측 위젯 박스에 widget과 view 그룹이 존재한다
뷰-모델 예제파일 보기 (ch14\01_ListView)

실습: 버튼 두 개(Add, Remove)를 아래에 추가
Add를 누르면 밑에 추가, Remove를 누르면 위부터 삭제
listview에서 원하는 아이템을 클릭하면 레이블 갱신
(데이터를 바꾸면 내부에서 알아서 뷰 갱신시켜줌)
// SLOTS
void Widget::changeLabel(QModelIndex idx){
// view에서 모델을 가져오고, 다운캐스팅
QStringListModel *model = (QStringListModel*)view->model();
QString str = model->data(idx, Qt::DisplayRole).toString();
lbl->setText(str);
}
void Widget::addItem(){
// 엥 다운캐스팅 안해도되네
// insertRow()는 QAbstractModel에 있기 때문에!
view->model()->insertRow(0);
}
void Widget::removeItem(){
view->model()->removeRow(0);
}
QPainter (2D 그래픽스)
paintEvent 가상함수를 override해서 사용할 수 있다
#include <QPainter>
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
void paintEvent(QPaintEvent *event) override;
};
paintEvent 함수에서, QPainter.begin()부터 end()까지의 사이에 있는 코드로 2D 그림을 그린다
창 변형이 일어날 때 자동으로 호출되나, 명시적으로 사용하여야 할때에는 paintEvent함수를 호출하는 대신, update()를 사용하여야 한다
main부터 다시본다
복습: c++에서는 기본이 static binding이니까 virtual 키워드가 있어야 실행 시 타입에 맞추어서 실행된다
exec() : wmquit (window message quit 할때까지 무한루프 돌겟다)
show(): 화면을 띄우겠다 (모든 위젯은 show로 화면에 나옴)
(다이얼로그는 show 로 하면 리턴을 못받으니까 exec을 사용했다)
나는 만든 위젯들에 대해 show를 안했는데, 만든 것들이 떳다
→ 메인 컨테이너에서 show를 하면 아래는 모두 show 된다
MDI에서는 show 썼는데요?
→ 생성자끝나서 이미 show했는데, 또 출력하려고 하면 show 해줘야지
사실? show하면 내부적으로 paintEvent를 호출하는 것
c.f. cpp에 include랑 h에 include가 다른가?
사실 거의 차이 없음.
h에서 가져오면 cpp에서 안해도 쓸 수 있다
h에 몰아놓는게 일반적
(최적화하는사람들은 h에 쓰는거만 두고, cpp에서 필요하면 cpp에서 include하라고 하기도 한다고 함)

버튼과 그림이 겹쳐서 나오고, 자세히 보면 선이 밑에 있고 버튼이 위에 있다
→paintEvent 그린 뒤에 생성자 그린다
begin(this)
→ 위젯마다 페인터 만들어서 그리는게 좋다
다음주 월화수는 실습
사흘간 오전 1~2시간정도는 수업 예정 (쓰레드는 무조건 하고, json/xml 중 하나, 통신)
(이 수업 내용은 프로젝트 평가에 들어가지 않음. 실무에서 많이 쓰니까)
나머지 시간엔 미니 프로젝트
2인 1팀. (시험 점수 기준 반반으로 팀원 지정, 점수는 동일, 자신의 역할&기여도 보고서 작성…인데 차이가 커도 감점요인 )
데이터파일을 쓸수있으면 쓰는게 좋음 (file io, stream)
CRUD 가능 (저장: file&stream or json (DB는 안할거니까 빼셈))
외부리소스: 기본 기능 이외의 추가적인 기능…인데 추가 점수에 목숨걸지마세요
물론 코드 가독성도 포함임!!!!!
'VEDA (한화비전) > Qt' 카테고리의 다른 글
| [Qt] 4일차 - 시그널과 슬롯 (이벤트 처리) (0) | 2026.07.06 |
|---|---|
| [Qt] 3일차 - 시그널, 레이아웃, 데이터 타입/데이터 클래스/컨테이너 클래스 (0) | 2026.07.06 |
| [Qt] 2일차 - 위젯, Qt디자이너 (0) | 2026.07.06 |
| [Qt] 1일차 - Qt 설치, make와 cmake의 개념 (0) | 2026.07.06 |
