๐ QML์ ํตํด์ ์
๋ ฅ๋ ๋ด์ฉ์ ์ง์ ํ๋ฉด์ ์ถ๋ ฅ ํ ์ ์์ต๋๋ค.
You can directly display the content entered through QML on the screen.
๐ ์ด ๋ถ๋ถ์ ์ถ๋ ฅ์ C++์ด ์ํํ๊ณ C++์ฝ๋๋ฅผ QML์ ์ฐ๊ฒฐํ๋ ๊ฒ์ ๋ํ ์ค๋ช
์
๋๋ค.
This part explains how the output is done in C++ and how to connect the C++ code to QML.
๐1.ํ๋ก์ ํธ / Project

๐ 2.C++ ๊ณผ qml ์ฐ๊ฒฐ / Connecting C++ and QML
โ๏ธ myconnector.h์ myconnector.cppํ์ผ์ qml์์ ์ฌ์ฉํ ์๊ทธ๋๊ณผ ํจ์๋ฅผ ์ค์ ํฉ๋๋ค.
Define the signals and functions to be used in QML within the myconnector.h and myconnector.cpp files.
โ๏ธ ์๋์ ์ฝ๋๋ ํค๋ํ์ผ์ ์ฝ๋์
๋๋ค.
The code below is from the header file.
#ifndef MYCONNECTOR_H
#define MYCONNECTOR_H
// MyConnector.h
#include <QObject>
#include <QString>
class MyConnector : public QObject {
Q_OBJECT
public:
explicit MyConnector(QObject *parent = nullptr);
Q_INVOKABLE void updateText(const QString &text1, const QString &text2);
signals:
void resultReady(const QString &result);
};
#endif // MYCONNECTOR_H
โ๏ธ updateText๋ qml(Screen01.qml)์์ ์๋์ ๊ฐ์ด ์ฌ์ฉํฉ๋๋ค.
updateText is used in QML (Screen01.qml) as shown below.
Button {
id: button
text: qsTr("Button")
// === ์ฝ๋์ถ๊ฐ:ํด๋ฆญ ์ด๋ฒคํธ ===
// === Add code:Click Event ===
onClicked: myConnector.updateText(textEdit.text, textEdit2.text)
}
โ๏ธ QML์ ๊ฐ์ฒด ๋ฑ๋กํ๊ธฐ(C++๊ณผ QML ์ฐ๊ฒฐ)
Registering Objects in QML (Connecting C++ and QML)
— Main.cpp์ ์๋์ฒ๋ผ myConnectorํด๋์ค๋ฅผ QML๊ฐ์ฒด๋ก ๋ฑ๋กํ ์ ์์ต๋๋ค.
You can register the myConnector class as a QML object in Main.cpp as shown below.
//โ
QML์ C++ ๊ฐ์ฒด๋ฅผ ๋ฑ๋กํ๊ธฐ ์ํด ํ์
// Required to register C++ objects in QML
#include <QQmlContext>
//โ
MyConnector ํด๋์ค ์ ์ธ ํฌํจ
// Include MyConnector class declaration
#include "MyConnector.h"
... ์ค๋ต / Omitted ...
MyConnector connector;
engine.rootContext()->setContextProperty("myConnector", &connector);
โ๏ธ QML์์ ์ฌ์ฉํ๊ธฐ / Using in QML
— onResultReady๋ myConnector๋ผ๋ ๊ฐ์ฒด๊ฐ ๊ฐ์ง resultReady๋ผ๋ ์๊ทธ๋(Signal) ์ด๋ฆ ์์ on์ ๋ถ์ฌ์ ๋ง๋ ์๊ทธ๋ ํธ๋ค๋ฌ(์ฌ๋กฏ)์
๋๋ค.onResultReady is a signal handler (or slot) created by prefixing “on” to the name of the resultReady signal belonging to the object named myConnector.
1)Screen01.qml(on+ResultReady)
Connections {
target: myConnector
function onResultReady(result) {
text1.text = result
}
}
2)Myconnector.h์ ์๊ทธ๋ ์ ์ธ
Declare the signal in Myconnector.h
signals:
void resultReady(const QString &result);
};
3)Myconnector.cpp์ ์๊ทธ๋ ๋ฐ์
Signal generation in Myconnector.cpp
void MyConnector::updateText(const QString &text1, const QString &text2) {
QString combined = text1 + " " + text2;
emit resultReady(combined);
}
๐3.์ฝ๋์ค๋ช / Code Description
โ๏ธMyconnector.h
#ifndef MYCONNECTOR_H
#define MYCONNECTOR_H
// MyConnector.h
#include <QObject>
#include <QString>
class MyConnector : public QObject {
Q_OBJECT
public:
explicit MyConnector(QObject *parent = nullptr);
Q_INVOKABLE void updateText(const QString &text1, const QString &text2);
signals:
void resultReady(const QString &result);
};
#endif // MYCONNECTOR_H
— ํค๋๊ฐ ๋ค๋ฅธ ํด๋์ค ํ์ผ์ ๋๋ฒ ์ฝ์
๋๋ฉด ์ปดํ์ผ ์ค๋ฅ๊ฐ ๋ฉ๋๋ค.
If a header is inserted twice in different class files, a compilation error occurs.
— ์์ ์ฝ๋์์ ์๋์ ๊ฐ์ด ์์ฑํ๋ฉด ์ค๋ณต ์ฝ์
์ค๋ฅ๊ฐ ๋ฐ์ํ์ง ์์ต๋๋ค.
If you write the code above as follows, a duplicate insertion error will not occur.
— ์ด๋ฏธ ํค๋๊ฐ C++ ํด๋์ค ํ์ผ์ ํฌํจ๋์ด ์์ผ๋ฉด ๋ฌด์ํฉ๋๋ค.
If the header is already included in the C++ class file, it is ignored.
#ifndef MYCONNECTOR_H
#define MYCONNECTOR_H
์ฝ๋ / CODE
#endif // MYCONNECTOR_H
โ๏ธqml/Screen01.qml
import QtQuick
import QtQuick.Controls
Rectangle {
// id: rectangle
// width: Constants.width
// height: Constants.height
// color: Constants.backgroundColor
// ์์ ์ง์ ์ ์ธ. / Direct declaration of constants
property int widthConst: 1920
property int heightConst: 1080
property color backgroundColorConst: "#EAEAEA"
width: widthConst
height: heightConst
color: backgroundColorConst
Column {
id: column
width: 200
anchors.centerIn: parent
spacing: 10
Rectangle {
width: 180
height: 30
color: "white"
border.color: "black"
TextEdit {
id: textEdit
anchors.fill: parent
width: 80
height: 20
text: qsTr("์
๋ ฅ1/input1")
font.pixelSize: 12
}
}
Rectangle {
width: 180
height: 30
color: "white"
border.color: "black"
TextEdit {
id: textEdit2
width: 80
height: 20
text: qsTr("์
๋ ฅ2/input2")
font.pixelSize: 12
}
}
Text {
id: text1
text: qsTr("๊ฐ์ถ๋ ฅ/Print Value")
font.pixelSize: 12
}
Button {
id: button
text: qsTr("Button")
// === ์ฝ๋์ถ๊ฐ:ํด๋ฆญ ์ด๋ฒคํธ ===
// === Add code:Click Event ===
onClicked: myConnector.updateText(textEdit.text, textEdit2.text)
}
// === ์ฝ๋์ถ๊ฐ:์ฐ๊ฒฐ ===
// === Add code:connection ===
Connections {
target: myConnector
function onResultReady(result) {
text1.text = result
}
}
}
}
โ๏ธ main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
// QML์ C++ ๊ฐ์ฒด๋ฅผ ๋ฑ๋กํ๊ธฐ ์ํด ํ์
// Required to register C++ objects in QML
#include <QQmlContext>
// MyConnector ํด๋์ค ์ ์ธ ํฌํจ
// Include MyConnector class declaration
#include "MyConnector.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
QObject::connect(
&engine,
&QQmlApplicationEngine::objectCreationFailed,
&app,
[]() { QCoreApplication::exit(-1); },
Qt::QueuedConnection);
// === ์ฝ๋ ์ถ๊ฐ / Add code ===
MyConnector connector;
engine.rootContext()->setContextProperty("myConnector", &connector);
// === ์ฌ๊ธฐ๊น์ง / Up to here ===
engine.loadFromModule("example3", "Main");
return app.exec();
}
โ๏ธ main.qml
import QtQuick
Window {
width: 640
height: 480
visible: true
title: qsTr("Example3")
// UI ํ์ผ ๋ก๋ฉ / UI file loading
Loader {
anchors.fill: parent
source: "qml/Screen01.qml"
}
}
โ๏ธ Myconnector.cpp
// MyConnector.cpp
#include "MyConnector.h"
MyConnector::MyConnector(QObject *parent) : QObject(parent) {}
void MyConnector::updateText(const QString &text1, const QString &text2) {
QString combined = text1 + " " + text2;
emit resultReady(combined);
}
โ๏ธ CmakeLists.txt
โ๏ธ ์๋์ ๊ตต์ ๊ธ์จ๊ฐ ํ์ผ ์ถ๊ฐ๋ ๋ถ๋ถ์
๋๋ค.
The bold text below is the added portion of the file.
โ๏ธ ๋ฐ๋ก ์๋์ ์ฝ๋๋ ์ง์ ์ถ๊ฐํ ์ฝ๋ ์
๋๋ค.
The code right below is the code I added myself.
qml/Screen01.qml
โ๏ธ๋ฐ๋ก ์๋์ ์ฝ๋๋ ์๋์ผ๋ก ์์ ๋ ๋ด์ฉ์
๋๋ค
The code directly below is automatically corrected.
โ๏ธQT Creator์ Souce Files์์ ๋ง์ฐ์ค ์ค๋ฅธ์ชฝ ํด๋ฆญ,Add New๋ฅผ ์ฌ์ฉํ ๊ฒฝ์ฐ ์๋์ผ๋ก ์๋์ ๋ด์ฉ์ด ์ถ๊ฐ๋ฉ๋๋ค.
If you right-click on Source Files in QT Creator and use Add New, the following will be added automatically.
โ๏ธ์ฌ๊ธฐ์๋ ํด๋์ค ํ์ผ๊ณผ ํค๋ํ์ผ์ ์ถ๊ฐํ์ต๋๋ค.
Here we have added the class file and header file.
SOURCES MyConnector.h
SOURCES MyConnector.cpp
โ๏ธ CmakeLists์ ์ฒด ์ฝ๋ / CmakeLists Full Code
cmake_minimum_required(VERSION 3.16)
project(example3 VERSION 0.1 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt6 REQUIRED COMPONENTS Quick)
qt_standard_project_setup(REQUIRES 6.8)
qt_add_executable(appexample3
main.cpp
)
qt_add_qml_module(appexample3
URI example3
VERSION 1.0
QML_FILES
Main.qml
qml/Screen01.qml
SOURCES MyConnector.h
SOURCES MyConnector.cpp
)
# 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.
set_target_properties(appexample3 PROPERTIES
# MACOSX_BUNDLE_GUI_IDENTIFIER com.example.appexample3
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
MACOSX_BUNDLE TRUE
WIN32_EXECUTABLE TRUE
)
target_link_libraries(appexample3
PRIVATE Qt6::Quick
)
include(GNUInstallDirs)
install(TARGETS appexample3
BUNDLE DESTINATION .
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
3.์คํ / Run
