Russian Qt Forum
Август 17, 2018, 13:07 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Указатели и QT объекты  (Прочитано 366 раз)
Scarecrow
Новичок

Offline Offline

Сообщений: 5


Просмотр профиля
« : Июль 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 который я ему задаю.

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

« Последнее редактирование: Июль 19, 2018, 14:11 от Scarecrow » Записан
zhbr
Новичок

Offline Offline

Сообщений: 29


Просмотр профиля
« Ответ #1 : Июль 19, 2018, 15:38 »

А можно проектик полный(ну или минимальный какой-то) глянуть?

Вобще есть подозрение, что когда со стороны модели вы меняете данные, то вы не сигнализируете об этом.
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2577


Просмотр профиля
« Ответ #2 : Июль 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()
Записан
Scarecrow
Новичок

Offline Offline

Сообщений: 5


Просмотр профиля
« Ответ #3 : Июль 20, 2018, 12:32 »

Спасибо всем за ответы!

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

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

В ссылке ниже код проекта
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2577


Просмотр профиля
« Ответ #4 : Июль 20, 2018, 14:46 »

Спасибо всем за ответы!

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

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

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


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

В BRM/ERM надо завернуть изменение внутренних данных модели (setter), как сделано в примере.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  

Страница сгенерирована за 0.05 секунд. Запросов: 22.