Qt Quick 뷰와 함께 C++ 모델 사용하기
사용자 정의 C++ 모델에서 제공되는 데이터
모델은 C++로 정의한 후 QML에서 사용할 수 있도록 할 수 있습니다. 이는 기존 C++ 데이터 모델이나 그 외의 복잡한 데이터 세트를 QML에 노출하는 데 유용합니다.
C++ 모델 클래스는 QStringList, QVariantList, QObjectList 또는 QAbstractItemModel 로 정의할 수 있습니다. 처음 세 가지는 비교적 단순한 데이터 세트를 노출하는 데 유용하며, QAbstractItemModel 는 더 복잡한 모델에 대해 더 유연한 솔루션을 제공합니다.
QStringList 기반 모델
모델은 modelData 역할을 통해 목록의 내용을 제공하는 간단한 QStringList 일 수 있습니다.
다음은 modelData 역할을 사용하여 모델 항목의 값을 참조하는 델리게이트를 가진 ListView 예시입니다:
ListView {
width: 100
height: 100
required model
delegate: Rectangle {
required property string modelData
height: 25
width: 100
Text { text: parent.modelData }
}
}Qt 애플리케이션은 이 QML 문서를 불러와 myModel 의 값을 QStringList 로 설정할 수 있습니다:
QStringList dataList = {
"Item 1",
"Item 2",
"Item 3",
"Item 4"
};
QQuickView view;
view.setInitialProperties({{ "model", QVariant::fromValue(dataList) }});이 예제의 전체 소스 코드는 Qt 설치 디렉터리의 examples/quick/models/stringlistmodel에서 확인할 수 있습니다.
참고: 뷰는 ` QStringList `의 내용이 변경되었는지 알 수있는 방법이 없습니다 . ` QStringList `가 변경되면, 뷰의 ` model ` 속성을 다시 설정하여 모델을 재설정해야 합니다.
QVariantList 기반 모델
모델은 단일 QVariantList 일 수 있으며, 이 경우 modelData 역할을 통해 목록의 내용을 제공합니다.
API는 이전 섹션에서 설명한 바와 같이 QStringList 와 똑같이 작동합니다.
참고: 뷰는 ` QVariantList `의 내용이 변경되었는지 알 수있는 방법이 없습니다 . ` QVariantList `가 변경된 경우, 뷰의 ` model ` 속성을 다시 설정하여 모델을 재설정해야 합니다.
QObjectList 기반 모델
QObject* 값의 목록도 모델로 사용할 수 있습니다. QList<QObject*>는 목록에 포함된 객체들의 속성을 역할(role)로 제공합니다.
다음 애플리케이션은 Q_PROPERTY 값을 가진 DataObject 클래스를 생성하며, QList<DataObject*>가 QML에 노출될 때 이 값들은 명명된 역할로 접근할 수 있게 됩니다:
class DataObject : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
Q_PROPERTY(QString color READ color WRITE setColor NOTIFY colorChanged)
...
};
int main(int argc, char ** argv)
{
QGuiApplication app(argc, argv);
const QStringList colorList = {"red",
"green",
"blue",
"yellow"};
const QStringList moduleList = {"Core", "GUI", "Multimedia", "Multimedia Widgets", "Network",
"QML", "Quick", "Quick Controls", "Quick Dialogs",
"Quick Layouts", "Quick Test", "SQL", "Widgets", "3D",
"Android Extras", "Bluetooth", "Concurrent", "D-Bus",
"Gamepad", "Graphical Effects", "Help", "Image Formats",
"Location", "Mac Extras", "NFC", "OpenGL", "Platform Headers",
"Positioning", "Print Support", "Purchasing", "Quick Extras",
"Quick Timeline", "Quick Widgets", "Remote Objects", "Script",
"SCXML", "Script Tools", "Sensors", "Serial Bus",
"Serial Port", "Speech", "SVG", "UI Tools", "WebEngine",
"WebSockets", "WebView", "Windows Extras", "XML",
"XML Patterns", "Charts", "Network Authorization",
"Virtual Keyboard", "Quick 3D", "Quick WebGL"};
QList<QObject *> dataList;
for (const QString &module : moduleList)
dataList.append(new DataObject("Qt " + module, colorList.at(rand() % colorList.length())));
QQuickView view;
view.setResizeMode(QQuickView::SizeRootObjectToView);
view.setInitialProperties({{ "model", QVariant::fromValue(dataList) }});
...QObject*는 modelData 속성으로 사용할 수 있습니다. 편의상, 객체의 속성은 델리게이트의 컨텍스트에서도 직접 사용할 수 있도록 제공됩니다. 여기서 view.qml 는 ListView 델리게이트의 DataModel 속성을 참조합니다:
ListView {
id: listview
width: 200; height: 320
required model
ScrollBar.vertical: ScrollBar { }
delegate: Rectangle {
width: listview.width; height: 25
required color
required property string name
Text { text: parent.name }
}
}color 속성의 사용법에 유의하십시오. 파생 유형에서 속성을 required 로 선언하여 기존 속성을 요구할 수 있습니다.
이 예제의 전체 소스 코드는 Qt 설치 디렉터리의 examples/quick/models/objectlistmodel에서 확인할 수 있습니다.
참고: 뷰는 ` QObjectList `의 내용이 변경되었는지 알 수있는 방법이 없습니다 . ` QObjectList `이 변경되면, 뷰의 ` model ` 속성을 다시 설정하여 모델을 재설정해야 합니다.
QAbstractItemModel의 서브클래스
QAbstractItemModel 을 상속하여 모델을 정의할 수 있습니다. 이는 다른 방법으로는 지원할 수 없는 더 복잡한 모델을 다루는 경우 가장 적합한 접근 방식입니다. 또한 QAbstractItemModel 은 모델 데이터가 변경될 때 QML 뷰에 자동으로 알릴 수 있습니다.
QAbstractItemModel 의 서브클래스의 역할은 QAbstractItemModel::roleNames()을 재구현하여 QML에 노출할 수 있습니다.
다음은 AnimalModel 라는 이름의 QAbstractListModel 하위 클래스를 사용하는 애플리케이션으로, 이 클래스는 type 및 sizes 역할을 노출합니다. 이 클래스는 QAbstractItemModel::roleNames()를 재구현하여 역할 이름을 노출함으로써, QML을 통해 해당 역할에 접근할 수 있도록 합니다:
class Animal
{
public:
Animal(const QString &type, const QString &size);
...
};
class AnimalModel : public QAbstractListModel
{
Q_OBJECT
public:
enum AnimalRoles {
TypeRole = Qt::UserRole + 1,
SizeRole
};
AnimalModel(QObject *parent = nullptr);
...
};
QHash<int, QByteArray> AnimalModel::roleNames() const {
QHash<int, QByteArray> roles;
roles[TypeRole] = "type";
roles[SizeRole] = "size";
return roles;
}
int main(int argc, char ** argv)
{
QGuiApplication app(argc, argv);
AnimalModel model;
model.addAnimal(Animal("Wolf", "Medium"));
model.addAnimal(Animal("Polar bear", "Large"));
model.addAnimal(Animal("Quoll", "Small"));
QQuickView view;
view.setResizeMode(QQuickView::SizeRootObjectToView);
view.setInitialProperties({{"model", QVariant::fromValue(&model)}});
...이 모델은 type 및 size 역할을 액세스하는 ListView 델리게이트를 통해 표시됩니다:
ListView {
width: 200; height: 250
required model
delegate: Text {
required property string type
required property string size
text: "Animal: " + type + ", " + size
}
}모델이 변경되면 QML 뷰가 자동으로 업데이트됩니다. 모델은 모델 변경에 대한 표준 규칙을 따라야 하며, QAbstractItemModel::dataChanged(), QAbstractItemModel::beginInsertRows() 등을 사용하여 모델이 변경되었을 때 뷰에 알리어야 한다는 점을 기억하십시오. 자세한 내용은 모델 서브클래싱 참조를 참조하십시오.
이 예제의 전체 소스 코드는 Qt 설치 디렉터리의 examples/quick/models/abstractitemmodel에서 확인할 수 있습니다.
QAbstractItemModel 는 테이블의 계층 구조를 나타내지만, 현재 QML에서 제공하는 뷰는 목록 데이터만 표시할 수 있습니다. 계층적 모델의 자식 목록을 표시하려면 DelegateModel QML 유형을 사용하십시오. 이 유형은 QAbstractItemModel 유형의 목록 모델과 함께 사용할 수 있는 다음과 같은 속성과 함수를 제공합니다:
- hasModelChildren 역할 속성을 사용하여 노드에 자식 노드가 있는지 여부를 확인할 수 있습니다.
- DelegateModel::rootIndex 루트 노드를 지정할 수 있게 해줍니다.
- DelegateModel::modelIndex()는 QModelIndex 를 반환하며, 이를 다음의 대상에 할당할 수 있습니다: DelegateModel::rootIndex
- DelegateModel::parentModelIndex()는 QModelIndex 를 반환하며, 이를 다음 대상에 할당할 수 있습니다. DelegateModel::rootIndex
C++ 데이터 모델을 QML에 노출하기
위의 예제에서는 뷰의 필수 속성을 사용하여 QML 컴포넌트 내에서 모델 값을 직접 설정합니다. 이에 대한 대안으로 C++ 모델 클래스를 QML 유형으로 등록할 수 있습니다( ‘C++에서 QML 유형 정의’ 참조). 이를 통해 모델 클래스를 QML 내의 유형으로 직접 생성할 수 있습니다:
| C++ | |
| QML | |
C++에서 QML 타입을 작성하는 방법에 대한 자세한 내용은 C++로 QML 확장 작성하기를 참조하십시오.
모델 데이터 변경
roleNames() 및 data() 외에도, 편집 가능한 모델은 기존 모델 데이터의 변경 사항을 저장하기 위해 setData 메서드를 재구현해야 합니다. 다음 메서드 구현은 주어진 모델 인덱스가 유효한지, 그리고 role 가 Qt::EditRole 와 동일한지 확인합니다:
bool EditableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (index.isValid() && role == Qt::EditRole) {
// Set data in model here. It can also be a good idea to check whether
// the new value actually differs from the current value
if (m_entries[index.row()] != value.toString()) {
m_entries[index.row()] = value.toString();
emit dataChanged(index, index, { Qt::EditRole, Qt::DisplayRole });
return true;
}
}
return false;
}참고: 변경 사항을 저장한 후 dataChanged() 신호를 발산하는것이 중요합니다.
QListView 이나 QTableView 과 같은 C++ 항목 뷰와 달리, setData() 메서드는 적절한 경우 QML 델리게이트에서 명시적으로 호출해야 합니다. 이는 해당 모델 속성에 새 값을 할당하기만 하면 됩니다.
ListView {
anchors.fill: parent
model: EditableModel {}
delegate: TextField {
width: ListView.view.width
text: model.edit
onAccepted: model.edit = text
}
}참고: edit 역할은 Qt::EditRole 과 동일합니다. 내장된 역할 이름에 대해서는 roleNames()을 참조하십시오. 그러나 실제 모델에서는 대개 사용자 정의 역할을 등록합니다.
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.