LAB/QT_C++

QT 6 Programming [Chapter 01. Qt6 - Chapter 06. Layout]

it-lab-0130 2024. 10. 7. 20:57
QT 란?

 

QT는 MS윈도우, 리눅스 그리고 MacOs와 같은 데스크탑 기반 운영체제에서 어플리케이션을 개발하기 위해 동일한 개발 프레임워크를 제공하는 기본언어 C++로 하는 GUI제작 크로스 플랫폼 프레임 워크 입니다.

 

더보기

** 라이브러리 와 프레임워크 차이점 

 

[라이브러리]

 

"개발자가 특정 기능을 구현할 때 필요한 함수나 클래스를 라이브러리에서 호출하여 사용합니다."

  • 정의: 라이브러리는 특정 작업을 쉽게 처리할 수 있도록 미리 작성된 코드의 모음입니다. 개발자는 필요할 때 이 라이브러리에서 기능을 호출하여 사용할 수 있습니다.
  • 사용 방식: 개발자가 필요한 부분에서 라이브러리의 기능을 직접 호출합니다. 즉, 개발자가 제어를 가지고, 필요할 때 원하는 기능을 끌어다 쓰는 방식입니다.

[프레임워크]

 

"프레임워크는 애플리케이션의 기본적인 동작 방식을 제공하며, 개발자는 그 안에서 필요한 기능을 추가로 구현하는 형태입니다."

 

  • 정의: 프레임워크는 전체 애플리케이션 구조를 잡아주고, 그 구조 안에서 개발자가 코드를 작성할 수 있도록 도와줍니다. 프레임워크는 일종의 틀을 제공하며, 그 틀 안에서 개발해야 합니다.
  • 사용 방식: 프레임워크는 자체적으로 흐름을 제어하며, 개발자는 프레임워크가 정해준 구조 안에서 특정 부분만 구현합니다. 즉, 개발자는 프레임워크의 규칙을 따라야 하며, 프레임워크가 제어의 주도권을 가지고 있습니다.

 


주요 차이점

"정리하자면, 라이브러리는 개발자가 필요할 때 가져다 쓰는 도구이고, 프레임워크는 큰 틀을 제공하여 그 틀 안에서 개발자가 동작하는 방식입니다."

  1. 제어의 흐름 (Inversion of Control):
    • 라이브러리는 개발자가 제어를 하며 필요한 기능을 호출.
    • 프레임워크는 프레임워크가 제어를 하며, 개발자는 그 안에 코드를 작성.
  2. 사용 방식:
    • 라이브러리는 개발자가 필요한 시점에 호출하여 사용.
    • 프레임워크는 전체 애플리케이션 구조를 잡아주며 그 안에서 개발.

 


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()
{

}