gpt4 book ai didi

qt - 在 ListView 中使用 QAbstractListModel

转载 作者:行者123 更新时间:2023-12-02 06:48:49 25 4
gpt4 key购买 nike

我是 Qt 新手,所以请耐心等待。

我已经成功地从 StringList 和对象的 QList 填充 ListView*

我现在正在努力解决的是使用 C++ 中定义的派生 QAbstractListModel 的类来填充 QML 中的 ListView。

这是我的 CPP 类的原型(prototype):

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和data的实现如下:

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

ListView 的 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 修饰符。

以正确的方式声明函数后,一切正常。

为了进一步说明,实现 data 和 rowCount 就足够了:)。

感谢您的帮助。我会接受 BaCaRoZzo 的回答,因为我在查看示例中的代码后才设法弄清楚这一点。

顺便说一句,它可以很好地与 message 和 model.message 配合使用。

最佳答案

如何实现加法?您应该使用我的评论中提供的示例中的方法。

来自docs :

An insertRows() implementation must call beginInsertRows() before inserting new rows into the data structure, and it must call endInsertRows() immediately afterwards.

你应该有这样的东西:

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 评论是正确的:仅使用您在模型中定义的委托(delegate)内的角色名称。如果其他一切都正确就是访问数据的方式。

<小时/>

了解 C++ 模型实现和使用的最佳文档之一是 Model subclassing reference 。本文档清楚地描述了哪些是最重要的子类方法以及目的。

至于实现什么方法,那就看需求了。根据模型上可能的操作,应实现不同的方法(有关完整详细信息,请参阅上面的链接)。 ListView 的模型其中可以添加/删除的项目可以继承QAbstractListModel并且仅依赖于大多数功能的默认实现。您只需要data() , roleNames()rowCount() ,正如您在大多数示例中已经看到的那样。

如果您还需要编辑数据而不仅仅是添加/删除数据,那么您还需要其他功能,特别是setData()还有责任通知所附 View setData() 中发生的任何模型修改。 ,通过信号dataChanged() 。再次引用上面提供的子类化引用。

另请注意,如果 add方法修改为 Q_INVOKABLE修饰符,即它被声明为

Q_INVOKABLE void add(params...);

在模型 header 中,您还可以从 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)
}
}

创建 View 后立即将项目插入 View 中。显然,相同的方法可以应用于其他 QML 信号,以便您可以对 QML 事件使用react并触发添加/删除行为。

最后,您不需要使用 qmlRegisterType 注册模型。对于您当前的要求来说,这是多余的。

关于qt - 在 ListView 中使用 QAbstractListModel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27400025/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com