Russian Qt Forum

Qt => Вопросы новичков => Тема начата: Scarecrow от Июль 19, 2018, 14:04



Название: Указатели и QT объекты
Отправлено: Scarecrow от Июль 19, 2018, 14:04
Добрый день!

Есть следующая проблема. Я создал свою модель данных на основе QAbstractListModel. Задача следующая: есть некоторый QJsonArray, который является приватным членом класса и поставляет информацию

// header
class MyClassModel : public QAbstractListModel
{
public:
    Q_OBJECT

public:
    explicit MyClassModel(QObject *parent = 0);
    virtual QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const;
    virtual int rowCount( const QModelIndex & parent = QModelIndex() ) const;

    void setArray(QJsonArray * in);

private:
    QJsonArray * m_contentJson;
};

//source

MyClassModel::MyClassModel(QObject *parent) :
    QAbstractListModel(parent),
    m_contentJson(nullptr)
{

}

QVariant MyClassModel::data( const QModelIndex &index, int role ) const
{
    QJsonValue data = m_contentJson->at(index.row());
    QVariant value("test");
    return value;
}

int MyClassModel::rowCount(const QModelIndex &/*parent*/) const
{
    if (!m_contentJson)
        return 0;
    return m_contentJson->size();
}

void MyClassModel::setArray(QJsonArray * in)
{
    if (in) {
        m_contentJson = in;
    }
}

Это все отображается в ComboBox. Но мне надо периодически менять массив данных внутри модели (то есть combobox может отображать цвета (красный, синий, желтый) или фигуры(шар, куб) например. Данные разные и не хотелось бы при смене данных внутри модели их копировать. Я пытаюсь просто подменять указатели, но почему-то мой m_contentJson не сохраняет тото указатель на внешний QJsonArray который я ему задаю.

Почему это происходит и как вообще в таких случаях правильно делать?



Название: Re: Указатели и QT объекты
Отправлено: zhbr от Июль 19, 2018, 15:38
А можно проектик полный(ну или минимальный какой-то) глянуть?

Вобще есть подозрение, что когда со стороны модели вы меняете данные, то вы не сигнализируете об этом.


Название: Re: Указатели и QT объекты
Отправлено: Авварон от Июль 19, 2018, 18:54
QJsonArray имеет внутри счётчик ссылок и его достаточно дешево копировать, не надо городить указатели там где они не нужны.

Цитировать
QJsonArray is an implicitly shared class and shares the data with the document it has been created from as long as it is not being modified.

Это раз.
Два - в data() всегда возвращается "test".
Три - при установке нового значения надо уведомить View при помощи методов beginResetModel() / endResetModel()


Название: Re: Указатели и QT объекты
Отправлено: Scarecrow от Июль 20, 2018, 12:32
Спасибо всем за ответы!

Я просто привык к механизму плюсов, где передача по ссылке, указателю и значению имеет отличия. И если передавать объект по значению, он будет копироваться, а это память и время. Как правильно это делается в QT? Если есть некоторые данные, которые быстро меняются откуда-то извне.

В каком месте надо вставлять beginResetModel() / endResetModel() ? Как вообще работает механизм обновления моделей?

В ссылке ниже код проекта


Название: Re: Указатели и QT объекты
Отправлено: Авварон от Июль 20, 2018, 14:46
Спасибо всем за ответы!

Я просто привык к механизму плюсов, где передача по ссылке, указателю и значению имеет отличия. И если передавать объект по значению, он будет копироваться, а это память и время. Как правильно это делается в QT? Если есть некоторые данные, которые быстро меняются откуда-то извне.

В каком месте надо вставлять beginResetModel() / endResetModel() ? Как вообще работает механизм обновления моделей?

В ссылке ниже код проекта


Всё также, как и в плюсах - если у объекта тривиальный конструктор копирования и размер меньше 2х указателей (QPoint, QSize, QStringView), то передаёте по значению, иначе - по ссылке (QString, QJsonArray). Т.е. почти всегда по ссылке. Из функций в Qt принято возвращать по значению (в т.ч. для геттеров) как раз из-за implicit sharing (и из-за того что так проще менять реализацию). Но в своём коде для геттеров можно и по ссылке возвращать.
Если объект надо сохранить как член класса, придётся копировать.
В плюсах вы бы завернули свой большой объект в std::shared_ptr и передавали бы его в setter по ссылке. Тут уже это сделано за вас, поэтому лишние указатели делать не нужно.

В BRM/ERM надо завернуть изменение внутренних данных модели (setter), как сделано в примере (http://doc.qt.io/qt-5/qtwidgets-itemviews-pixelator-example.html#imagemodel-class-implementation).


Название: Re: Указатели и QT объекты
Отправлено: Fregloin от Сентябрь 05, 2018, 11:53
Implicit sharing почитайте