Russian Qt Forum

Qt => Model-View (MV) => Тема начата: demaker от Апрель 27, 2016, 12:42



Название: Model-View + QGraphicsScene
Отправлено: demaker от Апрель 27, 2016, 12:42
Есть модель
Код:
 Base-----|---------|
             |             |
          Station     Station
               |       |         |
               |       |          |
         Device      Device   Device

Создаю абстрактный класс элемента модели
Код
C++ (Qt)
#include <QObject>
#include <QVariant>
#include <QIcon>
#include <QList>
#include <QString>
 
#include <QGraphicsScene>
 
class CommonElement: public QObject
{
   Q_OBJECT
 
public:
   explicit CommonElement(QObject*parent = 0);
   virtual ~CommonElement();
 
   virtual CommonElement*appendChild() = 0;
   virtual QVariant getIcon() = 0;
   virtual QVariant getHeaderData(int ) = 0;
   virtual void function() = 0;
   virtual int amountColumn() = 0;        
 
public:
   QString str;
   QGraphicsScene *scene;
};
 
Затем отдельно для каждого класса элемента
Base:
Код
C++ (Qt)
Base::Base(QObject *parent):
   CommonElement(parent)
{
   str = "Base";
 
//    scene = new QGraphicsScene(this);  ИЗ-ЗА ЭТОГО ПАДАЕТ ПРОГРАММА
//    scene->addText(str);                     !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}
 
Base::~Base()
{
}
 
CommonElement* Base::appendChild()
{
   Station *station = new Station(this);
   return station;
}
 
QVariant Base::getIcon()
{
   static QIcon icon("C:/Qt/Qt5.2.1/Tools/QtCreator/bin/build-MyMTLYNX-Desktop_Qt_5_2_1_MinGW_32bit-Debug/image/database.png");
   return QVariant::fromValue<QIcon>(icon);
}
 
QVariant Base::getHeaderData(int section)
{
   switch(section)
   {
       case 0: return tr("Name");
       case 1: return tr("Count Device");
       case 2: return tr("Workset");
   }
   return QVariant();
}
 
int Base::amountColumn()
{
   return 3;
}
 
void Base::function()
{
   qDebug()<<"Base";
}
 
Station:
Код
C++ (Qt)
Station::Station(CommonElement *parent):
 CommonElement(parent)
{
   str = "MyStantion";
 
   //scene = new QGraphicsScene(this);
   //scene->addText(str);
}
 
Station::~Station()
{
}
 
CommonElement* Station::appendChild()
{
   Device *device = new Device(this);  
   return device;
}
 
QVariant Station::getIcon()
{
   static QIcon icon("C:/Qt/Qt5.2.1/Tools/QtCreator/bin/build-MyMTLYNX-Desktop_Qt_5_2_1_MinGW_32bit-Debug/image/station.png");
   return QVariant::fromValue<QIcon>(icon);
}
 
QVariant Station::getHeaderData(int section)
{
   switch(section)
   {
       case 0: return tr("Connection");
       case 1: return tr("Serial Number");
       case 2: return tr("Network Number");
       case 3: return tr("Type Device");
   }
   return QVariant();
}
 
int Station::amountColumn()
{
   return 4;
}
 
void Station::function()
{
   qDebug()<<"Station->str = " + str;
}
 
 

Device:
Код
C++ (Qt)
Device::Device(QObject *parent):
   CommonElement(parent)
{
   str = "MyDevice";
 
   //scene = new QGraphicsScene(this);
   //scene->addText(str);
}
 
Device::~Device()
{
}
 
CommonElement* Device::appendChild()
{
   return NULL;
}
 
QVariant Device::getIcon()
{
   static QIcon icon("C:/Qt/Qt5.2.1/Tools/QtCreator/bin/build-MyMTLYNX-Desktop_Qt_5_2_1_MinGW_32bit-Debug/image/device.png");
   return QVariant::fromValue<QIcon>(icon);
}
 
QVariant Device::getHeaderData(int section)
{
   switch(section)
   {
       case 0: return tr("Name");
       case 1: return tr("Description");
   }
 
   return QVariant();
}
 
int Device::amountColumn()
{
   return 2;
}
 
void Device::function()
{
   qDebug()<<"Device->str = " + str;
}
 

Хочу чтобы при нажатии на элемент модели
подгружалась картинка сцены во вьювер,
но к сожалению такого не происходит программа вылетает
не могу понять почему???


Название: Re: Model-View + QGraphicsScene
Отправлено: demaker от Апрель 27, 2016, 12:51
Вот как выглядит окно

Слева общая модель - типа дерево
Справа модель - типа листа. При нажатии на элемент модели дерево модель листа обновляется для отображения элементов входящих в текущий выбранный элемент.
Внизу GraphicsView.


Название: Re: Model-View + QGraphicsScene
Отправлено: demaker от Апрель 27, 2016, 12:58
Вот что показывает Debug при возникновении ошибки


Название: Re: Model-View + QGraphicsScene
Отправлено: demaker от Апрель 27, 2016, 12:58
Если надо могу выслать весь проект :)


Название: Re: Model-View + QGraphicsScene
Отправлено: demaker от Апрель 27, 2016, 13:46
Вот проект
Спасибо!


Название: Re: Model-View + QGraphicsScene
Отправлено: Racheengel от Апрель 27, 2016, 15:13
1. Зачем для каждого элемента создавать отдельную сцену?
2. В QVariant Station::getIcon() и подобных используйте механизм ресурсов, а не иконки по непонятному пути.


Название: Re: Model-View + QGraphicsScene
Отправлено: demaker от Апрель 27, 2016, 15:26
1. Зачем для каждого элемента создавать отдельную сцену?
2. В QVariant Station::getIcon() и подобных используйте механизм ресурсов, а не иконки по непонятному пути.

1.после того как будет выбран элемент модели, подгружается сцена этого элемента с отрисовкой того количества элементов сколько этот выбранный элемент в себя включает.

2.К сожалению я не понял что Вы имели ввиду ???


Название: Re: Model-View + QGraphicsScene
Отправлено: Racheengel от Апрель 27, 2016, 15:36
я про это

Код:
QVariant Device::getIcon()
{
    static QIcon icon("C:/Qt/Qt5.2.1/Tools/QtCreator/bin/build-MyMTLYNX-Desktop_Qt_5_2_1_MinGW_32bit-Debug/image/device.png");
    return QVariant::fromValue<QIcon>(icon);
}

Положите все иконки в ресурсы и замените первую строчку на что то типа
static QIcon icon(":/icons/myDeviceIcon");

Иначе при перенесении проги на др. машину пропадут иконки.

По поводу сцены - ее надо убрать из самих девайсов и сделать частью окна-превью (связав с QGraphicsView).
При вызове превью уже будете на сцену кидать то, что хотите отобразить.


Название: Re: Model-View + QGraphicsScene
Отправлено: demaker от Апрель 27, 2016, 15:46
я про это

Код:
QVariant Device::getIcon()
{
    static QIcon icon("C:/Qt/Qt5.2.1/Tools/QtCreator/bin/build-MyMTLYNX-Desktop_Qt_5_2_1_MinGW_32bit-Debug/image/device.png");
    return QVariant::fromValue<QIcon>(icon);
}

Положите все иконки в ресурсы и замените первую строчку на что то типа
static QIcon icon(":/icons/myDeviceIcon");

Иначе при перенесении проги на др. машину пропадут иконки.


Переделал спасибо  :)

По поводу сцены - ее надо убрать из самих девайсов и сделать частью окна-превью (связав с QGraphicsView).
При вызове превью уже будете на сцену кидать то, что хотите отобразить.

Т.е нужно создать объект который будет формировать сцену и выдавать на нее указатель при клике на элемент модели, я Вас правильно понял.



Название: Re: Model-View + QGraphicsScene
Отправлено: Racheengel от Апрель 27, 2016, 16:03
Сцена - должна быть частью модели? Что-то в ней будет храниться важное?
Или она только для отображения служит?

Если второе, то сделайте функцию в CommonElement типа
void ShowOnScene(QGraphicsScene* scene)
и пусть ее вьювер вызывает, когда юзер на соотв. элемент модели кликнет.
И эта функция будет уже менять сцену.


Название: Re: Model-View + QGraphicsScene
Отправлено: demaker от Апрель 27, 2016, 16:27
Сцена - должна быть частью модели? Что-то в ней будет храниться важное?
Или она только для отображения служит?

У нас есть модель
элемент-модели может быть как parent так и child.
при нажатии на этот элемент на сцене отображаются все его дочерние элементы.
Отображаются т.е имеется ввиду рисуются квадратики или ...

И при нажатии на сцене на любой дочерний элемент, мы должны перейти соответственно на его сцену и отрисовать все дочерние элементы, а также селектор в treeview должен перейти на этот элемент.

Получается при создании Элемента модели в ней должен создаваться объеты типа
Код:
QGraphicsObject и QGraphicsScene 
или нет?

Если да, то когда я пишу код создания сцены в элементе-модели, то программа у меня падает ???


Название: Re: Model-View + QGraphicsScene
Отправлено: Racheengel от Апрель 27, 2016, 18:00
Ваши элементы - это наследники QGraphicsObject.
А сцена - это то, что их компонует.
Создавайте для каждого элемента отдельный QGraphicsObject и пакуйте их на сцену, которая связана с вьювером. Кликнул юзер на элемент - очищаете сцену и выводите на нее содержимое выбранного элемента.
Как то так.


Название: Re: Model-View + QGraphicsScene
Отправлено: demaker от Апрель 28, 2016, 11:19
Сделал как Вы сказали
Код
C++ (Qt)
class CommonElement;
class CommonGraphicsObject : public QGraphicsObject
{
   Q_OBJECT
 
public:
   explicit CommonGraphicsObject(CommonElement *element,QGraphicsObject *parent = 0);
   virtual ~CommonGraphicsObject();
 
   virtual QRectF boundingRect() const = 0;
   virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) = 0;
   virtual CommonElement *getModelElement() = 0;
 
public:
   CommonElement *commonelement;
};
 

Код
C++ (Qt)
DeviceGraphicsObject::DeviceGraphicsObject(Device *element,QGraphicsObject * parent):
   CommonGraphicsObject(element,parent)
{
   //device = element;
   commonelement = element;
}
 
DeviceGraphicsObject::~DeviceGraphicsObject()
{
 
}
 
QRectF DeviceGraphicsObject::boundingRect() const
{
   return QRectF(0,0,30,20);
}
 
void DeviceGraphicsObject::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
   QPen pen(Qt::black);
   painter->setBrush(Qt::yellow);
   painter->setPen(pen);
   painter->drawRect(0,0,30,20);
}
 
CommonElement *DeviceGraphicsObject::getModelElement()
{
   return commonelement;
}
 

Код
C++ (Qt)
StationGraphicsObject::StationGraphicsObject(Station *element, QGraphicsObject * parent):
   CommonGraphicsObject(element,parent)
{
   commonelement = element;
}
 
StationGraphicsObject::~StationGraphicsObject()
{
 
}
 
QRectF StationGraphicsObject::boundingRect() const
{
   return QRectF(0,0,30,20);
}
 
void StationGraphicsObject::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
   QPen pen(Qt::black);
   painter->setBrush(Qt::green);
   painter->setPen(pen);
   painter->drawRect(0,0,30,20);
}
 
CommonElement *StationGraphicsObject::getModelElement()
{
   return commonelement;
}
 

Обработка сигнала при клике на TreeView
Код
C++ (Qt)
void MainWindow::clickedTreeView(QModelIndex index)
{
   if(index.isValid())
   {
       currentModelIndex = index;
       currentElement = reinterpret_cast<CommonElement*>(currentModelIndex.internalPointer());
       listmodel->setRoot(currentModelIndex);
       setPathLabel(currentElement);
       listview->loadHeaderLine(currentElement);
 
       //загрузка отображения при клике
       graphicsScene->clear();
       if(!currentElement->children().isEmpty()){
           qDebug()<<"No Empty";
           for(int i = 0; i < currentElement->children().size(); i++){              
               CommonElement *ce = (CommonElement*)(currentElement->children().at(i));
               CommonGraphicsObject *cgo = ce->getGraphicsObject();
               cgo->setPos(10+(cgo->boundingRect().width() + 5)*i,10); //!!!!!но почему-то программа вылетает при  
                                                                                               //!!!!! установки координат и
               graphicsScene->addItem(cgo);                                      //!!!!!при добавлении объекта на сцену  
           }
           graphicsView->setScene(graphicsScene);
       }
   }
}
 

Скажите может я что-то делаю не правильно ???


Название: Re: Model-View + QGraphicsScene
Отправлено: demaker от Апрель 28, 2016, 12:11
Прошу прощнеия

Код:
scene->clear();

удаляет все объекты со сцены


Название: Re: Model-View + QGraphicsScene
Отправлено: Racheengel от Апрель 28, 2016, 14:00
так заработало то или как?


Название: Re: Model-View + QGraphicsScene
Отправлено: demaker от Апрель 28, 2016, 22:14
Да спасибо :)