C++ listviewitem在QML应用程序中不显示任何数据

C++ listviewitem在QML应用程序中不显示任何数据,c++,qt,model,qml,C++,Qt,Model,Qml,我有很多课 数据项 数据模型 接口 网络连接器 在dataitem中指定了项属性 class MDataItem : public QObject { Q_OBJECT Q_PROPERTY(QString host READ host WRITE setHost NOTIFY hostChanged) Q_PROPERTY(QString service READ service WRITE setService NOTIFY serviceChanged)

我有很多课

  • 数据项
  • 数据模型
  • 接口
  • 网络连接器
在dataitem中指定了项属性

class MDataItem : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString host READ host WRITE setHost NOTIFY hostChanged)
    Q_PROPERTY(QString service READ service WRITE setService NOTIFY serviceChanged)
    Q_PROPERTY(QString status READ status WRITE setStatus NOTIFY statusChanged)
    Q_PROPERTY(QString lastchck READ lastchck WRITE setLastChck NOTIFY lastchckChanged)
    Q_PROPERTY(QString duration READ duration WRITE setDuration NOTIFY durationChanged)
    Q_PROPERTY(QString info READ info WRITE setInfo NOTIFY infoChanged)

public:
    explicit MDataItem(QObject *parent = 0);

    QString host() const;
    void setHost(const QString &newhost);

    QString service() const;
    void setService(const QString &newservice);

    QString status() const;
    void setStatus(const QString &newstatus);

    QString lastchck() const;
    void setLastChck(const QString &newlastchck);

    QString duration() const;
    void setDuration(const QString &newduration);

    QString info() const;
    void setInfo(const QString &newinfo);

signals:
    void hostChanged();
    void serviceChanged();
    void statusChanged();
    void lastchckChanged();
    void durationChanged();
    void infoChanged();

private:
    QString m_host;
    QString m_service;
    QString m_status;
    QString m_lastchck;
    QString m_duration;
    QString m_info;
};
模型中包含模型规范

class MDataModel : public QAbstractTableModel
{

public:
    enum Columns{
            Host = Qt::UserRole,
            Service = Qt::UserRole + 1,
            Status = Qt::UserRole + 2,
            Duration = Qt::UserRole + 3,
            Info = Qt::UserRole + 4
        };
    MDataModel(QObject *parent = 0);
    QHash<int, QByteArray> roleNames() const;
    void fillData(QNetworkReply *r);
    int rowCount(const QModelIndex &parent) const;
    int columnCount(const QModelIndex &parent) const;
    QVariant data(const QModelIndex &index, int role) const;
    QVariant headerData(int section, Qt::Orientation orientation, int role) const;

private:
    QString dataAt(int offset) const;
    QList<MDataItem*> items_;

public:
    void prepareDataFinished(QNetworkReply *r);

};
在接口中,网络填充模型中的数据:

class MInterface : public QObject
{
    Q_OBJECT

public:
    MInterface();
    MDataModel *mainModel;
    MNetworkConnector *newConnection;
    MDataModel* getModel();

public slots:
    void dataWasPrepared(QNetworkReply *r);
};
在这一点上,一切都是好的。在调试程序中,我看到数据以正确的MDataItem格式存在于模型中

但当我将模型添加到QML listView时,应用程序什么也不显示。 问题在哪里?你能把我推到正确的方向吗

Main.cpp如下所示:

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    MInterface *myIface = new MInterface();

    QQmlApplicationEngine engine;
    engine.rootContext()->setContextProperty("MainModel", myIface->getModel());
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}
主qml文件:

import QtQuick 2.5
import QtQuick.Window 2.2
import QtQml 2.0


Window {
    visible: true
    width:  Screen.width / 2
    height: Screen.height / 2

    title: qsTr("webinfo")

    ListView
    {
        id: myList
        visible: true

        header: Header{}
        model: MainModel
        delegate: Item
        {
            Rectangle
            {
                Text { text: host }
            }
        }
    }
}
当我在modedata类和应该返回数据的函数中设置调试程序断点时,调试程序不会停止在那里。看起来程序从未进入这个函数

也许问题在于我如何设置模型?函数
getmodel()
仅返回指针。 main.cpp:

engine.rootContext()->setContextProperty("MainModel", myIface->getModel());
minterface.cpp:

MDataModel* MInterface::getModel()
{
    return this->mainModel;
}
有一个MDataModel.cpp

MDataModel::MDataModel(QObject *parent) : QAbstractTableModel(parent)
{
}

int MDataModel::rowCount(const QModelIndex & /* parent */) const
{
    return items_.count();
}

int MDataModel::columnCount(const QModelIndex & /* parent */) const
{
    return 5;
}

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

    if (role == Qt::DisplayRole)
    {
        switch(index.column()){
            case Columns::Host:
                return items_.value(index.row())->host();

            case Columns::Service:
                return items_.value(index.row())->service();

            case Columns::Status:
                return items_.value(index.row())->status();

            case Columns::Duration:
                return items_.value(index.row())->duration();

            case Columns::Info:
                return items_.value(index.row())->info();
        }
    }
    return QVariant();
}

QVariant MDataModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (role != Qt::DisplayRole)
        return QVariant();

    if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
    {
        switch(section){
            case Columns::Host:
                return tr("Host");
            case Columns::Service:
                return tr("Service");
            case Columns::Status:
                return tr("Status");
            case Columns::Duration:
                return tr("Duration");
            case Columns::Info:
                return tr("Info");
        }
    }
    return QVariant();
}


void MDataModel::prepareDataFinished(QNetworkReply *r)
{
    QList<MDataItem*> newItems;
    MDataItem *item = new MDataItem();

    QString data;

    while(r->canReadLine())
    {
        data = r->readLine();

            item = new MDataItem();

            if(data.contains("warning", Qt::CaseInsensitive))
            {
                item->setStatus("WARNING");
            }
            else if(data.contains("critical", Qt::CaseInsensitive))
            {
                item->setStatus("CRITICAL");
            }
            else if(data.contains("unknown", Qt::CaseInsensitive))
            {
                item->setStatus("UNKNOWN");
            }
            item->setHost(reg.cap(0).replace("host=","").toUpper());
        ...
        ...
        }
    }
    items_ = newItems;
    qDebug() << items_;

}

QHash<int, QByteArray> MDataModel::roleNames() const
{
    QHash<int, QByteArray> roles;

    roles[Columns::Host] = "host";
    roles[Columns::Service] = "service";
    roles[Columns::Status] = "status";
    roles[Columns::Duration] = "duration";
    roles[Columns::Info] = "info";

    return roles;
}
MDataModel::MDataModel(QObject *parent) : QAbstractListModel(parent)
{
}

int MDataModel::rowCount(const QModelIndex & /* parent */) const
{
    return items_.count();
}


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

    if (role == Qt::DisplayRole)
    {
        switch(index.column()){
            case host:
                return items_.value(index.row())->host();

            case service:
                return items_.value(index.row())->service();

            case status:
                return items_.value(index.row())->status();

            case duration:
                return items_.value(index.row())->duration();

            case info:
                return items_.value(index.row())->info();

        }
    }

    return QVariant();
}


void MDataModel::prepareDataFinished(QNetworkReply *r)
{
    QList<MDataItem*> newItems;
    MDataItem *item = new MDataItem();

    QString data;

    while(r->canReadLine())
    {
        data = r->readLine();

        QRegExp reg;
        if(data.contains("statusbgwarning'><a href", Qt::CaseInsensitive) || data.contains("statusbgcritical'><a href", Qt::CaseInsensitive) || data.contains("statusbgunknown'><a href", Qt::CaseInsensitive))
        {
            item = new MDataItem();
            newItems.append(item);

            if(data.contains("warning", Qt::CaseInsensitive))
            {
                item->setStatus("WARNING");
            }
            else if(data.contains("critical", Qt::CaseInsensitive))
            {
                item->setStatus("CRITICAL");
            }
            else if(data.contains("unknown", Qt::CaseInsensitive))
            {
                item->setStatus("UNKNOWN");
            }
        ...
        ...
    }
    // Call beginResetModel() and endResetModel() to tell the model
    // and the view the data changed.
    beginResetModel();
    items_ = newItems;
    endResetModel();
}


QHash<int, QByteArray> MDataModel::roleNames() const
{
    QHash<int, QByteArray> roles;

    roles[host] = "host";
    roles[service] = "service";
    roles[status] = "status";
    roles[duration] = "duration";
    roles[info] = "info";

    return roles;
}
MDataModel::MDataModel(QObject*parent):QAbstractTableModel(parent)
{
}
int-MDataModel::行计数(常量QModelIndex&/*父*/)常量
{
返回项目数();
}
int-MDataModel::columnCount(常量QModelIndex&/*parent*/)常量
{
返回5;
}
QVariant MDataModel::数据(常量QModelIndex&index,int角色)常量
{
如果(!index.isValid())
{
返回QVariant();
}
如果(角色==Qt::DisplayRole)
{
开关(index.column()){
案例列::主机:
返回items.value(index.row())->host();
案例列::服务:
返回items.value(index.row())->service();
案例列::状态:
返回项目值(index.row())->status();
案例列::持续时间:
返回项目值(index.row())->duration();
案例列::信息:
返回项目值(index.row())->info();
}
}
返回QVariant();
}
QVariant MDataModel::headerData(int节,Qt::定向,int角色)常量
{
if(角色!=Qt::DisplayRole)
返回QVariant();
if(方向==Qt::水平和角色==Qt::显示角色)
{
道岔(区段){
案例列::主机:
返回tr(“主机”);
案例列::服务:
返回tr(“服务”);
案例列::状态:
返回tr(“状态”);
案例列::持续时间:
返回tr(“持续时间”);
案例列::信息:
返回tr(“信息”);
}
}
返回QVariant();
}
void MDataModel::prepareDataFinished(QNetworkReply*r)
{
QList新项目;
MDataItem*item=新的MDataItem();
QString数据;
而(r->canReadLine())
{
data=r->readLine();
item=新的MDataItem();
if(data.contains(“警告”,Qt::case不敏感))
{
项目->设置状态(“警告”);
}
else if(data.contains(“critical”,Qt::CaseSensitive))
{
项目->设置状态(“关键”);
}
else if(data.contains(“未知”,Qt::case不敏感))
{
项目->设置状态(“未知”);
}
item->setHost(reg.cap(0).replace(“host=,”).toUpper());
...
...
}
}
项目=新项目;

qDebug()您的主要问题是:

  • MDataModel
    继承
    QAbstractTableModel
    而不是
    QAbstractListModel
    。这不是一个绝对的问题,因为您可以使用
    QAbstractTableModel
    ,但由于您在QML中使用的是
    ListView
    ,您应该更喜欢使用
    QAbstractTableModel

  • 您正在混合角色和列。这是第一点的结果,因为
    QAbstractListModel
    隐藏了列的概念

  • 您不会向更改数据的模型(以及视图/QML)发送信号。每当基础数据发生更改时,必须通过成对调用函数来告诉模型,具体取决于更改的内容:
    beginResetModel()
    /
    endResetModel()
    beginInsertRows()
    /
    endInsertRows()
    beginRemoveRows()
    /
    endRemoveRows()
    ,还有两个未配对的信号用于此目的:
    dataChanged()
    modelReset()
    。请注意,您可以通过始终调用
    modelReset()
    来摆脱困境,但这不是一个好的做法,您应该倾向于使用最特殊的函数对
您还应该阅读Qt文档:

这是你们的固定模型。我删除了
columnCount()
headerData()
,因为您不需要它们来让它工作

MDataModel.h

class MDataModel : public QAbstractListModel
{

public:
    enum Role{
            Host = Qt::UserRole,
            Service,
            Status,
            Duration,
            Info
        };
    MDataModel(QObject *parent = 0);
    QHash<int, QByteArray> roleNames() const;
    void fillData(QNetworkReply *r);
    int rowCount(const QModelIndex &parent) const;
    QVariant data(const QModelIndex &index, int role) const;

private:
    QString dataAt(int offset) const;
    QList<MDataItem*> items_;

public:
    void prepareDataFinished(QNetworkReply *r);

};

你的主要问题是:

  • MDataModel
    继承
    QAbstractTableModel
    而不是
    QAbstractListModel
    。这不是一个绝对的问题,因为您可以使用
    QAbstractTableModel
    ,但由于您在QML中使用的是
    ListView
    ,您应该更喜欢使用
    QAbstractTableModel

  • 您正在混合角色和列。这是第一点的结果,因为
    QAbstractListModel
    隐藏了列的概念

  • 您不会向更改数据的模型(以及视图/QML)发送信号。每当基础数据发生更改时,必须通过成对调用函数来告诉模型,具体取决于更改的内容:
    beginResetModel()
    /
    endResetModel()
    beginInsertRows()
    /
    endInsertRows()
    beginRemoveRows()
    /
    endRemoveRows()
    ,还有两个未配对的信号用于此目的:
    dataChanged()
    modelReset()
    。请注意,您可以通过始终调用
    modelReset()
    来摆脱这种情况,但这不是一种好的做法,您可以
    MDataModel::MDataModel(QObject *parent) : QAbstractListModel(parent)
    {
    }
    
    int MDataModel::rowCount(const QModelIndex & /* parent */) const
    {
        return items_.count();
    }
    
    
    QVariant MDataModel::data(const QModelIndex &index, int role) const
    {
        if (!index.isValid())
        {
            return QVariant();
        }
    
    
        switch(role){
            // For C++ views
            case Qt::DisplayRole:
                return items_.value(index.row())->host();
    
    
            // For QML views
            case Host:
                return items_.value(index.row())->host();
    
            case Service:
                return items_.value(index.row())->service();
    
            case Status:
                return items_.value(index.row())->status();
    
            case Duration:
                return items_.value(index.row())->duration();
    
            case Info:
                return items_.value(index.row())->info();
    
        }
        return QVariant();
    }
    
    
    
    void MDataModel::prepareDataFinished(QNetworkReply *r)
    {
        QList<MDataItem*> newItems;
        MDataItem *item = new MDataItem();
    
        QString data;
    
        while(r->canReadLine())
        {
            data = r->readLine();
    
                item = new MDataItem();
    
                if(data.contains("warning", Qt::CaseInsensitive))
                {
                    item->setStatus("WARNING");
                }
                else if(data.contains("critical", Qt::CaseInsensitive))
                {
                    item->setStatus("CRITICAL");
                }
                else if(data.contains("unknown", Qt::CaseInsensitive))
                {
                    item->setStatus("UNKNOWN");
                }
                item->setHost(reg.cap(0).replace("host=","").toUpper());
            ...
            ...
            }
        }
    
        // Call beginResetModel() and endResetModel() to tell the model
        // and the view the data changed.
        beginResetModel();
        items_ = newItems;
        endResetModel();
        qDebug() << items_;
    
    }
    
    QHash<int, QByteArray> MDataModel::roleNames() const
    {
        QHash<int, QByteArray> roles;
    
        roles[Host] = "host";
        roles[Service] = "service";
        roles[Status] = "status";
        roles[Duration] = "duration";
        roles[Info] = "info";
    
        // Add displayRole so that you can get what C++ views displays in QML
        // e.g Text { text: host + ' ' + status + ' (' + displayRole +')' }
        roles[Qt::DisplayRole] = "displayRole";
    
        return roles;
    
    }
    
    delegate: Component
        {
            Rectangle
            {
                width: 250
                height: textItem.height
                Text {
                    id: textItem 
                    text: host + ' ' + status + ' (' + displayRole +')'
                }
            }
        }
    
    class MDataModel : public QAbstractListModel
    {
    
    public:
        enum icingaRoles{
                host,
                service,
                status,
                duration,
                info
            };
        MDataModel(QObject *parent = 0);
        QHash<int, QByteArray> roleNames() const;
        void fillData(QNetworkReply *r);
        int rowCount(const QModelIndex &parent) const;
        QVariant data(const QModelIndex &index, int role) const;
    
    private:
        QString dataAt(int offset) const;
        QList<MDataItem*> items_;
    
    public:
        void prepareDataFinished(QNetworkReply *r);
    
    };
    
    MDataModel::MDataModel(QObject *parent) : QAbstractListModel(parent)
    {
    }
    
    int MDataModel::rowCount(const QModelIndex & /* parent */) const
    {
        return items_.count();
    }
    
    
    QVariant MDataModel::data(const QModelIndex &index, int role) const
    {
        if (!index.isValid())
        {
            return QVariant();
        }
    
        if (role == Qt::DisplayRole)
        {
            switch(index.column()){
                case host:
                    return items_.value(index.row())->host();
    
                case service:
                    return items_.value(index.row())->service();
    
                case status:
                    return items_.value(index.row())->status();
    
                case duration:
                    return items_.value(index.row())->duration();
    
                case info:
                    return items_.value(index.row())->info();
    
            }
        }
    
        return QVariant();
    }
    
    
    void MDataModel::prepareDataFinished(QNetworkReply *r)
    {
        QList<MDataItem*> newItems;
        MDataItem *item = new MDataItem();
    
        QString data;
    
        while(r->canReadLine())
        {
            data = r->readLine();
    
            QRegExp reg;
            if(data.contains("statusbgwarning'><a href", Qt::CaseInsensitive) || data.contains("statusbgcritical'><a href", Qt::CaseInsensitive) || data.contains("statusbgunknown'><a href", Qt::CaseInsensitive))
            {
                item = new MDataItem();
                newItems.append(item);
    
                if(data.contains("warning", Qt::CaseInsensitive))
                {
                    item->setStatus("WARNING");
                }
                else if(data.contains("critical", Qt::CaseInsensitive))
                {
                    item->setStatus("CRITICAL");
                }
                else if(data.contains("unknown", Qt::CaseInsensitive))
                {
                    item->setStatus("UNKNOWN");
                }
            ...
            ...
        }
        // Call beginResetModel() and endResetModel() to tell the model
        // and the view the data changed.
        beginResetModel();
        items_ = newItems;
        endResetModel();
    }
    
    
    QHash<int, QByteArray> MDataModel::roleNames() const
    {
        QHash<int, QByteArray> roles;
    
        roles[host] = "host";
        roles[service] = "service";
        roles[status] = "status";
        roles[duration] = "duration";
        roles[info] = "info";
    
        return roles;
    }