Qt 5.11 - QML - 在 treeView 中将 XML 文件显示为 QAbstractItemModel

如何解决Qt 5.11 - QML - 在 treeView 中将 XML 文件显示为 QAbstractItemModel

我正在尝试通过 qabstractitemmodel 类在 QML treeView 中显示一个简单的 XML 文件,但我找不到任何关于如何在线执行此操作的体面教程。我设法找到的最好的教程是关于如何在 QWidget 中执行此操作的教程,但我想在 QML 中执行此操作。无论如何,我尝试了我能在这里和那里找到的所有东西,但甚至无法让一棵树出现。

代码可以编译,但我的模型为空。我什至不确定我是否真的在阅读我的 XML 文件

很可能我遗漏了很多东西或做错了很多事情。有人可以帮忙吗?

DomItem.h

#ifndef DOMITEM_H
#define DOMITEM_H
#include <QDomNode>
#include <QHash>

class DomItem
{
    public:
        DomItem(const QDomNode &node,int row,DomItem *parent = nullptr);
        ~DomItem();
        DomItem *child(int i);
        DomItem *parent();
        QDomNode node() const;
        int row() const;

    private:
        QDomNode domNode;
        QHash<int,DomItem *> childItems;
        DomItem *parentItem;
        int rowNumber;
};

#endif // DOMITEM_H

DomItem.cpp

#include "DomItem.h"

DomItem::DomItem(const QDomNode &node,DomItem *parent)
    : domNode(node),parentItem(parent),rowNumber(row)
{

}

DomItem::~DomItem()
{
    qDeleteall(childItems);
}

DomItem *DomItem::parent()
{
    return parentItem;
}

int DomItem::row() const
{
    return rowNumber;
}

QDomNode DomItem::node() const
{
    return domNode;
}

DomItem *DomItem::child(int i)
{
    DomItem *childItem = childItems.value(i);
    if (childItem)
        return childItem;

    // if child does not yet exist,create it
    if (i >= 0 && i < domNode.childNodes().count()) {
        QDomNode childNode = domNode.childNodes().item(i);
        childItem = new DomItem(childNode,i,this);
        childItems[i] = childItem;
    }
    return childItem;
}

DomModel.h

#ifndef DOMMODEL_H
#define DOMMODEL_H
#include <QObject>
#include <QModelIndex>
#include <qabstractitemmodel>
#include <QDomDocument>
#include <QFile>
#include "DomItem.h"

class DomModel : public qabstractitemmodel
{
    Q_OBJECT

    public:
        enum DomModelRoles
        {
            DomModelRoleName = Qt::UserRole + 1,DomModelRoleAttributes,DomModelRoleValue
        };

        explicit DomModel(const QDomDocument &document,QObject *parent = nullptr);
        ~DomModel();

        QVariant data(const QModelIndex &index,int role) const override;
        Qt::ItemFlags flags(const QModelIndex &index) const override;
        QVariant headerData(int section,Qt::Orientation orientation,int role = Qt::displayRole) const override;
        QModelIndex index(int row,int column,const QModelIndex &parent = QModelIndex()) const override;
        QModelIndex parent(const QModelIndex &child) const override;
        int rowCount(const QModelIndex &parent = QModelIndex()) const override;
        int columnCount(const QModelIndex &parent = QModelIndex()) const override;
        void loadXml(QString xmlFilePath);
        void reload();
         QHash<int,QByteArray> roleNames() const override;

    private:
        QDomDocument domDocument;
        DomItem *rootItem;
        QString xmlSource;
};

#endif // DOMMODEL_H

DomModel.cpp

#include "DomModel.h"

DomModel::DomModel(const QDomDocument &document,QObject *parent)
    : qabstractitemmodel(parent),domDocument(document)
{
    rootItem = new DomItem(domDocument,0);
    
}

DomModel::~DomModel()
{
    delete rootItem;
}

int DomModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return 3;
}

Qt::ItemFlags DomModel::flags(const QModelIndex &index) const
{
    if (!index.isValid())
        return Qt::NoItemFlags;

    return qabstractitemmodel::flags(index);
}

QVariant DomModel::headerData(int section,int role) const
{
    if (orientation == Qt::Horizontal && role == Qt::displayRole) {
        switch (section) {
            case 0:
                return tr("Name");
            case 1:
                return tr("Attributes");
            case 2:
                return tr("Value");
            default:
                break;
        }
    }
    return QVariant();
}

QModelIndex DomModel::index(int row,const QModelIndex &parent) const
{
    if (!hasIndex(row,column,parent))
        return QModelIndex();

    DomItem *parentItem;

    if (!parent.isValid())
        parentItem = rootItem;
    else
        parentItem = static_cast<DomItem*>(parent.internalPointer());

    DomItem *childItem = parentItem->child(row);
    if (childItem)
        return createIndex(row,childItem);
    return QModelIndex();
}

int DomModel::rowCount(const QModelIndex &parent) const
{
    if (parent.column() > 0)
        return 0;

    DomItem *parentItem;

    if (!parent.isValid())
        parentItem = rootItem;
    else
        parentItem = static_cast<DomItem*>(parent.internalPointer());

    return parentItem->node().childNodes().count();
}

QModelIndex DomModel::parent(const QModelIndex &child) const
{
    if (!child.isValid())
        return QModelIndex();

    DomItem *childItem = static_cast<DomItem*>(child.internalPointer());
    DomItem *parentItem = childItem->parent();

    if (!parentItem || parentItem == rootItem)
        return QModelIndex();

    return createIndex(parentItem->row(),parentItem);
}

QVariant DomModel::data(const QModelIndex &index,int role) const
{
    if (!index.isValid())
        return QVariant();

    if (role != Qt::displayRole)
        return QVariant();

    const DomItem *item = static_cast<DomItem*>(index.internalPointer());
    const QDomNode node = item->node();

    switch (role)
    {
        case DomModelRoleName:
            return node.nodeName();

        case DomModelRoleAttributes:
        {
            const QDomNamednodeMap attributeMap = node.attributes();
            QStringList attributes;
            for (int i = 0; i < attributeMap.count(); ++i) {
                QDomNode attribute = attributeMap.item(i);
                attributes << attribute.nodeName() + "=\""
                              + attribute.nodeValue() + '"';
            }
            return attributes.join(' ');
        }

        case DomModelRoleValue:
            return node.nodeValue().split('\n').join(' ');

        default:
            break;
    }
    return QVariant();
}

void DomModel::loadXml(QString xmlFilePath)
{
    xmlFilePath.replace("file:///","");
    // on parse le xml de l'environnement
    QFile file(xmlFilePath);
    if (!file.open(qiodevice::ReadOnly| QFile::Text)){
        //QMessageBox::critical(this,"ParserFichierXML","Error");
    }
    else{
        domDocument.clear();
        if (!domDocument.setContent(&file)) {
            //QMessageBox::critical(this,"Error");
        }
        file.close();
    }
    reload();
}

void DomModel::reload()
{
    beginResetModel();
    delete rootItem;
    rootItem = new DomItem(domDocument,false);
    endResetModel();
}

QHash<int,QByteArray> DomModel::roleNames() const
{
    QHash<int,QByteArray> roles;
    roles[DomModelRoleName] = "Name";
    roles[DomModelRoleAttributes] = "Attributes";
    roles[DomModelRoleValue] = "Value";
    return roles;
}

ma​​in.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QDomDocument>
#include <QQmlContext>
#include "DomModel.h"

int main(int argc,char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6,0)
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif

    QGuiApplication app(argc,argv);

    QQmlApplicationEngine engine;
    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine,&QQmlApplicationEngine::objectCreated,&app,[url](QObject *obj,const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    },Qt::QueuedConnection);

    QQmlContext *ctx = engine.rootContext();

    QFile file("./test.xml");
    if (file.open(qiodevice::ReadOnly))
    {
        QDomDocument document;
        if (document.setContent(&file))
        {
            DomModel *model = new DomModel(document);
             ctx->setContextProperty("theModel",model);
        }

    }
    file.close();
    engine.load(url);

    return app.exec();
}

ma​​in.qml

import QtQuick 2.7
import QtQuick.Window 2.2
import QtQuick.Layouts 1.3
import QtQuick.Dialogs 1.2
import QtLocation 5.3
import QtQuick.Controls 1.4
import QtQuick.Controls 2.0
import QtQuick.Controls.Styles 1.4
import QtQml 2.0

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")

    TreeView
    {
        id:treeView
        anchors.fill: parent
        model: theModel
        itemDelegate: TreeDelegate
        {
            id: treeDeleg
        }
        style: TreeViewStyle
        {
            id: styleTree
        }

        TableViewColumn
        {
            id:column1
            role: "Name"
            title: "Name"
            width: 450
        }
        TableViewColumn
        {
            id:column3
            role: "Value"
            title: "Value"
            width: 400
        }

        Component.onCompleted:
        {
             treeView.model = Qt.binding(function()
             {
                 if (typeof theModel !== "undefined")
                 {
                     console.log("Model loaded");
                     return theModel;
                 }
                 else
                 {
                     console.log("Couldn't load model");
                    return null;
                 }
             });
        }
    }
}

TreeDelegate.qml

import QtQuick.Controls 2.1
import QtQuick.Layouts 1.3
import QtQuick 2.7
import QtQml 2.0

Item
{
    id: item
    width : parent.width
    height: 25

    TextEdit
    {
        id: text1
        font.pixelSize: 14
        readOnly: true
        focus: false
        width : parent.width
        height: 25 * lineCount
        anchors.left: parent.left
        wrapMode: TextEdit.Wrap
        text: styleData.value
        verticalAlignment: Text.AlignVCenter
        horizontalAlignment: Text.AlignLeft
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?