QT 란?
QT는 MS윈도우, 리눅스 그리고 MacOs와 같은 데스크탑 기반 운영체제에서 어플리케이션을 개발하기 위해 동일한 개발 프레임워크를 제공하는 기본언어 C++로 하는 GUI제작 크로스 플랫폼 프레임 워크 입니다.
** 라이브러리 와 프레임워크 차이점
[라이브러리]
"개발자가 특정 기능을 구현할 때 필요한 함수나 클래스를 라이브러리에서 호출하여 사용합니다."
- 정의: 라이브러리는 특정 작업을 쉽게 처리할 수 있도록 미리 작성된 코드의 모음입니다. 개발자는 필요할 때 이 라이브러리에서 기능을 호출하여 사용할 수 있습니다.
- 사용 방식: 개발자가 필요한 부분에서 라이브러리의 기능을 직접 호출합니다. 즉, 개발자가 제어를 가지고, 필요할 때 원하는 기능을 끌어다 쓰는 방식입니다.
[프레임워크]
"프레임워크는 애플리케이션의 기본적인 동작 방식을 제공하며, 개발자는 그 안에서 필요한 기능을 추가로 구현하는 형태입니다."
- 정의: 프레임워크는 전체 애플리케이션 구조를 잡아주고, 그 구조 안에서 개발자가 코드를 작성할 수 있도록 도와줍니다. 프레임워크는 일종의 틀을 제공하며, 그 틀 안에서 개발해야 합니다.
- 사용 방식: 프레임워크는 자체적으로 흐름을 제어하며, 개발자는 프레임워크가 정해준 구조 안에서 특정 부분만 구현합니다. 즉, 개발자는 프레임워크의 규칙을 따라야 하며, 프레임워크가 제어의 주도권을 가지고 있습니다.
주요 차이점
"정리하자면, 라이브러리는 개발자가 필요할 때 가져다 쓰는 도구이고, 프레임워크는 큰 틀을 제공하여 그 틀 안에서 개발자가 동작하는 방식입니다."
- 제어의 흐름 (Inversion of Control):
- 라이브러리는 개발자가 제어를 하며 필요한 기능을 호출.
- 프레임워크는 프레임워크가 제어를 하며, 개발자는 그 안에 코드를 작성.
- 사용 방식:
- 라이브러리는 개발자가 필요한 시점에 호출하여 사용.
- 프레임워크는 전체 애플리케이션 구조를 잡아주며 그 안에서 개발.
3. CMake / 4. QMake
CMake
CMake는 프로젝트를 쉽게 빌드하기 위해서 제공하는 틀이다. 구현한 소스코드를 쉽게 빌드해 실행파일을 만드는 기능을 제공한다.
CMakeList.txt 파일이 만들어지는데 CMakeList.txt는 이프로젝트의 빌드하기 위한 프로젝트 파일이다.
[Console 에서 CMakeList.txt]
cmake_minimum_required(VERSION 3.16)
project(console_test LANGUAGES CXX)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core)
add_executable(console_test
main.cpp
# 파일 여러개 있을 경우 추가해놓는곳
)
target_link_libraries(console_test Qt${QT_VERSION_MAJOR}::Core)
include(GNUInstallDirs)
install(TARGETS console_test
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
project(ConsoleApplication LANGUAGES CXX)
=> 프로젝트의 이름과 사용된 언어가 C++ 언어임을 명시한다.
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
=> 첫번째 라인은 C++17 버전 이상을 사용하겠다는 뜻이다.
=> 두번째 라인은 만약 C++버전이 너무 오래된 컴파일이면 오류를 출력하라는 뜻이다.
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core)
target_link_libraries(ConsoleApplication Qt${QT_VERSION_MAJOR}::Core)
=> 위의 소스코드는 Qt에서 사용할 모듈이 명시한다. Qt는 다양한 모듈로 구성되어있다.
add_executable(ConsoleApplication
main.cpp
)
=> 프로젝트에서 추가할 소스코드 파일 명시하면 된다.
#include <QCoreApplication>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qDebug("Hello world.");
return a.exec();
}
=> 응용 어플리케이션 Console 이므로 QCoreApplicate이지만 만약, GUI 기반 어플리케이션인 경우 " QGuiApplication"를 사용해야한다.
=> qDebug( )는 메시지를 출력한다.
=> 마지막 라인은 프로그램이 종료되지 않도록 해주는 역할을 한다.
[GUI 어플리케이션 에서 CMakeList.txt]
cmake_minimum_required(VERSION 3.16)
project(cmake_app VERSION 0.1 LANGUAGES CXX)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets)
set(PROJECT_SOURCES
main.cpp
widget.cpp
widget.h
widget.ui
)
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
qt_add_executable(cmake_app
MANUAL_FINALIZATION
${PROJECT_SOURCES}
)
# Define target properties for Android with Qt 6 as:
# set_property(TARGET cmake_app APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
# ${CMAKE_CURRENT_SOURCE_DIR}/android)
# For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation
else()
if(ANDROID)
add_library(cmake_app SHARED
${PROJECT_SOURCES}
)
# Define properties for Android with Qt 5 after find_package() calls as:
# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
else()
add_executable(cmake_app
${PROJECT_SOURCES}
)
endif()
endif()
target_link_libraries(cmake_app PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
# If you are developing for iOS or macOS you should consider setting an
# explicit, fixed bundle identifier manually though.
if(${QT_VERSION} VERSION_LESS 6.1.0)
set(BUNDLE_ID_OPTION MACOSX_BUNDLE_GUI_IDENTIFIER com.example.cmake_app)
endif()
set_target_properties(cmake_app PROPERTIES
${BUNDLE_ID_OPTION}
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
MACOSX_BUNDLE TRUE
WIN32_EXECUTABLE TRUE
)
include(GNUInstallDirs)
install(TARGETS cmake_app
BUNDLE DESTINATION .
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
if(QT_VERSION_MAJOR EQUAL 6)
qt_finalize_executable(cmake_app)
endif()
project(GuiApplication VERSION 0.1 LANGUAGES CXX)
=> Console에서는 버전 정보가없지만, 위에서 보는 것과 같이 버전 정보를 직접 명시할 수 있다.
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
=> CMAKE_AUTOUIC는 Qt의 uic(Qt User Interface Compiler)파일을 자동으로 생성하라는 문구이다.
예를들어, 이 문구가 없으면 Qt가 자동으로 생성해주는 파일이 있는데 그 중에서 확장자가 .ui인 XML 포맷의 UI 파일의 소스코드를 자동으로 생성해 주지 않는다.
=> CMAKE_AUTOMOC는 moc(Meta Object Compiler) 파일을 자동으로 생성해준다. 그리고 CMAKE_AUTORCC는 리소스파일을 자동으로 생성해준다.
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
qt_add_executable(GuiApplication
MANUAL_FINALIZATION
${PROJECT_SOURCES}
)
else()
if(ANDROID)
add_library(GuiApplication SHARED
${PROJECT_SOURCES}
)
else()
add_executable(GuiApplication
${PROJECT_SOURCES}
)
endif()
endif()
=> CMake에서는 if문을 사용할 수 있다. 위의 소스코드는 Qt 버전이 6 이상인 경우 괄호 안에 내용을 실행하라는 문구이며 그렇지 않고, 만약 플랫폼이 Android 이면 괄호안에 내용을 실행한다. 그렇지 않으면 else( ) 의 괄호 안에 내용을 실행하라는 뜻이다.
=> add_library( )는 라이브러리를 만들기 위해 사용한다.
예를들어, 프로젝트를 생성할 때 실행할 수 있는 응용 어플리케이션 인지, 라이브러리인지 정의 할 수 있다. 여기"add_library( )"는 라이브러리 프로젝트를 만들 때 사용한다. 그리고 "add_executable( )" 함수는 실행 가능한 어플리케이션을 만들 때 사용한다.
[main.cpp]
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w; // widget 클래스 추가
w.show(); // widget 클래스 show() 메서드 실행
return a.exec();
}
[widget.h]
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
=> ui_widget.h라는 uic 확장자가 .ui 인 파일을 기반으로 자동으로 소스코드를 변환해 ui_widget.h 파일을 만들어준다.
여기서 단순히 QLabel을 사용했지만 나중에 복잡한 GUI를 만들고 해당 이벤트를 처리해주면 된다.
예를들어, GUI 상에서 버튼을 배치하고 버튼을 처리하는 함수를 Widget클래스 상에서 처리하는 함수를 만들면 된다.
QMake
- Qt에서 제공하는 qmake는 프로젝트 빌드하기 위해서 제공하는 틀이다. 프로젝트에 소스코드 외에도 이미지 파일, 설정파일, uic, moc 등 파일들이 있다. 이러한 파일들을 쉽게 빌드할 수 있는 틀이다.
- Debug 모드로 빌드 할 때 또는 Release 모드로 빌드할 때 어떤 특징을 조건으로 설정할 수 있다.
- qmake는 확장자가 .pro 이며 파일명은 프로젝트 이름을 사용한다.
[Console 에서 qmake.pro]
QT = core
CONFIG += c++17 cmdline
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000
#
disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
=> QT 키워드로 시작하는 부분은 이 프로젝트 Console기반의 어플리케이션만 사용할 경우 core 모듈만 프로젝트에 포함 시키라는 뜻이다. QT는 제공하는 라이브러리가 모듈별로 나눠져 있다.
예를들어, 네트워크 API 또는 라이브러리를 사용하기 위해서는 QT키워드에 network 모듈을 아래와같이 추가해야한다.
QT = core
QT += network
CONFIG += c++17 cmdline
=> "C++17" 은 사용할 C++ 버전이 17버전을 사요하겠다는 뜻
=> cmdline은 Console 어플리케이션일 경우를 뜻한다. 이 옵션은 모든 플랫폼에서 사용할 수 있다.
이 방법 이외에 "MS윈도우에서는 CONFIG += console"을 사용할 수 있고, "MacOS에서 는 CONFIG -= app_bundle"을 사용할 수 있다.
CONFIG += opengl
=> CONFIG는 미리 정의된 변수들 이외에도 사용자 직접 변수처럼 지정해 사용할 수 있다. 예를 들어 위와 같이 opengl 이라는 변수를 사용자가 선언해 사용할 경우 위와 같이 사용할 수 있다.
opengl {
TARGET = application-gl
} else {
TARGET = application
}
=> opengl 이라는 변수를 CONFIG에 등록하고 위와 같이 특정 조건일 경우 사용할 수 있다.
SOURCES += \
MyCode.cpp \
main.cpp
HEADERS += \
MyCode.h
=> SOURCE 키워드는 소스코드를 명시한다. 여기서는 소스코드 main.cpp만 존재하기 때문에 SOURCE 키워드에 main.cpp만 있다. 예를들어, 헤더파일과 소스파일이 더 생긴다면 SOURCE 와 HEADER 코드에 MyCode.h 와 MyCode.cpp 소스코드 파일명이 추가 된다.
=> 위의 소스에서 Back Slash ("\") 문자는 줄 바꿈(New Line) 을 하라는 뜻이다.
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
=> “qnx" 키워드는 플랫폼이 QNX 인 경우를 뜻한다. target.path 는 빌드 된 실행파일이 위치할 디렉토리이다.
=> 그리고 프로젝트파일에서는 if 문과 같은 분기 문을 사용할 수 있다. else 는 만약 QNX플랫폼이 아니라면 이라는 뜻이고 unix:!android: 는 플랫폼이 리눅스 이고 안드로이드 플랫폼이 아닌 경우 빌드 된 실행 파일 위치를 뜻한다. TARGET 변수는 프로젝트의 실행파일명을 뜻한다.
[GUI 어플리케이션 에서 qmake.pro]
Qt Designer 툴로 배치한 Widget들의 위치 및 특성 정보를 widget.ui 파일에 저장한다. 파일의 형식은 XML이다.
이 파일은 나중에 컴파일 시, Qt가 자동으로 C++ 소스코드로 변환해 준다.
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private:
Ui::Widget *ui;
private slots:
void slot_clicked();
};
#endif // WIDGET_H
=> 위의 소스코드에서 보는 것과 같이 slot_clicked( ) 함수를 작성하고 widget.cpp 에서 이 Slot 함수의 구현 부를 아래와 같이 작성한다.
[widget.cpp]
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
connect(ui->pushButton, SIGNAL(clicked()) , this, SLOT(slot_clicked()));
}
Widget::~Widget()
{
delete ui;
}
void Widget::slot_clicked()
{
qDebug()<< "Hello world";
}
=> 위의 소스코드에서 보는 것과 같이 slot_clicked( ) 함수를 작성하고 widget.cpp 에서 이 Slot 함수의 구현 부를 아래와 같이 작성한다.이 함수에서는 “Hello world” 를 출력하기 위해서 Qt 에서 제공하는 함수를 사용해 보자. widget.cpp 파일 상단에 QDebug 헤더를 include 한다. 그리고 slot_clicked( ) 함수상에 “Hello world”를 출력하는 소스코드이다.
void Widget::slot_clicked()
{
qDebug() << "Hello world";
}
=> 마지막으로 버튼을 클릭했을 때 slot_clicked( )함수를 호출하기 위해서는 connect( )함수를 이용해 시그널(이벤트)과 Slot함수인 slot_clicked( ) 함수를 연결한다.
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(slot_clicked()));
}
=> 위의 connect( ) 함수의 첫 번째 인자는 시그널을 발생하는 오브젝트이다. 이 오브젝트의 고유한 이름은 Qt Designer 에서 정의하였다.
=> 두 번째 인자는 시그널을 발생하는 종류이다. 클릭, 더블 클릭, 클릭 후 해제 했을 때 등 여러 개의 시그널이 존재한다.
여기서는 이 버튼을 클릭했을 때 발생하는 시그널을 명시한다. 세 번째 인자는 이 시그널과 연결할 Slot 함수가 있는 인스턴스명을 입력한다. 여기서는 자기 자신을 명시하기 때문에 this 을 입력하였다. 마지막인자는 호출 할 Slot 함수를 명시한다. 여기서는
slot_clicked( ) 함수를 명시한다.
Cmake 와 qmake 차이점
- CMake: 여러 플랫폼과 컴파일러를 지원하는 범용적인 빌드 시스템입니다. Linux, macOS, Windows 등 다양한 운영체제에서 사용할 수 있으며, Visual Studio, GCC, Clang 등 다양한 컴파일러를 지원합니다.
- QMake: 주로 Qt 프레임워크를 사용하는 C++ 프로젝트를 위해 개발된 도구입니다. 여러 플랫폼에서 사용할 수 있지만, Qt 개발 환경에 최적화되어 있어 Qt 프로젝트를 다룰 때 특히 유용합니다.
2. 사용 목적
- CMake: Qt 외에도 다양한 프로젝트에서 사용할 수 있는 범용 빌드 시스템입니다. C++, C, Fortran 등 여러 언어를 지원하며, 다양한 프로젝트에서 널리 사용됩니다.
- QMake: Qt 프로젝트를 위한 빌드 시스템으로, Qt 위젯, QtQuick 등을 사용하는 애플리케이션 개발에 최적화되어 있습니다. Qt를 사용할 때 빌드 설정을 간소화해 주지만, 비-Qt 프로젝트에서는 그리 많이 사용되지 않습니다.
- CMake는 범용적인 빌드 시스템으로 여러 플랫폼과 언어에서 사용 가능하며, 다양한 옵션과 확장성을 제공합니다.
- QMake는 Qt 프로젝트에 특화된 빌드 시스템으로, Qt 개발 환경을 간편하게 설정할 수 있지만, 그 외의 프로젝트에서는 덜 사용됩니다.
5. QT GUI Widgets
[widget.h]
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QCheckBox>
#include <QButtonGroup>
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private:
QButtonGroup *m_chk_group[2];
QCheckBox *m_exclusive[3];
QCheckBox *m_non_exclusive[3];
// QButtonGroup과 QCheckBox 오브젝트를 선언한다.
private:
void slot_chkChanged();
// 시그널(이벤트)을 처리할 slot_chkChanged( )함수를 선언한다.
//Slot 함수는 QCheckBox에서 발생한 시그널을 처리하는 함수이다. Slot 함수를 선언하기 위해서는
//접근 제한자(private 또는 public) 과 “slots” 라는 키워드를 선언해야 한다.
};
#endif // WIDGET_H
[widget.cpp]
#include "widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
QString str1[3] = {"Game", "Office", "Develop"};
// 출력 시 왼쪽에 보이는 QButtonGroup
QString str2[3] = {"P&rogramming", "Q&t", "O&S"};
// 출력 시 오른쪽에 보이는 QButtonGroup
int xpos = 30;
int ypos = 30;
//xpos, ypos는 체크박스가 화면에 배치될 좌표입니다.
m_chk_group[0] = new QButtonGroup(this);
// 왼쪽 체크박스 그룹을 관리하는 QButtonGroup객체 생성
m_chk_group[1] = new QButtonGroup(this);
// 오른쪽 체크박스 그룹을 관리하는 QButtonGroup객체 생성
for(int i = 0 ; i < 3 ; i++)
{
m_exclusive[i] = new QCheckBox(str1[i], this);
// 왼쪽 체크박스들을 담는다.
m_exclusive[i]->setGeometry(xpos, ypos, 120, 30);
// QCheckBox의 메서드 setGeometry를 사용하여 위치를 설정합니다.
// xpos:x축 좌표 , ypos:y축 좌표 지정해 위젯 위치를 설정
m_chk_group[0]->addButton(m_exclusive[i]);
// 왼쪽 QButtonGroup으로 해당 체크박스를 m_chk_group[0]에 추가하여 그룹의 일부로 만듭니다.
// 이 코드로 인해 m_exclusive[] 배열의 세 개의 체크박스가 모두 m_chk_group[0]이라는 그룹에 추가됩니다.
// 그룹화된 버튼들은 해당 그룹에서 설정한 규칙에 따라 상호작용하게 됩니다.
// 이 경우, m_chk_group[0]->setExclusive(false);로 설정되어 다중 선택이 가능한 체크박스 그룹으로 동작하게 됩니다.
m_non_exclusive[i] = new QCheckBox(str2[i], this);
// 오른쪽 체크박스들을 담는다.
m_non_exclusive[i]->setGeometry(xpos + 120, ypos, 120, 30);
// xpos + 120은 오른쪽으로 120픽셀 떨어진 위치에 배치된다.
// ypos는 기존 y좌표값을 사용합니다.
// 120, 30: 이값은 체크박스의 너비 (120픽셀)와 높이(30픽셀)를 의미합니다.
// m_non_exclusive에 속한 체크박스를 화면의 오른쪽 120픽셀이동 배치하라는 뜻
m_chk_group[1]->addButton(m_non_exclusive[i]);
connect(m_exclusive[i], SIGNAL(clicked()), this,SLOT(slot_chkChanged ()));
// connect()는 Qt에서 신호와 슬롯을 연결하는 함수입니다. 여기서 특정 이벤트(신호)가 발생할 때 해당하는 처리 함수(슬롯)를 호출합니다.
ypos += 40;
// 각 체크박스를 아래로 40픽셀씩 떨어뜨려 배치합니다.
}
// setExclusive()함수에서 첫번째 인자를 넘겨주면 다중 선택이 가능하거나 불가능하게 처리할 수 있다.
// false를 사용하면 다중 선택이 가능하며 true를 사용하면 다중선택이 불가능하다.
m_chk_group[0]->setExclusive(false);
// 왼쪽의 QCheckBox 항목은 다중선택이 가능
m_chk_group[1]->setExclusive(true);
// 오른쪽의 QCheckBox 항목은 다중선택이 불가능
}
void Widget::slot_chkChanged()
{
// 체크박스가 선택되었을 때, checkState()로 해당 체크박스의 상태를 확인하고,
// 선택된 항목의 인덱스를 qDebug()로 출력합니다.
for(int i = 0 ; i < 3 ; i++) {
if(m_exclusive[i]->checkState())
// 모든 왼쪽의 체크박스 상태를 확인하여 체크된 항목을 출력
{
qDebug("checkbox %d selected ", i+1);
// 체크된 체크박스의 번호를 출력
}
}
}
Widget::~Widget()
{
}
QButtonGroup의 역할
QButtonGroup은 여러 버튼(QCheckBox, QRadioButton 등)을 하나의 그룹으로 묶어 관리할 수 있는 클래스입니다. addButton() 함수는 해당 버튼을 그룹에 추가해주는 기능을 합니다. 그룹에 포함된 버튼들은 일반적으로 독립적인 개별 버튼이 아니라, 그룹 내에서 상호작용할 수 있게 설정됩니다. 예를 들어, 하나의 버튼을 선택하면 다른 버튼이 자동으로 선택 해제되는 등의 동작을 쉽게 구현할 수 있습니다.
connect(m_exclusive[i], SIGNAL(clicked()), this, SLOT(slot_chkChanged()));
- connect()는 Qt에서 신호와 슬롯을 연결하는 함수입니다. 여기서 특정 이벤트(신호)가 발생할 때 해당하는 처리 함수(슬롯)를 호출합니다.
- m_exclusive[i]: 왼쪽에 있는 체크박스 배열 중 하나를 의미합니다.
- SIGNAL(clicked()): 체크박스가 클릭되었을 때 발생하는 신호입니다.
- this: 현재 객체(Widget 클래스)를 의미하며, 슬롯이 구현된 곳입니다.
- SLOT(slot_chkChanged()): slot_chkChanged() 함수는 슬롯으로서, 체크박스가 클릭될 때 호출됩니다. 이 함수는 어떤 체크박스가 선택되었는지 확인하고, 선택 상태를 처리하는 역할을 합니다.
QComboBox
사용자가 위젯을 클릭하면 팝업 메뉴가 나타나고 등록된 항목 중 하나를 선택할 수 있는 GUI를 제공한다. QComboBox 위젯 상에 아이템을 등록하기 위해 텍스트 또는 아이템에 이미지를 사용해 텍스트를 함께 사용할 수 있다.
[widget.h]
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QComboBox>
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private:
QComboBox *combo;
private slots:
void valueChanged();
};
#endif // WIDGET_H
[main.cpp]
#include <QtWidgets/QApplication>
#include "widget.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
[widget.cpp]
#include "widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
setWindowTitle("QComboBox");
combo = new QComboBox(this);
combo->setGeometry(50, 50, 200, 30);
combo->addItem(QIcon(":resources/browser.png"), "Application");
combo->addItem(QIcon(":resources/mail.png"), "Graphics");
// 각 이미지의 리소스 파일의 위치를 알기 위해서는 Qt Creator의 왼쪽 프로젝트 창에서 이미지에 마우스를 올려놓은다음
// 마우스 오른쪽 버튼을 클릭하면 메뉴게서 Copy Path또는 Copy URL를 누르면 해당 이미지의 리소스명을 메모리에 복사된다.
// 그런다음 소스코드에 붙여넣기 하면된다.
combo->addItem("Database");
combo->addItem("Network");
connect(combo, SIGNAL(currentIndexChanged(int)),
this, SLOT(valueChanged()));
QString str;
str = combo->currentText();
qDebug("Total Items : %d", combo->count());
}
void Widget::valueChanged()
{
int current_index = combo->currentIndex();
qDebug("Current ComboBox index : %d", current_index);
}
Widget::~Widget()
{
}
=> 콤보박스 선택에 따른 인덱스 출력 나오는 widget
QCommandLinkButton
이 위젯은 QPushButton 위젯과 동일한 기능을 제공하는 위젯이다. 특징으로 이 위젯은 MS Windows 에서 제공하는 Link Button과 같은 스타일을 제공한다.
[widget.h]
#ifndef WIDGET_H
#define WIDGET_H
#include <QCommandLinkButton>
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private:
QCommandLinkButton *cmmBtn;
private slots:
void clickFunc();
};
#endif // WIDGET_H
[widget.cpp]
#include "widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
setFixedSize(QSize(300, 100));
// 이 메서드는 위젯의 크기를 고정시키는 역할을 합니다.
// QSize(300, 100)는 가로 300 픽셀, 세로 100 픽셀 크기의 위젯을 나타냅니다.
// 즉, 이 위젯은 크기가 고정되어, 사용자가 창의 크기를 변경할 수 없습니다.
cmmBtn = new QCommandLinkButton("Vision", "Vision Project", this);
// QCommandLinkButton은 기본적으로 제목과 설명이 있는 특수한 버튼입니다. 보통 다른 명령을 실행할 때 사용됩니다.
// 제목 , 버튼 아래 텍스트 , this는 버튼의 부모를 widget으로 설정하므로, 이 버튼은 widget위제에 포함됩니다.
cmmBtn->setFlat(true);
// setFlat(true)는 버튼의 스타일을 평평하게 만듭니다. 즉, 버튼에 테두리나 3D 효과가 없어지고, 좀 더 단순한 디자인으로 보여집니다.
connect(cmmBtn, SIGNAL(clicked()), this, SLOT(clickFunc()));
// cmmBtn이 클릭되면 SIGNAL(clicked()) 신호가 발생합니다.
// 이 신호가 발생하면, this (즉, 현재 Widget 객체)에 있는 SLOT(clickFunc()) 함수가 호출됩니다.
// clickFunc()는 버튼이 클릭될 때 실행되는 함수입니다.
}
void Widget::clickFunc()
{
qDebug("QCommandLinkButton Click.");
// 이 함수는 QCommandLinkButton이 클릭되었을 때 실행됩니다.
// qDebug("QCommandLinkButton Click.");는 디버그 콘솔에 "QCommandLinkButton Click."이라는 메시지를 출력하는 함수입니다.
// 이로써 버튼이 제대로 클릭되었는지 확인할 수 있습니다.
}
Widget::~Widget()
{
}
=> QCommandLinkButton이라는 버튼을 생성하고, 클릭 시 콘솔에 메시지를 출력하는 기능을 가지고 있습니다.
[main.cpp]
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
QDate 클래스와 QDateEdit 위젯 클래스
QDateEdit는 날짜를 표시하거나 변경할 수 있는 GUI를 제공한다. QDateEdit는 QDate 클래스에 설정된 날짜를 표시할 수 있다. QDate 클래스는 년, 월, 일을 지정하거나 현재 날짜를 시스템으로부터 얻어와 QDateEdit 위젯에 연결해 표시할 수 있다.
[widget.h]
#ifndef WIDGET_H
#define WIDGET_H
#include <QDate>
#include <QDateEdit>
#include <QLabel>
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private:
QDateEdit *dateEdit[4];
QLabel *lbl[2];
};
#endif // WIDGET_H
[widget.cpp]
#include "widget.h"
#include <QDate>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
QDate dt1 = QDate(2023, 1, 1);
// dt1이라는 QDate 객체를 생성하며, 2023년 1월 1일로 초기화됩니다.
QDate dt2 = QDate::currentDate();
// dt2는 현재 날짜를 저장하는 QDate 객체입니다.
// QDate::currentDate()는 시스템의 현재 날짜를 반환합니다.
dateEdit[0] = new QDateEdit(dt1.addYears(2), this);
// dt1의 날짜에서 2년을 더한 날짜를 표시하는 QDateEdit 위젯을 생성합니다.
// dt1.addYears(2)는 2023년 1월 1일에 2년을 더해 2025년 1월 1일을 반환합니다.
dateEdit[0]->setGeometry(10, 10, 140, 40);
// 위젯의 위치와 크기를 설정하는 함수입니다.
// 여기서는 (x: 10, y: 10) 위치에 너비 140, 높이 40의 크기로 설정합니다.
dateEdit[1] = new QDateEdit(dt1.addMonths(3), this);
// dt1에서 3개월을 더한 날짜를 표시하는 위젯입니다.
// dt1.addMonths(3)은 2023년 4월 1일을 반환합니다.
dateEdit[1]->setGeometry(160, 10, 140, 40);
dateEdit[2] = new QDateEdit(dt1.addDays(10), this);
// dt1에서 10일을 더한 날짜를 표시하는 위젯입니다.
// dt1.addDays(10)은 2023년 1월 11일을 반환합니다.
dateEdit[2]->setGeometry(310, 10, 140, 40);
dateEdit[3] = new QDateEdit(dt2, this);3
// 현재 날짜(dt2)를 표시하는 위젯입니다. 이 위젯은 현재 날짜로 설정됩니다.
dateEdit[3]->setGeometry(10, 60, 140, 40);
// 1:mon, 2:tue, 3:wed, 4:thur, 5:fri, 6:sat, 7:sun
qDebug("Day of year : %d", dt1.dayOfYear());
// 해당 날짜가 1년 중 몇 번째 날인지를 반환합니다.
// 여기서 2023년 1월 1일은 1년 중 1번째 날이므로, Day of year: 1이 출력됩니다.
qDebug("End Day : %d", dt1.daysInMonth());
// 해당 달의 마지막 날(총 일수)을 반환합니다. 2023년 1월은 31일이므로, End Day: 31이 출력됩니다.
qDebug("End Day : %d", dt1.daysInYear());
// 해당 연도의 마지막 날(총 일수)을 반환합니다. 2023년은 평년이므로, 365일이 반환됩니다.
QDate dt3 = QDate::fromString("2002.06.26", "yyyy.MM.dd");
// 문자열 "2002.06.26"을 QDate 객체로 변환합니다. 문자열 형식은 "yyyy.MM.dd"입니다.
QDate dt4 = QDate::fromString("06.26", "MM.dd");
// 문자열 "06.26"을 QDate로 변환합니다. 형식은 "MM.dd"이며, 이 경우 연도가 기본값(1900)으로 설정됩니다.
lbl[0] = new QLabel(dt3.toString(), this);
// dt3의 날짜(2002년 6월 26일)를 QLabel에 표시합니다.
lbl[0]->setGeometry(10,110, 150, 30);
lbl[1] = new QLabel(dt4.toString(), this);
// dt4의 날짜(연도가 없는 6월 26일, 기본적으로 1900년 6월 26일)를 QLabel에 표시합니다.
lbl[1]->setGeometry(10,150, 150, 30);
if(QDate::isValid(2011, 6, 27))
{
qDebug("2013.6.27 true");
// 주어진 날짜가 유효한지 확인하는 함수입니다.
// 여기서 2011년 6월 27일이 유효한 날짜이므로, true를 반환하고 "2013.6.27 true"가 콘솔에 출력됩니다.
}
else
{
qDebug("2013.6.27 false");
}
}
Widget::~Widget()
{
}
[main.cpp]
#include <QApplication>
#include "widget.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
QTime 클래스와 QTimeEdit 위젯 클래스
QTime 클래스는 시간을 표시하거나 특정 조건에 비교 등 어플리케이션 개발에 필요한 시간 관련 기능을 쉽게 구현할 수 있다. QTimeEdit는 QTime 클래스로부터 얻어온 시간을 GUI인터페이스 상에 표시할 수 있는 기능을 제공한다.
[widget.h]
#ifndef WIDGET_H
#define WIDGET_H
#include <QTime>
#include <QTimeEdit>
#include <QLabel>
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
};
#endif // WIDGET_H
[widget.cpp]
#include "widget.h"
#include <QTime>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
QTimeEdit *qte[10];
// QTimeEdit 객체를 배열로 선언합니다. 총 10개의 QTimeEdit를 생성할 준비를 합니다.
QTime ti1 = QTime(6, 24, 0, 0); // hour, min, sec, millisecond
// QTime 객체를 생성하고, 6시 24분 0초 0밀리초로 초기화합니다.
qte[0] = new QTimeEdit(ti1, this);
// ti1을 기반으로 QTimeEdit 위젯을 생성하여 시간(6:24:00)을 표시합니다.
qte[0]->setGeometry(10, 30, 150, 30);
// 이 위젯을 (x: 10, y: 30) 좌표에 너비 150, 높이 30으로 배치합니다.
QTime t;
t = ti1.addSecs(70);
// ti1에 70초를 더한 시간을 t에 저장합니다.
// 6:24:00에 70초를 더하면 6:25:10이 됩니다.
qte[1] = new QTimeEdit(t, this);
// t를 표시하는 QTimeEdit 위젯을 생성하여 시간(6:25:10)을 표시합니다.
qte[1]->setGeometry(10, 70, 150, 30);
qte[2] = new QTimeEdit(ti1.addSecs(2), this);
// ti1에 2초를 더한 시간을 표시하는 QTimeEdit을 생성합니다. 즉, 6:24:02가 됩니다.
qte[2]->setGeometry(10, 110, 150, 30);
QTime ti2 = QTime::currentTime();
// 현재 시간을 ti2에 저장합니다.
qte[4] = new QTimeEdit(ti2.currentTime(), this);
// 현재 시간을 표시하는 QTimeEdit 위젯을 생성합니다.
qte[4]->setGeometry(10, 150, 150, 30);
QTime ti3 = QTime::fromString("03:32", "hh:mm");
// 문자열 "03:32"을 QTime 객체로 변환합니다.
// 문자열 형식은 "hh:mm"으로 설정되어 있어 3시 32분을 의미합니다.
QLabel *lbl_fromString = new QLabel(ti3.toString(), this);
// QTime 객체 ti3를 문자열로 변환하여 라벨로 표시합니다.
lbl_fromString->setGeometry(10, 190, 150, 30);
QTime ti4 = QTime(6, 25, 34, 323);
// 6시 25분 34초 323밀리초로 구성된 QTime 객체를 생성합니다.
qDebug("Hour : %d", ti4.hour());
// ti4.hour()은 6을 반환합니다.
qDebug("min : %d", ti4.minute());
// ti4.minute()은 25를 반환합니다.
qDebug("sec : %d", ti4.second());
// ti4.second()은 34를 반환합니다.
qDebug("msec : %d", ti4.msec());
// ti4.msec()은 323을 반환합니다.
QTime ti5 = QTime(7, 10, 23, 122);
// 7시 10분 23초 122밀리초로 구성된 QTime 객체를 생성합니다.
QLabel *lbl_toString = new QLabel(ti5.toString("AP hh:mm:ss:zzz"), this);
// AP는 오전/오후를 나타내며, "hh:mm:ss:zzz"는 시, 분, 초, 밀리초를 포맷에 맞춰 문자열로 변환합니다.
lbl_toString->setGeometry(10, 10, 150, 30);
// 이 문자열을 QLabel로 표시하며, 좌표 (10, 10)에 배치합니다.
}
Widget::~Widget()
{
}
=> 이 코드는 Qt 프레임워크를 사용하여 시간(Time)과 관련된 기능을 다루는 GUI 애플리케이션입니다. QTimeEdit 위젯을 사용하여 다양한 시간을 표시하고, 시간과 관련된 여러 작업을 수행합니다.
[main.cpp]
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
QDateTimeEdit
위젯에 표시된 날짜와 시간을 스핀 박스 버튼으로 변경할 수 있으며 날짜와 시간을 변경할 때 범위를 지정할 수 있다.
[widget.h]
#ifndef WIDGET_H
#define WIDGET_H
#include <QDate>
#include <QDateTime>
#include <QtWidgets/QDateTimeEdit>
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
private:
};
#endif // WIDGET_H
[widget.cpp]
#include "widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
QDateTimeEdit *qde1;
// 현재 날짜와 시간을 표시하는 QDateTimeEdit 위젯입니다.
qde1 = new QDateTimeEdit(QDateTime::currentDateTime(), this);
// 현재 날짜와 시간을 QDateTime::currentDateTime()으로 가져와 위젯에 설정합니다.
qde1->setDisplayFormat("yyyy-MM-dd hh:mm:ss:zzz");
// setDisplayFormat(): 날짜와 시간을 표시하는 형식을 설정합니다.
qde1->setGeometry(10, 30, 250, 30);
// 이 위젯을 (x: 10, y: 30) 위치에 너비 250, 높이 30으로 배치합니다.
QDateTimeEdit *qde[3];
// qde[3] 배열은 각각 연도, 월, 일에 대한 날짜 선택을 제공합니다. 각 위젯은 범위가 제한되어 있습니다.
qde[0] = new QDateTimeEdit(QDate::currentDate(), this);
// 현재 날짜를 기준으로 QDateTimeEdit 위젯을 생성합니다.
qde[0]->setMinimumDate(QDate::currentDate().addYears(-3));
// 최소 날짜를 현재 날짜에서 3년 전으로 설정합니다.
qde[0]->setMaximumDate(QDate::currentDate().addYears(3));
// 최대 날짜를 현재 날짜에서 3년 후로 설정합니다.
qde[0]->setDisplayFormat("yyyy");
// 연도만 표시하는 형식으로 설정합니다.
qde[0]->setGeometry(10, 90, 100, 30);
// 이 위젯을 (x: 10, y: 90) 위치에 너비 100, 높이 30으로 배치합니다.
qde[1] = new QDateTimeEdit(QDate::currentDate(), this);
qde[1]->setMinimumDate(QDate::currentDate().addMonths(-2));
// 최소 날짜를 현재 날짜에서 2개월 전으로 설정합니다.
qde[1]->setMaximumDate(QDate::currentDate().addMonths(2));
// 최대 날짜를 현재 날짜에서 2개월 후로 설정합니다.
qde[1]->setDisplayFormat("MM");
// 월만 표시하는 형식으로 설정합니다.
qde[1]->setGeometry(120, 90, 100, 30);
qde[2] = new QDateTimeEdit(QDate::currentDate(), this);
qde[2]->setMinimumDate(QDate::currentDate().addDays(-20));
// 최소 날짜를 현재 날짜에서 20일 전으로 설정합니다.
qde[2]->setMaximumDate(QDate::currentDate().addDays(20));
// 최대 날짜를 현재 날짜에서 20일 후로 설정합니다.
qde[2]->setDisplayFormat("dd");
// 일만 표시하는 형식으로 설정합니다.
qde[2]->setGeometry(230, 90, 100, 30);
}
Widget::~Widget()
{
}
[main.cpp]
#include <QtWidgets/QApplication>
#include "widget.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
[현재 날짜 기준 최소날짜 범위 출력]
QDial
QDial 위젯 클래스는 다이얼과 같은 GUI 인터페이스를 제공한다. 예를 들어 볼륨 조절 시 다이얼을 돌려 조절하는 것과 같은 GUI를 제공한다.
QSpinBox와 QDoubleSpinBox
QSpinBox 클래스는 int형 데이터 타입의 정수 값을 상하 버튼을 이용해 변경할 수 있는 GUI를 제공한다. double 데이터 타입을 사용하기 위해서는 QDoubleSpinBox 위젯을사용하면 된다.
QSpinBox와 QDoubleSpinBox 위젯 클래스는 사용자가 변경할 수 있는 값의 범위를 제한할 수 있으며 숫자가 표시되는 Prefix와 Suffix 부분에 특정 문자 혹은 단위를 가리키는 문자를 사용할 수 있다. 예를 들어 화폐 기호를 위젯 안에 사용할 수 있다.
QPushButton 과 QFocusFrame
QPushButton 위젯은 버튼 기능을 제공한다. QFocusFrame은 바깥쪽에 Outer Line을 사용해야 할 경우 QFocusFrame을 사용하면 유용하다. 이 외에도 QFocusFrame은 QStyle(HTML에서 사용하는 Style Sheet) 을 사용 할 수 있다. QPushButton 위젯 바깥쪽에Outer Line을 그리기 위해 QFocusFrame를 사용하는 방법은 다음과 같다.
QFontComboBox
QFontComboBox 위젯은 GUI상에 폰트를 선택하기 위한 GUI를 제공한다. 이 위젯은 폰트가 알파벳 순서로 나열되고, 폰트의 모양도 확인할 수 있다.
setFontFilters( ) 멤버함수에서 사용 가능한 상수이다.
상수 | 값 | 설명 |
QFontComboBox::AllFonts | 0 | 모든 폰트 |
QFontComboBox::ScalableFonts | 0x1 | 확대/축소시 동적 자동 변환 가능한 폰트 |
QFontComboBox::NonScalableFonts | 0x2 | 동적 자동 변환이 제공되지 않는 폰트 |
QFontComboBox::MonospacedFonts | 0x3 | 일정한 문자 넓이 형태를 제공하는 폰트 |
QFontComboBox::ProportionalFonts | 0x4 | 넓이와 폭의 균형이 잡힌 폰트 |
QLabel 과 QLCDNumber
QLabel 위젯은 어플리케이션 상에서 텍스트 또는 이미지를 표시하는 기능을 제공한다.
QLCDNumber 위젯은 숫자만 표시할 수 있으며 디지털 시계와 같은 형태로 숫자를 표시할 수 있다. QLCDNumber 위젯은 시간을 표시할 때 사용하는 “ : ” 문자를 함께 사용할 수 있다.
QLineEdit
QLineEdit 위젯은 텍스트를 입력 및 수정을 위한 GUI를 제공한다. QLineEdit 클래스 위젯에서 복사, 붙여 넣기, 자르기 등의 기능을 제공한다.
setEchoMode( )멤버 함수에 인자로 다음과 같은 상수를 사용해야 한다.
상수 | 값 | 설명 |
QLineEdit::Normal | 0 | 디폴트와 동일한 스타일 |
QLineEdit::NoEcho | 1 | 텍스트가 보이지 않으며 커서의 위치도 변경되지 않는 스타일 |
QLineEdit::Password | 2 | 텍스트가“*”문자로 표시 |
QLineEdit::PasswordEchoOnEdit | 3 | 텍스트가 변경되면 디폴트 스타일과 동일 하지만 포커스가 이동되면 “*” 표시 |
QMenu 와 QMenuBar 클래스를 이용한 메뉴
QMenu 와 QMenuBar 클래스 위젯은 메뉴 기능을 제공한다. QMenu 위젯은 메뉴를 만들기 위해 제공하는 위젯으로써 addAction( )과 addMenu( ) 멤버 함수를 제공한다. 아래는 이 함수들을 이용해 작성한 소스코드이다.
QProgressBar
진행사항을 표시하기 위한 위젯으로 QProgressBar 위젯을 사용할 수 있으며 위젯의 배치 방향을 가로 또는 세로로 표시할 수 있다. QProgressBar 위젯은 가로 방향으로 배치할 경우 왼쪽에서 오른쪽으로, 오른쪽에서 왼쪽으로 진행방향을 변경할 수 있다. 반대
로 세로 방향으로 배치할 경우 아래에서 위로, 위에서 아래로 진행 방향을 표시할 수 있다.
QRadioButton
QRadioButton 위젯은 사용자에게 여러 항목 중 하나를 선택할 수 있는 GUI를 제공한다. 예를 들어 On(checked) 혹은 Off(unchecked)와 같이 둘 중 하나를 선택할 수 있다.
QScrollArea
QScrollArea 위젯은 GUI가 표시되는 윈도우 상에서 위젯들을 모두 표시할 수 없는 경우 스크롤 바를 이용해 가려진 부분으로 이동하는 방식으로 GUI를 모두 표시할 수 있는 기능을 제공한다.
예를 들어 어떤 이미지를 축소하지 않고 화면에 표시 하고자 할 때 GUI 위젯의 크기가 부족하게 되면 좌측 또는 하단에 스크롤이 생겨 마우스로 스크롤을 이동하면서 이미지를 볼 수 있는 것과 같은 기능을 제공한다.
QScrollBar
QScrollBar 위젯 클래스는 슬라이더 위젯의 모양과 비슷하다. QScrollBar 위젯은 좌우 혹은 상하 위치 시킬 때 세로 방향 혹은 가로 방향으로 직접 배치할 수 있는 기능을 제공한다.
QSizeGrip
QSizeGrip 클래스 위젯은 한정된 크기의 윈도우 영역 안에 위젯의 크기를 조절할 수 있다. 예를 들어 MS Windows의 탐색기와 같이 왼쪽에는 트리 영역, 오른쪽은 파일 및 디렉토리 속성을 보여주는 GUI 상에서 트리 영역의 경계선을 마우스로 드래그하여 줄
이거나 늘릴 수 있다. 다음 소스코드는 widget.h 파일 소스코드 이다.
QSilder
QSlider 위젯은 최소값과 최대값을 지정한 범위 내에서 설정 값을 변경할 수 있는 GUI를 제공한다. 이 위젯은 QScrollBar와 유사하다. setMinimum( )과 setMaximum( ) 멤버함수를 사용해 최소값과 최대값을 설정할 수 있다. 최소값과 최대값을 설정하기 위해 setRange( ) 멤버 함수를 사용할 수 있다.
QTableWidget
많은 위젯을 배치할 경우 또는 윈도우의 크기가 제한적일 때 이 위젯을 사용하면 유용하다. 이 위젯은 제한된 크기에 모든 탭을 표시할 수 없을 경우 동적으로 페이지를 이동할 수 있는 기능을 제공한다.
QWidget으로 선언한 위젯을 tab 인스턴스 위젯 상에 배치하기 위해 addTab( ) 멤버 함수를 사용하면 된다. 각 탭 상에 위젯을 배치하는 방법은 위젯을 배치하기 위해 부모클래스를 인자로 명시한 것처럼 부모 클래스를 탭 위젯으로 명시하면 그 위젯이 해당 탭 내에 위젯을 배치할 수 있다.
QToolBar 와 QAction
QToolBar 위젯은 윈도우 상에 툴 메뉴 바와 같은 GUI를 제공한다. QToolBar 위젯은 addAction( ) 멤버 함수를 이용해 툴바 상에 메뉴를 추가할 수 있다.
setToolButtonStyle( ) 멤버함수
상수 | 값 | 설명 |
Qt::ToolButtonIconOnly | 0 | 아이콘만 표시 |
Qt::ToolButtonTextOnly | 1 | 버튼 이름만 표시 |
Qt::ToolButtonTextBesideIcon | 2 | 아이콘을 텍스트 안쪽에 표시 |
Qt::ToolButtonTextUnderIcon | 3 | 아이콘을 텍스트 아래에 표시 |
QWidget
지금까지 살펴본 위젯은 QWidget으로부터 상속받아 구현한 위젯이다. 예를 들어 마우스, 키보드 혹은 윈도우로부터 받은 이벤트를 QPushButton과 같은 위젯에서 사용할 수 있는 것도 QWidget 으로부터 상속받았기 때문에 가능하다.
QWidget 클래스는 paintEvent( ) virtual 함수를 이용해 위젯 영역에 텍스트, 도형(선, 원, 사각형 등), 이미지를 랜더링 할 수 있는 기능을 제공한다. 또한 QWidget 클래스의 update() 멤버 함수를 호출하면 paintEvent ( ) 함수를 호출 할 수 있다. 예를 들어 어떤
버튼을 클릭하면 호출되는 Slot함수 내에 update() 멤버 함수를 사용하면 paintEvent( ) virtual 함수가 호출 된다. 따라서 QWidget 의 Paint 영역을 다시 Drawing 한다.
QWidget 클래스는 resizeEvent( ) virtual 함수를 제공한다. 이 virtual 함수는 QWidget의 크기가 변경되면 호출된다. QWidget 영역 내에 마우스 이벤트를 처리, 키보드 이벤트, 위젯의 영역에 활성화가 Focus 되어 있는지 등의 다양한 virtual 함수를 제공한다.
QTabBar
QTabBar 클래스 위젯은 탭 GUI를 제공한다. 이 위젯은 QTabWidget 과 비슷한 기능을 제공한다. 탭에 아이콘을 사용 하기 위해서 setTabIcon( ) 함수를 사용하면 된다. 각 탭 에 표시되는 텍스트가 구별되게 컬러 지정이 가능하다. 탭의 텍스트를 지정하기 위해
setTabTextColor( ) 함수를 사용하면 된다.
QTabBar는 모서리가 둥근 형태의 탭이나 탭의 왼쪽 모서리만 둥글게 표현한 도형을 이용할 수 있는 기능을 제공하며 setShape( ) 함수를 이용해 지정할 수 있다.
상수 | 값 | 설명 |
QTabBar::RoundedNorth | 0 | 디폴트 모양 |
QTabBar::RoundedSouth | 1 | 페이지 아래쪽이 둥근 형태 |
QTabBar::RoundedWest | 2 | 페이지의 왼쪽 부분이 둥근 형태 |
QTabBar::RoundedEast | 3 | 페이지의 오른쪽 부분이 둥근 형태 |
QTabBar::TriangularNorth | 4 | 삼각형 모양 |
QTabBar::TriangularSouth | 5 | 스프레드시트에서 사용하는 형태와 비슷한 형태 |
QTabBar::TriangularWest | 6 | 페이지의 왼쪽 부분이 삼각형 모양 |
QTabBar::TriangularEast | 7 | 페이지의 오른쪽 부분이 삼각형 모양 |
QToolBox
QToolbox 클래스 위젯은 위젯 아이템들을 새로 방향 탭 컬럼 형태로 GUI를 제공한다. 각 탭의 이름으로 텍스트와 아이콘을 사용할 수 있다.
QToolButton
QToolButton 위젯은 텍스트 또는 아이콘을 사용해 버튼과 같은 기능을 제공한다.
QToolButton의 아이콘은 QIcon 클래스를 이용해 지정할 수 있다. 아이콘은 상태에 따라 활성화 또는 비활성화된 상태로 표시할 수 있으며 비활성화 상태에서는 버튼을 사용할 수 없다.
setToolButtonStyle( ) 멤버 함수를 이용하면 스타일을 변경 할 수 있으며 setIConSize( )함수를 이용하면 아이콘의 크기를 지정할 수 있다.
6. Layout
레이아웃을 이용하면 윈도의 크기가 될 때마다 동적으로 GUI 상에 위젯들의 크기도 동적으로 변경된다.
** QWidget 클래스의 setGeometry( ) 멤버 함수를 이용해 GUI 상에서 특정 X, Y 좌표로 위젯을 배치하게 되면 윈도우의 크기가 변경될 때 위젯의 위치가 변경되지 않는다.
Qt에서 주로 사용되는 레이아웃 클래스들
클래스 | 설명 |
QHBoxLayout | 위젯들을 가로 방향으로 배치 |
QVBoxLayout | 위젯들을 세로 방향으로 배치 |
QGridLayout | 위젯을 그리드(Grid) 또는 바둑판 스타일로 배치 |
QFormLayout | 위젯을 2열로 배치하는 형식. |
QHBoxLayout
QHBoxLayout은 위젯들을 가로 방향으로 배치할 수 있다. 다음 예제에서와 같이 QPushButton 위젯을 addWidget( ) 멤버 함수를 이용해 추가할 수 있다.
[widget.cpp]
#include "widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
QHBoxLayout *hboxLayout = new QHBoxLayout();
// 수평 레이아웃(HBox)을 생성합니다. 이 레이아웃에 버튼을 추가하면 좌에서 우로 배치됩니다.
QPushButton *btn[6];
QString btnStr[6] = {"One", "Two", "Three", "Four", "Six", "Seven"};
// 버튼 6개가 수평으로 추가되며,
// 각 버튼에는 "One", "Two", "Three", "Four", "Six", "Seven" 텍스트가 표시됩니다.
for(int i = 0 ; i < 6 ; i++)
{
btn[i] = new QPushButton(btnStr[i]);
// 버튼 생성
hboxLayout->addWidget(btn[i]);
// 각각의 버튼을 hboxLayout에 추가합니다.
}
QVBoxLayout *vboxLayout = new QVBoxLayout();
// 수직 레이아웃(VBox)을 생성합니다. 이 레이아웃에 버튼을 추가하면 위에서 아래로 배치됩니다.
QPushButton *vbtn[6];
QString vbtnStr[3] = {"Movie", "Drama", "Animation"};
// 버튼 3개가 수직으로 추가되며,
// 각각의 버튼에는 "Movie", "Drama", "Animation" 텍스트가 표시됩니다.
for(int i = 0 ; i < 3 ; i++)
{
vbtn[i] = new QPushButton(vbtnStr[i]);
vboxLayout->addWidget(vbtn[i]);
// 각각의 버튼을 vboxLayout에 추가합니다.
}
QGridLayout *gridLayout = new QGridLayout();
// 그리드 레이아웃(Grid)을 생성합니다. 이 레이아웃은 행(row)과 열(column)로 구성됩니다.
QPushButton *gbtn[5];
for(int i = 0 ; i < 5 ; i++)
{
gbtn[i] = new QPushButton(btnStr[i]);
}
// 버튼 5개를 2x3 그리드 형식으로 배치합니다.
gridLayout->addWidget(gbtn[0], 0, 0); // (0, 0): 첫 번째 버튼 (gbtn[0])
gridLayout->addWidget(gbtn[1], 0, 1); // (0, 1): 두 번째 버튼 (gbtn[1])
gridLayout->addWidget(gbtn[2], 1, 0, 1, 2); // (1, 0)에서 (1, 1)까지: 세 번째 버튼 (gbtn[2], 두 열을 차지) /두 열을 차지하는 버튼을 추가하는 것을 의미합니다.
gridLayout->addWidget(gbtn[3], 2, 0); // (2, 0): 네 번째 버튼 (gbtn[3])
gridLayout->addWidget(gbtn[4], 2, 1); // (2, 1): 다섯 번째 버튼 (gbtn[4])
QVBoxLayout *defaultLayout = new QVBoxLayout();
// 전체 레이아웃을 관리하는 defaultLayout입니다. 이 레이아웃에 다른 레이아웃들을 추가할 수 있습니다.
/////////////////////주석 해제를 통해 hboxLayout / vboxLayout / gridLayout 대로 출력가능
defaultLayout->addLayout(hboxLayout);
// defaultLayout->addLayout(vboxLayout);
// defaultLayout->addLayout(gridLayout);
setLayout(defaultLayout);
// defaultLayout을 Widget의 메인 레이아웃으로 설정합니다.
}
Widget::~Widget()
{
}
QVBoxLayout
QVBoxLayout은 위젯을 세로 방향으로 배치할 수 있다.
[widget.cpp]
#include "widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
QHBoxLayout *hboxLayout = new QHBoxLayout();
// 수평 레이아웃(HBox)을 생성합니다. 이 레이아웃에 버튼을 추가하면 좌에서 우로 배치됩니다.
QPushButton *btn[6];
QString btnStr[6] = {"One", "Two", "Three", "Four", "Six", "Seven"};
// 버튼 6개가 수평으로 추가되며,
// 각 버튼에는 "One", "Two", "Three", "Four", "Six", "Seven" 텍스트가 표시됩니다.
for(int i = 0 ; i < 6 ; i++)
{
btn[i] = new QPushButton(btnStr[i]);
// 버튼 생성
hboxLayout->addWidget(btn[i]);
// 각각의 버튼을 hboxLayout에 추가합니다.
}
QVBoxLayout *vboxLayout = new QVBoxLayout();
// 수직 레이아웃(VBox)을 생성합니다. 이 레이아웃에 버튼을 추가하면 위에서 아래로 배치됩니다.
QPushButton *vbtn[6];
QString vbtnStr[3] = {"Movie", "Drama", "Animation"};
// 버튼 3개가 수직으로 추가되며,
// 각각의 버튼에는 "Movie", "Drama", "Animation" 텍스트가 표시됩니다.
for(int i = 0 ; i < 3 ; i++)
{
vbtn[i] = new QPushButton(vbtnStr[i]);
vboxLayout->addWidget(vbtn[i]);
// 각각의 버튼을 vboxLayout에 추가합니다.
}
QGridLayout *gridLayout = new QGridLayout();
// 그리드 레이아웃(Grid)을 생성합니다. 이 레이아웃은 행(row)과 열(column)로 구성됩니다.
QPushButton *gbtn[5];
for(int i = 0 ; i < 5 ; i++)
{
gbtn[i] = new QPushButton(btnStr[i]);
}
// 버튼 5개를 2x3 그리드 형식으로 배치합니다.
gridLayout->addWidget(gbtn[0], 0, 0); // (0, 0): 첫 번째 버튼 (gbtn[0])
gridLayout->addWidget(gbtn[1], 0, 1); // (0, 1): 두 번째 버튼 (gbtn[1])
gridLayout->addWidget(gbtn[2], 1, 0, 1, 2); // (1, 0)에서 (1, 1)까지: 세 번째 버튼 (gbtn[2], 두 열을 차지) /두 열을 차지하는 버튼을 추가하는 것을 의미합니다.
gridLayout->addWidget(gbtn[3], 2, 0); // (2, 0): 네 번째 버튼 (gbtn[3])
gridLayout->addWidget(gbtn[4], 2, 1); // (2, 1): 다섯 번째 버튼 (gbtn[4])
QVBoxLayout *defaultLayout = new QVBoxLayout();
// 전체 레이아웃을 관리하는 defaultLayout입니다. 이 레이아웃에 다른 레이아웃들을 추가할 수 있습니다.
/////////////////////주석 해제를 통해 hboxLayout / vboxLayout / gridLayout 대로 출력가능
// defaultLayout->addLayout(hboxLayout);
defaultLayout->addLayout(vboxLayout);
// defaultLayout->addLayout(gridLayout);
setLayout(defaultLayout);
// defaultLayout을 Widget의 메인 레이아웃으로 설정합니다.
}
Widget::~Widget()
{
}
QGridLayout
QGridLayout은 바둑판 모양과 같은 스타일로 위젯을 배치할 수 있다. QGridLayout 은 특정 행을 하나의 위젯만 배치할 수 있도록 병합 하거나 여러 개의 셀로 나눌 수 있다.
[widget.cpp]
#include "widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
QHBoxLayout *hboxLayout = new QHBoxLayout();
// 수평 레이아웃(HBox)을 생성합니다. 이 레이아웃에 버튼을 추가하면 좌에서 우로 배치됩니다.
QPushButton *btn[6];
QString btnStr[6] = {"One", "Two", "Three", "Four", "Six", "Seven"};
// 버튼 6개가 수평으로 추가되며,
// 각 버튼에는 "One", "Two", "Three", "Four", "Six", "Seven" 텍스트가 표시됩니다.
for(int i = 0 ; i < 6 ; i++)
{
btn[i] = new QPushButton(btnStr[i]);
// 버튼 생성
hboxLayout->addWidget(btn[i]);
// 각각의 버튼을 hboxLayout에 추가합니다.
}
QVBoxLayout *vboxLayout = new QVBoxLayout();
// 수직 레이아웃(VBox)을 생성합니다. 이 레이아웃에 버튼을 추가하면 위에서 아래로 배치됩니다.
QPushButton *vbtn[6];
QString vbtnStr[3] = {"Movie", "Drama", "Animation"};
// 버튼 3개가 수직으로 추가되며,
// 각각의 버튼에는 "Movie", "Drama", "Animation" 텍스트가 표시됩니다.
for(int i = 0 ; i < 3 ; i++)
{
vbtn[i] = new QPushButton(vbtnStr[i]);
vboxLayout->addWidget(vbtn[i]);
// 각각의 버튼을 vboxLayout에 추가합니다.
}
QGridLayout *gridLayout = new QGridLayout();
// 그리드 레이아웃(Grid)을 생성합니다. 이 레이아웃은 행(row)과 열(column)로 구성됩니다.
QPushButton *gbtn[5];
for(int i = 0 ; i < 5 ; i++)
{
gbtn[i] = new QPushButton(btnStr[i]);
}
// 버튼 5개를 2x3 그리드 형식으로 배치합니다.
gridLayout->addWidget(gbtn[0], 0, 0); // (0, 0): 첫 번째 버튼 (gbtn[0])
gridLayout->addWidget(gbtn[1], 0, 1); // (0, 1): 두 번째 버튼 (gbtn[1])
gridLayout->addWidget(gbtn[2], 1, 0, 1, 2); // (1, 0)에서 (1, 1)까지: 세 번째 버튼 (gbtn[2], 두 열을 차지) /두 열을 차지하는 버튼을 추가하는 것을 의미합니다.
gridLayout->addWidget(gbtn[3], 2, 0); // (2, 0): 네 번째 버튼 (gbtn[3])
gridLayout->addWidget(gbtn[4], 2, 1); // (2, 1): 다섯 번째 버튼 (gbtn[4])
QVBoxLayout *defaultLayout = new QVBoxLayout();
// 전체 레이아웃을 관리하는 defaultLayout입니다. 이 레이아웃에 다른 레이아웃들을 추가할 수 있습니다.
/////////////////////주석 해제를 통해 hboxLayout / vboxLayout / gridLayout 대로 출력가능
// defaultLayout->addLayout(hboxLayout);
// defaultLayout->addLayout(vboxLayout);
defaultLayout->addLayout(gridLayout);
setLayout(defaultLayout);
// defaultLayout을 Widget의 메인 레이아웃으로 설정합니다.
}
Widget::~Widget()
{
}
중첩된 레이아웃을 사용
레이아웃 안에 레이아웃을 배치할 수 있다. 다음 예제는 중첩 구조로 예제이다.
[widget.cpp]
#include "widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
QHBoxLayout *hboxLayout = new QHBoxLayout();
// 수평 레이아웃(HBox)을 생성합니다. 이 레이아웃에 버튼을 추가하면 좌에서 우로 배치됩니다.
QPushButton *btn[6];
QString btnStr[6] = {"One", "Two", "Three", "Four", "Six", "Seven"};
// 버튼 6개가 수평으로 추가되며,
// 각 버튼에는 "One", "Two", "Three", "Four", "Six", "Seven" 텍스트가 표시됩니다.
for(int i = 0 ; i < 6 ; i++)
{
btn[i] = new QPushButton(btnStr[i]);
// 버튼 생성
hboxLayout->addWidget(btn[i]);
// 각각의 버튼을 hboxLayout에 추가합니다.
}
QVBoxLayout *vboxLayout = new QVBoxLayout();
// 수직 레이아웃(VBox)을 생성합니다. 이 레이아웃에 버튼을 추가하면 위에서 아래로 배치됩니다.
QPushButton *vbtn[6];
QString vbtnStr[3] = {"Movie", "Drama", "Animation"};
// 버튼 3개가 수직으로 추가되며,
// 각각의 버튼에는 "Movie", "Drama", "Animation" 텍스트가 표시됩니다.
for(int i = 0 ; i < 3 ; i++)
{
vbtn[i] = new QPushButton(vbtnStr[i]);
vboxLayout->addWidget(vbtn[i]);
// 각각의 버튼을 vboxLayout에 추가합니다.
}
QGridLayout *gridLayout = new QGridLayout();
// 그리드 레이아웃(Grid)을 생성합니다. 이 레이아웃은 행(row)과 열(column)로 구성됩니다.
QPushButton *gbtn[5];
for(int i = 0 ; i < 5 ; i++)
{
gbtn[i] = new QPushButton(btnStr[i]);
}
// 버튼 5개를 2x3 그리드 형식으로 배치합니다.
gridLayout->addWidget(gbtn[0], 0, 0); // (0, 0): 첫 번째 버튼 (gbtn[0])
gridLayout->addWidget(gbtn[1], 0, 1); // (0, 1): 두 번째 버튼 (gbtn[1])
gridLayout->addWidget(gbtn[2], 1, 0, 1, 2); // (1, 0)에서 (1, 1)까지: 세 번째 버튼 (gbtn[2], 두 열을 차지) /두 열을 차지하는 버튼을 추가하는 것을 의미합니다.
gridLayout->addWidget(gbtn[3], 2, 0); // (2, 0): 네 번째 버튼 (gbtn[3])
gridLayout->addWidget(gbtn[4], 2, 1); // (2, 1): 다섯 번째 버튼 (gbtn[4])
QVBoxLayout *defaultLayout = new QVBoxLayout();
// 전체 레이아웃을 관리하는 defaultLayout입니다. 이 레이아웃에 다른 레이아웃들을 추가할 수 있습니다.
defaultLayout->addLayout(hboxLayout);
defaultLayout->addLayout(vboxLayout);
defaultLayout->addLayout(gridLayout);
setLayout(defaultLayout);
// defaultLayout을 Widget의 메인 레이아웃으로 설정합니다.
}
Widget::~Widget()
{
}