티스토리 뷰
이어서 같은 작업을 ui를 사용해서 하기 위해 새로 프로젝트 하나를 만들었다

그랬더니 Groupbox 경계 실선이 보인다(크기때문에 글씨 잘리는건 못잡아주네…)
그룹박스는 특별한 컴포넌트이다
위젯(전체 창) > 그룹박스(컨테이너) > 체크박스
지금은 ui로 덮기만 했으므로 연결이 되어있지 않다 (심지어 체크박스를 먼저 만들고 그룹박스를 만들었으므로, 체크박스는 위젯에 소속되고, 그룹박스 뒤쪽에 위치하므로 체크동작도 안된다)
그래서 만들 때 일반적으로 컨테이너를 먼저 만들고 그 안에 만들면 순서대로 알아서 들어간다
혹은, 그룹 ui 영역 밖에 위치 시켰다가, 다시 그룹 영역에 드래그 드롭하면 위계 설정이 가능하다


오른쪽에 property가 보인다
어제 코드로 입력했던 geometry 속성을 열어보면, 어제 입력한 것과 같이 x, y, w, h를 볼 수 있다


체크박스는 위젯 > 추상버튼 > 체크박스 소속이기 때문에, 공통 속성이 widget에 존재하고, 버튼 관련 속성은 abstractbutton에 존재한다
(배타적 작동을 위해 그룹1을 라디오 버튼으로 변경하였다)

이제 slot 연결하기 위해 go to slot…을 보면
QObject가 잇다. 모든 컴포넌트는 QObject를 상속받음
QWidget은 UI가 나타나는(눈에 보이는) 모든 컴포넌트가 있음

QObject::destroyed() : 파괴. 즉 사라질 때의 이벤트
QWidget::windowTitleChanged : 창 이름이 바뀌었다
컨텍스트메뉴: 우클릭했을 때 뜨는 이벤트
버튼::클릭/눌림/떨어짐/토글(눌려있는 버튼)


void Widget::on_radioButton_3_clicked()
{
qDebug() << "데스크탑 버튼 선택";
}
void Widget::on_checkBox_4_clicked(bool checked)
{
if(checked)
qDebug() << "프로그래밍 버튼 선택";
}
라디오 버튼과 달리, 체크박스는 인자로 bool checked가 존재한다
따라서 checked를 if에 걸어주면 선택할 때에만 동작하게 할 수 있다 (안걸어주면, 해제할 때에도 동작한다)
(그래서 라디오버튼은 체크가 되어있을 때 다시 눌러도 동작해서, 디버그에 찍힌다)
함수 이름이 규칙적인거 같은데… 그렇다면 직접 내가 on_이름_clicked()로 함수 만들면 작동할까?
(물론 Widget의 헤더에도 함수 이름을 추가해주어야 한다)

이게되네
→ 규칙을 지키면 알아서 연결해준다
이름 지키지 않고 만들고 싶은데…
일단 헤더에서는 slots에 넣으면 인식할거고 함수도 만들어놧다


연결할 수 잇도록 connect함수를 작성하면 되겠지
이번엔 ui를 만들었기 때문에 ui - >checkBox_6으로 접근할 수 있다
connect(객체이름, 이벤트 시그널, 대상, 콜백함수)로, Widget에 추가해주면 된다
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// 아래 코드 추가!
connect(ui->checkBox_6, SIGNAL(clicked()), this, SLOT(test()));
}

이제 함수 이름도 마음대로 할 수 있다
저기에 적힌 텍스트를 출력하고 싶으니까 qDebug() << “test:” << sender() - > text(); 로 고쳐본다
sender() : 이벤트를 발생시킨 객체를 리턴


내 객체는 qcheckbox*이고, sender는 qobject니까, 후손을 선조에 받는거니 문제가 없을 것 같다
후손을 선조로 보기: 업캐스팅, 자연스러움
오잉 텍스트는 위젯에 존재하는데? (오브젝트 > 위젯 > 버튼 > 체크박스)
선조를 강제로 후손으로 바꾸어서 볼 수 있도록 하기: 다운캐스팅
원래 다운캐스팅은 위험하지만, 우리는 후손을 선조로 본 상황이니까 → 다시 후손으로 보는게 괜찮다!
코드로 돌아가보면 text 호출했을 때 선조를 먼저 검사해서 바디가 있으면 선조의 text 함수를 사용할 것이고,
virtual로 선언되어있으면서 후손에 구현되어있으면 후손의 text 함수를 사용할 것이다
그래서 형변환을 명확히 하면 이렇게 된다
(형변환을 괄호로 감싸주지 않으면, - > 포인터 연산이 먼저되니까 작동이 정상적으로 안된다)
void Widget::test()
{
qDebug() << "test:" << ((QCheckBox*)sender())->text();
}
(이 형태는 Qt에서 정말 많이 쓰인다)

이걸 활용해서, sender()로 텍스트를 받아온 후 → 그 텍스트를 수정할 수 있다

(출력은 누름→뗌→누름 순으로, OS → changed → changed 출력된다)
리소스 추가
코드로 구현했던 프로젝트로 수행한다



이후 Resources 폴더와, 내부에 resources.qrc 파일이 생긴다
처음엔 전부 비어있기 때문에 Add Prefix로 분류경로를 만들어주고 (여기에서는 / 로 설정하였음),
Add Files로 파일들을 불러온다 (프로젝트명/resources/ 에 파일들을 넣어놨다)


그러면 프로젝트에서 QIcon(”경로”)로 접근할 수 있게 된다
m_exclusive[0]->setIcon(QIcon(":resources/browser.png"));

(당연히 경로 오타나면 못가져옴, 근데 문자열 내부 오타는 찾기 너무 어렵드라…. )
cmake로 만들면 코드로 ui 인식이 안되는 문제가 있었음
UI를 안써서 CMakeLists.txt에 set(오토컴파일) 3개가 없었음 (자동으로 생성되지 않았음)
CMakeLists.txt
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
윈도우에서 보안 문제로 실행이 안되는 경우가 있었음

동일한 작업을 UI 디자이너를 통해서 작성해보기

Choose file로 가져와서 바로 적용할 수 있다
(…을 누르면 내장된 아이콘을 사용한다. 역삼각형을 눌러야 저 옵션들이 뜬다)
결론: UI 디자이너에서 가져오면 코드로 안전하게 생긴다
추가적으로, 윈도우 화면 배율도 100%라면 실제 화면과 거의 같게 볼 수 있다
(그런데 나는 노트북 배율이 150%다…)
(교재에서 5장까지는 UI 디자이너 안쓰고 작업하도록 유도하고 있고, 9장은 사용하도록 한다)
코드로 작업할 때
widget.h : 사용할 애들(변수, 함수) 직접 정의
UI 작성
this : 이 컨테이너 안에 집어넣는다 라고 이해하면 편함
new로 객체를 만든다
setGeometry() 등 함수를 통해 여러 속성을 정의한다
로직
헤더에 slots 함수를 선언한다
connect(샌더객체, SIGNAL(시그널), 리시버객체, SLOT(함수))
sender: 이벤트 발생시키는 놈
SIGNAL: 이벤트 종류 미리 정의되어있음
리시버객체: this로하면 해당 객체(여기에선 위젯)의 함수를 사용
SLOT(함수): 이벤트 핸들러 함수
디자이너를 써서 UI를 분리하여 작업할 때
위와 가장 큰 차이점은, 헤더에 변수가 없음
ui 디자이너에서 따로 만들어줄 것이기 때문에, 멤버변수 ui를 통해서 가져옴
(즉, 헤더 파일 건드릴 일이 없음)
소스 파일에서도 UI세팅(+속성)과 이벤트 핸들러 연결이 알아서 추가되지만, 수동으로 추가 할 수는 있음(대부분은 안씀)
그러면 우리는 로직만 신경쓰면 된다 (심지어 함수 이름 규칙을 지키면 connect도 안해줘도 알아서 된다)
실제로 실무에선 100% 디자이너 사용함 (안쓰면 너무 노가다)
커넥트 함수는 직접 사용하는 경우가 생각보다 많음
다음시간엔 콤보박스를 소스레벨 / 디자이너 레벨에서 만들어볼 것임
(timer, thread programming까진 간단하게 다루고 xml json은 안다룸)
DB는 보통 무조건 해야하지만, 임베디드니까 안할거임
네트워크는 볼거임 (websocket, http는 안함)
멀티미디어는 opencv랑 사용법이 달라서 헷갈릴까봐안할까했는데, 간단히만 소개할 예정
(근데 이걸 5일만에 다 하는거…지..?)
그 다음 3일동안 프로젝트할거임(수준에 따라 1/2/4인으로 진행할거라 의논해볼예정)
콤보박스를 코드로 만들기 실습
cmake와 아래 설정으로 프로젝트를 새로 만들었다

폼을 안만들었으므로 ui 관련 내용이 없다

콤보박스는 이렇게 여러 아이템이 보여지는 컴포넌트이다
그래서 다른 말로는 ‘드롭다운’이라고 하기도 한다


addItem의 힌트를 통해 넣을 수 있는 인자의 종류를 볼 수 있다
이것만으로도 UI 완성했다 (심지어 선택하면 나오는 글자도 바뀐 상태로 존재해준다 기특하다)


로직을 추가하기 위해 헤더에 slot파트를, 소스에 이벤트핸들러와 connect함수를 작성한다



마우스를 올려놓거나, 혹은 Ctrl + Enter로 힌트 볼 수 잇다
(왠진모르겠지만 괄호안에 int까지 작성해줘야 함수가 작동한다…)

4개의 인덱스가 0~3으로 출력된다
clicked()와 다르게 currentIndexChanged(int)에는 인자로 int를 넘겨주엇다
그러면 connect에서 int로 지정된 애를 slot함수에 넘겨줄 수 있지 않을까?
void valueChanged(int i);
//slot함수에 int써주어야 한다
connect(combo, SIGNAL(currentIndexChanged(int)), this, SLOT(valueChanged(int)));
void Widget::valueChanged(int i) qDebug() << i;

동일하게, 다른 시그널 함수를 통해 QString 인자를 받아서 출력하는 함수를 만들 수 있다
(connect 함수 작성할 때, SIGNAL(함수)와 SLOT(함수) 로 감싸는 것을 까먹지 말자!)


똑같은 구현을 위해 QtDesigner를 사용하는 프로젝트를 만든다 (CMake)

CMakeLists.txt에 오토컴파일 구문이 안들어가있으므로 추가해준다
.ui파일을 눌러서 디자이너로 넘어와서 콤보박스를 만든다
아이템은 콤보박스를 더블클릭해서 나오는 창에서 추가(+), 삭제(-)할 수 있다

이 창에서 아이템 별 아이콘 등은 Properties에서 할 수 있다
resource에 추가하는 것은 동일하고, 빌드를 한 번 해야 인식이 되는 것을 잊지말자 ㅜㅜ
(3분 헤멨다)


이후 모든 종류를 같이 실습할 수 없으므로 각자 실습을 진행했다
Line Edit: 한 줄만 가능
Text Edit, Plain Text Edit: 여러 줄 가능
Time, Date, Date/Time Edit: 유효한 범위만 입력되는듯 (393년은 안되더라)
Dial: 계속 돌아가지 않고, 대략 7시~12시~5시 범위가 기본인듯 (바꿀수있는진 몰루?)
(Double) Spin Box: 정수를 입력받음( 소수점 처리를 위해서는 double을 사용하여야 함 )
기본 간격은 1이고, 세자리부터랑 음수는 입력이 안되는데 이건 바꿀수있겠지
Vertical / Horizontal Layout: 각 위젯을 vertical/horizontal하게 배치( 위젯 박스에 나와있는 아이콘이 너무 적절하다)
Form은… 좌우로 이름-위젯 같이, 좌우 쌍으로 정렬해주는걸 간단하게 해주는 듯



'VEDA (한화비전) > Qt' 카테고리의 다른 글
| [Qt] 5일차 - 메인윈도우, 스트림, 파일, 모델&뷰, 페인터 (0) | 2026.07.06 |
|---|---|
| [Qt] 4일차 - 시그널과 슬롯 (이벤트 처리) (0) | 2026.07.06 |
| [Qt] 3일차 - 시그널, 레이아웃, 데이터 타입/데이터 클래스/컨테이너 클래스 (0) | 2026.07.06 |
| [Qt] 1일차 - Qt 설치, make와 cmake의 개념 (0) | 2026.07.06 |
