我有课。
在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);
};
此时一切都很好。在debuger中,我看到数据在模型中,采用正确的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 }
}
}
}
}
当我将debuger断点设置到我的modedata类和应该返回数据的函数中时,debuger不会停在那里。它看起来程序永远不会进入这个功能。
也许问题是我如何设置模型?函数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;
}
答案 0 :(得分:2)
您的主要问题是:
MDataModel
继承QAbstractTableModel
而不是QAbstractListModel
。这不是绝对的问题,因为您可以使用QAbstractTableModel
,但由于您在QML中使用ListView
,因此您应该更喜欢使用QAbstractListModel
。
您正在混合角色和列。这是第一点的结果,因为QAbstractListModel
隐藏了列的概念。
beginResetModel()
/ endResetModel()
,beginInsertRows()
/ endInsertRows()
,{ {1}} / beginRemoveRows()
等。此目的还有2个不成对的信号:endRemoveRows()
和dataChanged()
。请注意,您可以通过始终调用modelReset()
来逃避,但这不是一个好习惯,您应该赞成使用最特殊的功能。 您还应该阅读Qt文档:
这是你修复模型。我删除了modelReset()
和columnCount()
,因为您不需要它们来使其正常工作。
<强> MDataModel.h 强>
headerData()
<强> MDataModel.cpp 强>
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);
};
QML修复
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;
}
答案 1 :(得分:0)
此时,我的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;
}