Qml과 C++로 구현하는 GUI어플리케이션, 두번째 글로 C++로 작성한 클래스를 QML에서 생성하고 사용하는 방법이다.
C++과 QML 을 통합하는 방법중 QQmlContext의 setContextProperty 라는 메서드를 사용하면 C++ 코드에서 이미 생성된 객체를 QML 컨텍스트에 등록하여 QML에서 C++ 클래스의 메서드 및 프로퍼티에 접근할 수 있음을 기억할 것이다. 이 경우 QQmlContext 에서 객체의 소유권을 갖지 않기 때문에 객체가 더 이상 사용되지 않을 때(프로그램 종료)에 객체를 파괴 해줘야 한다.
반면 qmlRegisterType 템플릿 함수는 QML 시스템에 C++ 로 작성된 유형을 등록하고 QML컨텍스트에서 직접 생성한다.
File을 읽고 쓰는 간단한 C++클래스를 작성하고 qmlRegisterType 함수를 이용해 이 클래스를 등록하여 최종적으로 QML에서 파일을 읽고 쓰는 예제를 작성해 본다.
FileIO 클래스의 헤더 파일이다. FileIO 구현은 간단하다. read, write 메서스와 source, text 프로퍼티 가 있는 간단한 클래스다.
fileio.h
#include <QtCore>
class FileIO : public QObject
{
Q_OBJECT
Q_DISABLE_COPY(FileIO)
Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
public:
FileIO(QObject *parent = nullptr);
~FileIO() override;
Q_INVOKABLE void read();
Q_INVOKABLE void write();
QUrl source() const;
QString text() const;
public slots:
void setSource(QUrl source);
void setText(QString text);
signals:
void sourceChanged(QUrl arg);
void textChanged(QString arg);
private:
QUrl m_source;
QString m_text;
};
read 메서드는 읽기 모드에서 파일을 열고 텍스트 스트림을 사용하여 데이터를 읽는다. 텍스트가 변경되면 emit textChanged(m_text)를 사용하여 변경 사항을 외부에 알려야한다.
void FileIO::read()
{
if(m_source.isEmpty()) {
return;
}
QFile file(m_source.toLocalFile());
if(!file.exists()) {
qWarning() << "Does not exits: " << m_source.toLocalFile();
return;
}
if(file.open(QIODevice::ReadOnly)) {
QTextStream stream(&file);
m_text = stream.readAll();
emit textChanged(m_text);
}
}
write 메서드는 동일한 작업을 수행하지만 파일을 쓰기 모드로 열고 스트림을 사용하여 내용을 쓴다.
void FileIO::write()
{
if(m_source.isEmpty()) {
return;
}
QFile file(m_source.toLocalFile());
if(file.open(QIODevice::WriteOnly)) {
QTextStream stream(&file);
stream << m_text;
}
}
이제 qmlRegisterType 템플릿 함수를 호출하여 작성한 클래스를 QML 컨텍스트에 등록한다. 이때 네임스페이스 문자열( "net.makersweb.file"), 메이져 버전, 마이너 버전 번호, 그리고 QML 타입 이름을 지정한다.
#include "fileio.h"
...
qmlRegisterType<FileIO>("net.makersweb.file", 1, 0, "FileIO");
...
QML에서 등록된 유형을 사용하기위해 import net.makersweb.file 1.0 를 포함한다. 다음은 FileIO 를 사용하는 간단한 QML 코드이다.
main.qml
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import QtQuick.Dialogs 1.2
import net.makersweb.file 1.0
Window {
id: window
visible: true
width: 640
height: 480
property FileIO backend: FileIO{}
FileDialog{
id: dialog
onAccepted: {
backend.setSource(window.title = dialog.fileUrl)
backend.read()
text.text = backend.text
}
}
Column {
anchors.fill: parent
Row {
id: buttons
anchors.horizontalCenter: parent.horizontalCenter
Button {
id: open
text: qsTr("Open")
onClicked: {
dialog.open()
}
}
Button {
id: save
text: qsTr("Save")
onClicked: {
backend.text = text.text
backend.write()
}
}
}
ScrollView {
id: view
contentHeight: Window.height - buttons.height
contentWidth: parent.width
TextArea {
id: text
selectByMouse: true
}
}
}
}
프로그램을 실행 후 Open 버튼을 클릭 후 텍스트 파일을 읽고, 써지는 것을 확인 할 수 있다.
본문에서 사용된 FileIO 클래스 출처: http://qmlbook.github.io/ch18-extensions/extensions.html#using-fileio