티스토리 뷰

개발/QT, QML

[QT,QML] Qt의 QAbstractListModel

부캐: 개발하는 조대리 2024. 11. 9. 10:55
반응형

Qt의 QAbstractListModel

QAbstractListModel은 Qt 모델-뷰 프레임워크의 일부로, 리스트 형태의 데이터를 QML에서 사용할 수 있도록 제공하는 추상 클래스입니다. 이 클래스는 데이터를 리스트 형식으로 관리하고, 그 데이터를 뷰(view)에 표시할 때 기본이 되는 기능을 제공하며, 이를 상속받아 사용자 정의 모델을 구현할 수 있습니다.

QAbstractListModel은 특히 QML의 ListView, Repeater, GridView와 같은 UI 컴포넌트와 잘 결합하여 동적이고 반응적인 리스트를 생성할 때 유용합니다.

 

 

 

 모델-뷰 구조

  • 모델 (Model): 데이터를 관리하는 역할. QAbstractListModel은 이 역할을 수행합니다.
  • (View): 데이터를 시각적으로 표현하는 역할. 예를 들어 QML의 ListView는 모델의 데이터를 시각적으로 표시합니다.

QAbstractListModel을 사용하면 데이터를 관리하는 로직과 이를 시각적으로 표현하는 로직을 분리할 수 있어, 코드의 재사용성과 유지보수성이 크게 향상됩니다.

 

 

 

 QAbstractListModel의 주요 기능

QAbstractListModel은 리스트 데이터를 쉽게 관리하고 QML과 연결할 수 있는 몇 가지 주요 메서드와 기능을 제공합니다.

핵심 메서드 및 멤버 함수

  • rowCount(const QModelIndex &parent) const:
    • 모델의 총 행(row)의 개수를 반환합니다.
    • 뷰에서 모델의 데이터가 얼마나 있는지 알 수 있게 합니다.
  • data(const QModelIndex &index, int role = Qt::DisplayRole) const:
    • 특정 행의 데이터와 역할(roles)을 기반으로 데이터를 반환합니다.
    • index는 행을 나타내며, role은 반환할 데이터의 종류를 지정합니다.
  • roleNames() const:
    • 사용자 정의 역할(roles)을 정의하여 QML에서 이 데이터를 참조할 수 있게 합니다.
    • role은 데이터의 속성을 나타내며, QML에서는 이 이름을 통해 접근합니다.
  • setData(const QModelIndex &index, const QVariant &value, int role) (선택적):
    • 모델의 데이터를 수정하는 데 사용됩니다.
    • 데이터가 변경되면 자동으로 UI에도 반영됩니다.
  • insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) 및 removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) (선택적):
    • 모델에 행을 추가하거나 제거할 때 사용됩니다.

 

 

 

 QAbstractListModel을 상속하여 사용자 정의 모델 구현하기

다음 예제는 QAbstractListModel을 상속하여 간단한 사용자 정의 모델을 구현하고, 이를 QML에서 사용하는 방법을 보여줍니다.

#include <QAbstractListModel>
#include <QStringList>

class MyListModel : public QAbstractListModel {
    Q_OBJECT

public:
    enum Roles {
        NameRole = Qt::UserRole + 1,
        AgeRole
    };

    explicit MyListModel(QObject *parent = nullptr)
        : QAbstractListModel(parent) {
        // 초기 데이터를 설정
        m_data.append({"Alice", 25});
        m_data.append({"Bob", 30});
        m_data.append({"Charlie", 22});
    }

    int rowCount(const QModelIndex &parent = QModelIndex()) const override {
        Q_UNUSED(parent);
        return m_data.count();
    }

    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override {
        if (index.row() < 0 || index.row() >= m_data.count())
            return QVariant();

        const Person &person = m_data[index.row()];
        if (role == NameRole)
            return person.name;
        else if (role == AgeRole)
            return person.age;

        return QVariant();
    }

    QHash<int, QByteArray> roleNames() const override {
        QHash<int, QByteArray> roles;
        roles[NameRole] = "name";
        roles[AgeRole] = "age";
        return roles;
    }

private:
    struct Person {
        QString name;
        int age;
    };

    QList<Person> m_data;
};

설명

  • MyListModel 클래스는 QAbstractListModel을 상속받아 구현된 사용자 정의 모델입니다.
  • Roles 열거형은 QML에서 접근할 데이터의 역할을 정의합니다. Qt::UserRole + 1부터 사용하여 사용자 정의 역할을 설정합니다.
  • rowCount(): 모델의 행 수를 반환합니다.
  • data(): 특정 행의 데이터를 반환합니다. 여기서는 NameRole과 AgeRole을 통해 이름과 나이를 반환합니다.
  • roleNames(): QML에서 사용할 수 있도록 역할의 이름을 정의합니다. 이 이름을 통해 QML에서 모델의 데이터를 참조할 수 있습니다.

 

 

 

 QML에서 사용자 정의 모델 사용하기

이제 C++에서 정의한 모델을 QML에서 사용할 수 있습니다. 모델을 QML 컨텍스트에 등록하고, QML의 ListView를 통해 데이터를 시각화합니다.

 

C++에서 QML에 모델 등록:

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "MyListModel.h"

int main(int argc, char *argv[]) {
    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;

    MyListModel model;

    // QML 컨텍스트에 모델 등록
    engine.rootContext()->setContextProperty("myModel", &model);

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}

 

 

main.qml:

import QtQuick 2.15
import QtQuick.Controls 2.15

ApplicationWindow {
    visible: true
    width: 640
    height: 480

    ListView {
        anchors.fill: parent
        model: myModel

        delegate: Item {
            height: 50
            Row {
                spacing: 10
                Text { text: name } // roleNames에서 정의한 "name"
                Text { text: age.toString() } // roleNames에서 정의한 "age"
            }
        }
    }
}

설명

  • model: myModel: C++에서 등록한 myModel을 사용하여 ListView의 모델로 지정합니다.
  • delegate: 각 행의 데이터를 시각적으로 표현하는 데 사용됩니다. name과 age 역할을 통해 모델의 데이터를 참조합니다.

 

 

 

 요약

  • QAbstractListModel은 리스트 형태의 데이터를 관리하고, 이를 뷰와 연동하는 데 필요한 기능을 제공합니다.
  • 이를 상속받아 사용자 정의 모델을 구현할 수 있으며, QML과 결합하여 반응적이고 동적인 UI를 쉽게 만들 수 있습니다.
  • QML에서의 사용을 위해서는 역할(role)을 정의하고, 데이터를 QML에 등록하여 ListView 등과 연결하면 됩니다.
  • 모델-뷰 구조를 사용하면 데이터와 UI 간의 분리를 통해 코드의 유지보수성확장성이 크게 향상됩니다.

 

QAbstractListModel을 사용한 C++과 QML의 결합은 복잡한 데이터를 효율적으로 관리하고 이를 직관적이고 아름다운 UI로 표현하는 데 매우 유용합니다.

 

 


 

 

 

개인적으로 학습하면서 정리한 내용입니다.
잘못된 내용이 있을 경우 알려주시면 확인 후 수정 및 반영하도록 하겠습니다.

오늘도 감사합니다.(__)

'개발 > QT, QML' 카테고리의 다른 글

QML의 ParallelAnimation  (1) 2024.11.11
QML의 positionViewAtIndex 함수  (0) 2024.11.10
[QT,QML] C++과 QML 간의 시그널-슬롯 통신  (0) 2024.11.08
[QT,QML] QML의 Connections  (2) 2024.11.07
[QT,QML] Q_PROPERTY의 MEMBER 키워드  (5) 2024.11.06