簡體   English   中英

listviewitem在QML應用程序中不顯示任何數據

[英]listviewitem showing no data in QML application

我有課

  • 數據項
  • 數據模型
  • 接口
  • 網絡連接器

在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 MNetworkConnector : public QObject
{
    Q_OBJECT

public:
    MNetworkConnector(QObject *parent=0);


private:
    QNetworkAccessManager *manager;
    void getData();

private slots:
    void replyFinished(QNetworkReply *r);
    void requireAuth(QNetworkReply *r, QAuthenticator *a);

signals:
    void dataWasChanged(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繼承QAbstractTableModel而不是QAbstractListModel 這不是絕對的問題,因為您可以使用QAbstractTableModel ,但是由於您在QML中使用ListView ,因此您應該更喜歡使用QAbstractListModel

  • 您正在混合角色和列。 這是第一點的結果,因為QAbstractListModel隱藏了列的概念。

  • 您不會發信號通知您更改了數據的模型(因此也沒有視圖/ QML)。 每當基礎數據發生變化時,您必須通過成對調用函數來告知模型,具體取決於變化是: beginResetModel() / endResetModel()beginInsertRows() / endInsertRows()beginRemoveRows() / endRemoveRows()等為此,還有2個未配對的信號: 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.cpp

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;

}

QML修復

delegate: Component
    {
        Rectangle
        {
            width: 250
            height: textItem.height
            Text {
                id: textItem 
                text: host + ' ' + status + ' (' + displayRole +')'
            }
        }
    }

此時,我的MDataModel.h和MDataModel.cpp看起來像這樣:

MDataModel.h

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.cpp

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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM