我是Qt的新人,所以请耐心等待。
我已成功设法从StringList和Object *的QList填充ListView
我现在正在努力的是使用在C ++中定义的派生QAbstractListModel的类在QML中填充ListView。
这是我的CPP课程的原型:
class MessageListEntryModel : public QAbstractListModel
{
Q_OBJECT
public:
enum eMLERoleTypes
{
MLERT_MSG = Qt::UserRole+1,
MLERT_COLOR
};
MessageListEntryModel(QObject* parent=0);
virtual ~MessageListEntryModel();
void AddEntry(QString aMessage, QColor aColor);
// pure virtuals implementations
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const ;
int columnCount(const QModelIndex &parent = QModelIndex()) const ;
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
QModelIndex parent(const QModelIndex &child) const ;
QHash<int,QByteArray> roleNames();
private:
QList<MessageEntry*> m_vpMessages;
MessageEntry是一个简单的类,包含2个成员,一个QColor和一个QString(该类不会扩展QObject)。
我必须实现上述所有功能,因为它们在底层类中是纯虚拟的(这是正常的吗?到目前为止人们只提到了角色名和数据的教程/样本中)。
roleNames和数据的实现如下:
QHash<int,QByteArray> MessageListEntryModel::roleNames()
{
QHash<int,QByteArray> rez;
rez[MLERT_MSG]="message";
rez[MLERT_COLOR]="messagecolor";
return rez;
}
QVariant MessageListEntryModel::data(const QModelIndex &index, int role) const
{
qDebug()<<" Data asked for "<<index.row()<<" and role "<<role;
if (index.row()<0 || index.row()>=m_vpMessages.size())
{
return QVariant();
}
MessageEntry* entry = m_vpMessages[index.row()];
if (role == MLERT_MSG)
{
return QVariant::fromValue(entry->message);
} else if (role == MLERT_COLOR)
{
return QVariant::fromValue(entry->messageColor);
}
// should be unreachable code
return QVariant();
}
列表视图的QML部分是这样的:
ListView {
id: quickMessageListdata
model: quickListModel
delegate: Rectangle {
width: 400
height: 25
color:"#000000"
Text{
text: model.message
color: model.messagecolor
}
}
到目前为止,这是我对如何在CPP和QML中实现事物的理解。 为了链接这两个,我使用以下代码:
MessageListEntryModel* model =new MessageListEntryModel();
// Add various entries
...
// assign model in QML
m_pViewRef->rootContext()->setContextProperty("quickListModel",model);
使用上面的代码,ListView中显示什么都不运行,我收到以下错误:
Unable to assign [undefined] to QString
Unable to assign [undefined] to QColor
我还注册了要导出到QML的模型类(不知道是否有必要):
qmlRegisterType<MessageListEntryModel> ("dlti.exported",1,0,"MessageListEntryModel");
所以很明显,我错过了正确使用QAbstractListItem派生类的方法,或者我错过了一个简单的重要关键信息。
我希望得到一些相关示例/教程的指示(也可以向您展示如何在QML中正确访问模型中的数据,因为我已经注意到在CPP中它从不通过数据函数)。
另外请注意我使用的是qt5,所以qt4.8样本不会做到这一点。
修改
经过长时间的挫折之后,我终于找到了该死的东西的错误:
我的roleNames函数签名错了! 过载的正确签名是:
protected :
QHash<int,QByteArray> roleNames() const;
请注意protected和const修饰符。
在以正确的方式声明功能后,一切正常。
如需进一步通知,实现数据和rowCount就足够了:)。
感谢您的帮助。 我将接受BaCaRoZzo的答案,因为我只是在查看示例中的代码后才想到这一点。
作为旁注,它适用于message和model.message。
答案 0 :(得分:8)
如何实施添加方法?您应该使用我的评论中提供的示例中的方法。
来自docs:
insertRows()实现必须先调用beginInsertRows() 在数据结构中插入新行,必须调用 紧接着是endInsertRows()。
你应该有类似的东西:
void MessageListEntryModel::add(params...)
{
beginInsertRows(QModelIndex(), rowCount(), rowCount()); // kindly provided by superclass
// object creation based on params...
m_vpMessages << objectCreated;
endInsertRows(); // kindly provided by superclass
}
与
int MessageListEntryModel::rowCount(const QModelIndex & parent) const {
Q_UNUSED(parent);
return m_vpMessages.count();
}
此外,@ Jonathan Mee评论是正确的:在模型中定义它们时,只使用委托中的角色名称。如果其他一切都正确 是访问数据的方式。
理解C ++模型实现和使用的最佳文档之一是Model subclassing reference。在本文档中清楚地描述了子类化和用于何种目的的最重要方法。
至于实施方法,实际上取决于需求。根据模型上可能的操作,应实施不同的方法(有关完整详细信息,请参阅上面的链接)。可以添加/删除项目的ListView
模型可以继承自QAbstractListModel
,只需依赖大多数函数的默认实现。正如您在大多数示例中看到的那样,您只需要data()
,roleNames()
和rowCount()
。
如果您还需要编辑数据而不仅仅是添加/删除数据,那么您还需要其他功能,尤其是setData()
。通过setData()
信号对dataChanged()
中发生的模型进行任何修改,通知所附视图也是 的责任。再次参考上面提供的子类化参考。
另请注意,如果使用add
修饰符修改Q_INVOKABLE
方法,即将其声明为
Q_INVOKABLE void add(params...);
在模型标题中,您也可以从QML中调用它(因为模型被设置为上下文属性),您可以编写,例如:
ListView {
id: quickMessageListdata
model: quickListModel
delegate: Rectangle {
width: 400
height: 25
color:"#000000"
Text{
text: model.message
color: model.messagecolor
}
}
Component.onCompleted: {
quickListModel.add(params)
quickListModel.add(params)
}
}
在创建视图后立即在视图中插入项目。显然,可以将相同的方法应用于其他QML信号,以便您可以对QML事件做出反应并触发添加/删除行为。
最后,您不需要使用qmlRegisterType
注册模型。对于您目前的要求,它是多余的。
答案 1 :(得分:1)
嗯......我对QML并不是很熟悉,但我相信这是你的问题:http://qt-project.org/doc/qt-5/qtquick-modelviewsdata-cppmodels.html#qabstractitemmodel
根据链接,您需要将Text
块更改为:
Text{
text: message
color: messagecolor
}
答案 2 :(得分:0)