listviewitem在QML应用程序中没有显示数据
listviewitem showing no data in QML application
我有一个类。
- dataitem datamodel
- 界面
- networkconnector
在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 }
}
}
}
}
当我将调试器断点设置到我的moddata类和应该返回数据的函数中时,调试器不会停止在那里。看起来程序永远不会进入这个函数。
也许问题是我如何设置模型?功能getmodel()
只返回指针。main.cpp:
engine.rootContext()->setContextProperty("MainModel", myIface->getModel());
minterface.cpp:
MDataModel* MInterface::getModel()
{
return this->mainModel;
}
有mdatmodel .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文档:
- 使用c++模型与Qt快速视图> QAbstractItemModel子类
- QAbstractItemModel Class>受保护的函数
这是你的固定模型。我删除了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;
}
相关文章:
- 访问和打印元组中的数据,并使用 C++14 使用模板函数显示数据
- 它不显示数据,只显示永无止境的循环
- 在网格视图中显示数据 - 基于 MFC c++ 对话框的应用程序
- 使用 insertion(<<) 运算符和 "write" 函数在 C++ 中显示数据有什么区别?
- 使用 ARDUINO 和处理在 8x8 LED 矩阵上显示数据时出现问题
- 列表视图最初不显示数据
- C++服务器未显示数据包
- 模板堆栈类:堆栈中没有显示数据
- 使用选择排序对名称进行排序并显示数据
- 'top'程序用于在屏幕上重新显示数据的技术是什么?
- 以两列c++显示数据
- QTableView 显示列标题,但不显示数据
- 显示功能不显示数据
- 从变体VT_ARRAY读取和显示数据 |VT_BSTR
- 线程不刷新数据,在屏幕中显示数据时出错
- 使用C++与3000Hz的线阵扫描相机接口,并处理/显示数据
- QtableWidget不显示数据
- 不按我的要求显示数据输入表单
- 无法在 MySql 数据库中的 C++ QTableView 中显示数据 QSqlQueryModel
- 使用SDI应用程序(MFC)从文本文件读取数据并显示数据