Russian Qt Forum

Qt => Model-View (MV) => Тема начата: kuzulis от Январь 12, 2010, 10:10



Название: Помогите разобраться с MVC. Простой пример.
Отправлено: kuzulis от Январь 12, 2010, 10:10
Всем доброго времени!

У меня тут назрела необходимость в представлении каким либо образом данных из массива. Т.е. имеется некий массив с данными (пусть на 10 элементов) и мне необходимо на форме(виджете) показывать что-то вроде таблицы в которой один столбец будет представлять собой номер элемента массива, а другой - значение!
Также необходимо, чтобы по клику на значении какого либо элемента - эта ячейка таблицы переходила в режим редактирования с возможностью изменить значение выбранного элемента массива.

Вопросы:
1. Какой для этих целей выбрать виджет лучше?
2. Необходима ли для этого вообще концепция MVC? Или что-то другое?
3. Посоветуйте примеры где есть что-то аналогичное?

:)

спс.

ЗЫ: что-то я в тупике


Название: Re: Помогите разобраться с MVC. Простой пример.
Отправлено: Karl-Philipp от Январь 12, 2010, 11:27
Spin Box Delegate Example?


Название: Re: Помогите разобраться с MVC. Простой пример.
Отправлено: kuzulis от Январь 12, 2010, 11:42
Дадада, именно это! Спс :)


Название: Re: Помогите разобраться с MVC. Простой пример.
Отправлено: kuzulis от Январь 12, 2010, 11:51
Бегло просмотрел.. И непонятен момент: а каким образом связать данные моего массива с моделью? Ведь в этом примере данные из ячеек хранятся в самой модели - а у меня они должны хранится в массиве!


Название: Re: Помогите разобраться с MVC. Простой пример.
Отправлено: Karl-Philipp от Январь 12, 2010, 12:07
Тогда глянь пример simple tree model - там для хранения данных используется кастомная модель, думаю она тебе подойдёт. Но в этом примере не демонстрируются делегаты.


Название: Re: Помогите разобраться с MVC. Простой пример.
Отправлено: kuzulis от Январь 12, 2010, 12:18
спс


Название: Re: Помогите разобраться с MVC. Простой пример.
Отправлено: crossly от Январь 12, 2010, 22:58
посмотри QStringListModel.... там в качестве источника данных для модели используется QStringList... может вместо массива тебе можно использовать    QStringList.... если нет.... можешь сделать свою модель по примеру этой (с источником данных в качестве массива)... ничего сложного там нету...


Название: Re: Помогите разобраться с MVC. Простой пример.
Отправлено: kuzulis от Январь 14, 2010, 22:01
что-то у меня ничего не получается. мне нужно сделать модель в виде таблицы с размерностью 3 столбца х 10 строк (к примеру).
конструктор модели при ее создании должен брать в расчет (принимать входным параметром) размер некоего массива с данными.

arraymodel.h
Код:
#ifndef ARRAYMODEL_H
#define ARRAYMODEL_H

#include <QAbstractTableModel>
#include <QVector>

class ArrayModel : public QAbstractTableModel
{
    Q_OBJECT

public:
    ArrayModel(const QVector<int> &data, int startAddress, int regType, QObject *parent = 0);
    ~ArrayModel();

    private:
    QVector<int> m_data;
};

#endif
arraymodel.cpp
Код:
#include <QtGui>

#include "arraymodel.h"

ArrayModel::ArrayModel(const QVector<int> &data, int startAddress, int regType, QObject *parent)
    : QAbstractTableModel(parent), m_data(data)
{
    Q_UNUSED(startAddress);
    Q_UNUSED(regType);
   
    //вставляем 3 столбца + 10 строк в модель
    this->insertColumns (0, 3);
    this->insertRows (0, m_data.count());
}

ArrayModel::~ArrayModel()
{
}

main.cpp
Код:
#include <QApplication>
#include <QVector>
#include <QTableView>

#include "arraymodel.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
   
    QVector<int> data(10);  //наш массив из которого/в который должны читаться/писаться данные
   
    for (int i=0;i<10;i++)
        data[i] = i*2;      //тут мы заполнили массив

    ArrayModel model(data, 0, 0);   //должны создать модель типа "таблица
    QTableView tableView;
    tableView.setModel(&model);

    tableView.setWindowTitle(QObject::tr("Example #1"));
    tableView.show();
    return app.exec();
}

компилятор пишет это:
Цитировать
[kuzulis@kuzulis test1]$ make
g++ -c -m64 -pipe -march=x86-64 -mtune=generic -O2 -pipe -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt/mkspecs/linux-g++-64 -I. -I/usr/include/QtCore -I/usr/include/QtGui -I/usr/include -I. -o arraymodel.o arraymodel.cpp
g++ -c -m64 -pipe -march=x86-64 -mtune=generic -O2 -pipe -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt/mkspecs/linux-g++-64 -I. -I/usr/include/QtCore -I/usr/include/QtGui -I/usr/include -I. -o main.o main.cpp
main.cpp: In function ‘int main(int, char**)’:
main.cpp:17: ошибка: cannot declare variable ‘model’ to be of abstract type ‘ArrayModel’
arraymodel.h:9: замечание:   because the following virtual functions are pure within ‘ArrayModel’:
/usr/include/QtCore/qabstractitemmodel.h:178: замечание:        virtual int QAbstractItemModel::rowCount(const QModelIndex&) const
/usr/include/QtCore/qabstractitemmodel.h:179: замечание:        virtual int QAbstractItemModel::columnCount(const QModelIndex&) const
/usr/include/QtCore/qabstractitemmodel.h:182: замечание:        virtual QVariant QAbstractItemModel::data(const QModelIndex&, int) const
make: *** [main.o] Ошибка 1
[kuzulis@kuzulis test1]$

Помогите разобраться в чем дело :(
ЗЫ: что-то я не понял в чем суть
ЗЫЗЫ: прикрепляю проект


Название: Re: Помогите разобраться с MVC. Простой пример.
Отправлено: MoPDoBoPoT от Январь 14, 2010, 22:27
Хех, QAbstractTableModel - не спроста он абстрактный. Надо реализовать хотябы минимальный интерфейс - только для чтения: flags(), data(), headerData(), rowCount(), columnCount().


Название: Re: Помогите разобраться с MVC. Простой пример.
Отправлено: kuzulis от Январь 14, 2010, 23:27
спасибо, вроде получилось.

Но теперь возникает вопрос: как сделать так, чтобы модель отслеживала изменение данных в массиве data(10) который в main.cpp ?
Код:
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
   
    QVector<int> data(10);  //наш массив из которого/в который должны читаться/писаться данные
....
}
?

PS: прилагаю проект


Название: Re: Помогите разобраться с MVC. Простой пример.
Отправлено: Dendy от Январь 14, 2010, 23:32
Прятать массив внутрь самой модели и изменять его не напрямую, а с помощью торчащих наружу из модели методов.


Название: Re: Помогите разобраться с MVC. Простой пример.
Отправлено: kuzulis от Январь 14, 2010, 23:46
Цитировать
Прятать массив внутрь самой модели и изменять его не напрямую, а с помощью торчащих наружу из модели методов.
'эмм... так внутри модели есть копия этого массива - т.е. переменная:
Код:
....
 private:
    QVector<int> m_data;
....
вот если менять элементы этого "внутреннего" массива m_data - то модель отследит?


Название: Re: Помогите разобраться с MVC. Простой пример.
Отправлено: Dendy от Январь 14, 2010, 23:53
Чудес не бывает, это C++. Чтобы отследить нужно делать обёртку. Снаружи никто даже не должен догадываться в каком виде хранятся данные. Кроме того внутри обёртки перед изменением самих данных модель обязана сигнализировать, что вот сейчас данные ещё старые, но я их сейчас поменяю QAbstractItemModel::beginInsertRows()/QAbstractItemModel::endInsertRows() + сопутствующие методы, в документации всё подробно расписано.


Название: Re: Помогите разобраться с MVC. Простой пример.
Отправлено: kuzulis от Январь 15, 2010, 00:18
не понятно все-равно...
Я у себя предполагал что оно будет работать так:
1. Имеется класс А - в котором находится массив с данными.
2. При запуске приложения - должен начать работать некий алгоритм (процесс работы), который меняет (обновляет) данные в этом массиве в течении всего периода работы приложения.
3. Имеется класс Б - это типа модель, которая должна чисто для GUI показывать (отображать) изменения этих данных в процессе работы приложения...

Так вот, теперь я опять запутался:
Цитировать
Кроме того внутри обёртки перед изменением самих данных модель обязана сигнализировать, что вот сейчас данные ещё старые, но я их сейчас поменяю QAbstractItemModel::beginInsertRows()/QAbstractItemModel::endInsertRows() + сопутствующие методы
у меня модель (допустим для простоты) не меняет данные - она их только отображает... т.е. это класс А (источник данных) должен сигнализировать классу Б (модели) о том. что данные поменялись и следовательно модель должна обновить значения в QTableView.

т.е. путаница и нестыковка получается или я недопонял ничего :(




Название: Re: Помогите разобраться с MVC. Простой пример.
Отправлено: Dendy от Январь 15, 2010, 00:55
Модель не просто отображает данные, она их полностью контролирует. Неважно, прямо или косвенно. Класс А не может просто сигнализировать, что данные уже изменились, он должен предварительно указать что данные сейчас поменяются, а после изменений сказать готово. Простого изменения данных недостаточно - нужно задейстовать весь функционал модели. Выше я показал пример с добавлением строк. В документации всё расписано.


Название: Re: Помогите разобраться с MVC. Простой пример.
Отправлено: kuzulis от Январь 15, 2010, 01:10
Бррр.... ничо не понял.. пора спать :)


Название: Re: Помогите разобраться с MVC. Простой пример.
Отправлено: MoPDoBoPoT от Январь 15, 2010, 14:18
Я у себя предполагал что оно будет работать так:
1. Имеется класс А - в котором находится массив с данными.
2. При запуске приложения - должен начать работать некий алгоритм (процесс работы), который меняет (обновляет) данные в этом массиве в течении всего периода работы приложения.
3. Имеется класс Б - это типа модель, которая должна чисто для GUI показывать (отображать) изменения этих данных в процессе работы приложения...

Так вот, теперь я опять запутался:
Цитировать
Кроме того внутри обёртки перед изменением самих данных модель обязана сигнализировать, что вот сейчас данные ещё старые, но я их сейчас поменяю QAbstractItemModel::beginInsertRows()/QAbstractItemModel::endInsertRows() + сопутствующие методы
у меня модель (допустим для простоты) не меняет данные - она их только отображает... т.е. это класс А (источник данных) должен сигнализировать классу Б (модели) о том. что данные поменялись и следовательно модель должна обновить значения в QTableView.

т.е. путаница и нестыковка получается или я недопонял ничего :(
Как уже ранее говорилось, модель - обертка над некой структурой данных, которая предоставляет интерфейс для чтения/модификации данных структуры. Что из себя представляет эта самая структура для внешнего мира не важно, потому как внешний мир работает с этой структурой через обертку (модель) с помощью определенного интерфейса (предоставленного набора методов). Так вот, "отслеживание" измений данных получается за счет использования специально предназначенных для этого методов (они отсылают необходимые сигналы).
Я надеюсь ты теперь понял то, что изменение данных структуры вне модели - это не комильфо.
В общем, в классе А надо работать с моделью (классом В  :)), а не напрямую с массивом.