【问题标题】:Exposing QList<customobj *> to QML将 QList<customobj *> 暴露给 QML
【发布时间】:2018-07-03 08:29:47
【问题描述】:

我正在尝试将带有自定义对象 (Sample) 的 QList 公开到 QML 中。每当我将这些自定义对象(它们继承自 QObject)存储到 QList&lt;QObject *&gt; 中时,它们就会显示出来,但没有信息,但是当我尝试将它们公开为 QList&lt;Sample *&gt; 时,它们不会。

sample.h

class Sample : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString getVar READ getVar WRITE setVar NOTIFY varChanged)
public:
    explicit Sample();

    //! Returns var
    QString getVar() const { return var; }

    //! Sets var
    void setVar(const QString &a);

signals:
    varChanged();

protected:
    QString var;
};

包含列表的类如下所示

samplecontrol.h

class SampleManager : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QList<Sample *> getSampleList READ getSampleList NOTIFY sampleListChanged)
public:
    SampleManager(const QString &path);

    //! Returns sample list
    QList<Sample *> getSampleList() const { return sampleList_; }

signals:
    sampleListChanged();

protected:
    QList<Sample *> sampleList_;
};

我正在设置上下文

view_->rootContext()->setContextProperty("slabGridModel", QVariant::fromValue(samplecontrol.getSampleList()));

正如我所说,当我累了

QList<QObject *> datalist;
datalist.append(sampleManager.getSampleList().first());
datalist.append(sampleManager.getSampleList().last());

成功了。我怎样才能使它与QList&lt;Sample *&gt; 一起工作?

感谢您的帮助!

【问题讨论】:

  • 所以你想在 QML 端使用 getSampleList 吗?它会成为某个视图的模型吗?
  • @eyllanesc 是的,应该是委托 Sample 的 GridView 的模型
  • 问题是一个QList 是一个只读模型,每个副本添加一次,也就是说,如果你向QList 添加元素它不会通知你,因此即使添加元素,视图也将始终为空。
  • @eyllanesc 那我怎么暴露它呢?
  • 对于生产你必须实现一个合适的模型,直接暴露列表效率太低了。由于您的模型项从 QObject 派生,您可以使用通用模型实现,那里有一些可用的。

标签: c++ qt qml


【解决方案1】:

你可以传递一个QObjects列表,但问题是如果添加更多元素它不会通知视图,如果你想通知视图你必须使用继承自QAbstractItemModel的模型。另一方面,您如何将数据模型作为 qproperty 公开,最好公开 SampleManager:

samplemodel.h

#ifndef SAMPLEMODEL_H
#define SAMPLEMODEL_H

#include "sample.h"

#include <QAbstractListModel>

class SampleModel : public QAbstractListModel
{
    Q_OBJECT
public:
    using QAbstractListModel::QAbstractListModel;
    ~SampleModel(){
        qDeleteAll(mSamples);
        mSamples.clear();
    }
    int rowCount(const QModelIndex &parent = QModelIndex()) const override{
        if (parent.isValid())
            return 0;
        return mSamples.size();
    }

    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override{
        if (!index.isValid())
            return QVariant();
        if(role == Qt::UserRole){
            Sample *sample =  mSamples[index.row()];
            return QVariant::fromValue(sample);
        }
        return QVariant();
    }

    void appendSample(Sample * sample)
    {
        beginInsertRows(QModelIndex(), rowCount(), rowCount());
        mSamples << sample;
        endInsertRows();
    }

    QHash<int, QByteArray> roleNames() const{
        QHash<int, QByteArray> roles;
        roles[Qt::UserRole] = "sample";
        return roles;
    }

private:
    QList<Sample *> mSamples;
};


#endif // SAMPLEMODEL_H

samplemanager.h

#ifndef SAMPLEMANAGER_H
#define SAMPLEMANAGER_H

#include "samplemodel.h"

#include <QObject>

class SampleManager : public QObject
{
    Q_OBJECT
    Q_PROPERTY(SampleModel* model READ model WRITE setModel NOTIFY modelChanged)
public:
    using QObject::QObject;
    SampleModel *model() const{
        return mModel.get();
    }
    void setModel(SampleModel *model){
        if(mModel.get() == model)
            return;
        mModel.reset(model);
    }
signals:
    void modelChanged();
private:
    QScopedPointer<SampleModel> mModel;
};

#endif // SAMPLEMANAGER_H

ma​​in.cpp

#include "samplemanager.h"
#include "samplemodel.h"

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>

#include <QTime>
#include <QTimer>

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

    SampleManager manager;
    manager.setModel(new SampleModel);

    // test
    QTimer timer;
    QObject::connect(&timer, &QTimer::timeout, [&manager](){
        manager.model()->appendSample(new Sample(QTime::currentTime().toString()));
    });
    timer.start(1000);

    QQmlApplicationEngine engine;
    engine.rootContext()->setContextProperty("manager", &manager);
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}

ma​​in.qml

import QtQuick 2.9
import QtQuick.Window 2.2

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    GridView {
        anchors.fill: parent
        model: manager.model
        delegate:
            Rectangle {
            width: 100
            height: 100
            color: "darkgray"
            Text {
                text: sample.getVar
                anchors.centerIn: parent
            }
        }
    }
}

完整的例子可以在下面的link找到。

【讨论】:

  • 它可以工作,但不知何故它只添加了一个样本,当我点击它时(在它写“点击!”到控制台之前),程序抛出 SIGSEGV
猜你喜欢
  • 1970-01-01
  • 2021-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-07
相关资源
最近更新 更多