LINUX.ORG.RU

[Qt] View & Scene. Свой Item.

 


0

0

Создал свой Item:

class Cell: public QGraphicsItem
{
    public:
        Cell(QRectF &inRect, QColor &color);

        QRectF boundingRect() const;
        QPainterPath shape() const;
        void paint(QPainter *painter, const QStyleOptionGraphicsItem *item, QWidget *widget);
    private:
        QRectF m_rect;
        QColor m_color;
};

Как его использовать?

Ну то есть я могу сделать что-то вроде

           QRectF myrect(0,0,40,30);
           QColor mycolor(QColor::fromHsv(qrand() % 256, 255, 190));
           Cell *myCell = new Cell(myrect, mycolor);
           scene()->addItem(myCell);

Но выглядит это как-то неправильно. Где хранить массив айтемов? По логике ведь это надо делать в сцене. Чтобы потом можно было их удалять. Чтобы у сцены была функция addCell(Cell*) и всё такое.

Как делать правильно?

★★★★★

Сама сцена имеет уже коллекцию итемов - items () (+ несколько оверайтов). Удалять из сцены, можно просто удалением итема или removeItem.

zJes ★★
()
Ответ на: комментарий от zJes

Ясно. Но всё же, мне хотелось бы, чтобы моя сцена имела функцию addCell(Cell*), которая по аналогии с addRect(QRectF*) и прочими клонировала бы Cell и добавляла бы объект с такими параметрами в список итемов. Чтобы не было извращений с new.

 QGraphicsScene scene;
 QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 100, 100));

 QGraphicsItem *item = scene.itemAt(50, 50);
 // item == rect

Я смотрел qgraphicsscene.cpp, но не разобрался, как оно там таки устроено.

И можете сказать, правильный ли план?

Я создаю инструмент, который заполнял бы прямоугольниками заданного пользователем размера в заданной области. Далее работа с прямоугольниками (нужно только выделение, удаление и просмотр свойств) идёт как с отдельными объектами. Вот. Не использую addRect, так как это тормоз (при количестве элементов в 5000 уже подтормаживает) и нужно больше фичей (допустим, хранение цвета).

Создал class Cell: public QGraphicsItem, с этим проблем не возникло.

Далее следует создать class Scene: public QGraphicsScene, где была бы операция добавления Cell, а также переделанное выделение объектов (у меня оно сложнее стандартных — выделяются только те объекты, которые в область выделения попадают более чем половиной своей площади). Тут, собственно, сейчас затык. Во-первых, создание аналога addRect вызвало проблемы. Во-вторых, не совсем понятно, что делать с выделением: как определять прощадь пересечения между моими прямоугольничками и, например, полигонами или кругами. В Qt есть стандартные методы для этого? (с прямоугольниками всё очевидно, есть intersect)

Далее следует создать инструмент рисования. Для этого надо будет поковырать эвенты в моём унаследованном от QGraphicsView виджете.

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от Obey-Kun

Да, кстати, и есть ли функция для нахождения ближайшего к заданной точке айтема?

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от Obey-Kun

Хинт, ты используешь QGraphicsView, то сделай так - в конструкторе сделай setViewport(new QGLWidget(QGLFormat(QGL::DoubleBuffer))) а потом уже вставляй сцену - setScene. Будет работать все через опенгл, с отрисовкой проблем думаю уже не будет.

Потом разницы между твоим методом addCell и стандартным addItem я не вижу ( три буквы n,e и w это не извращение :) ), лишние телодвижения только. Хотя конечно можно автоматизировать некоторую работу, но не обязательно это делать в сцене.

По поводу пересечений, хбз :)

zJes ★★
()
Ответ на: комментарий от zJes

Там Qt::ItemSelectionMode или для случая, когда объект целиком в выделении, или когда пересекает его. А мне нужно третье :).

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от zJes

Хинт, ты используешь QGraphicsView, то сделай так - в конструкторе сделай setViewport(new QGLWidget(QGLFormat(QGL::DoubleBuffer))) а потом уже вставляй сцену - setScene. Будет работать все через опенгл, с отрисовкой проблем думаю уже не будет.

Да я как-то пытался повозиться, но оно отказывается собираться.

Во:

obey@damnbook build % make    
[ 16%] Built target ../../qfrost
Scanning dependencies of target qfrostgui
[ 33%] Building CXX object src/gui/CMakeFiles/../../qfrostgui.dir/area.cpp.o                                                                                     
Linking CXX executable ../../qfrostgui                                                                                                                           
CMakeFiles/../../qfrostgui.dir/area.cpp.o: In function `qfgui::Area::Area(QWidget*)':                                                                            
area.cpp:(.text+0x190): undefined reference to `QGLFormat::QGLFormat(QFlags<QGL::FormatOption>, int)'
area.cpp:(.text+0x1d1): undefined reference to `QGLWidget::QGLWidget(QGLFormat const&, QWidget*, QGLWidget const*, QFlags<Qt::WindowType>)'
area.cpp:(.text+0x20d): undefined reference to `QGLFormat::~QGLFormat()'
area.cpp:(.text+0x220): undefined reference to `QGLFormat::~QGLFormat()'
CMakeFiles/../../qfrostgui.dir/area.cpp.o: In function `qfgui::Area::Area(QWidget*)':
area.cpp:(.text+0x4f6): undefined reference to `QGLFormat::QGLFormat(QFlags<QGL::FormatOption>, int)'
area.cpp:(.text+0x537): undefined reference to `QGLWidget::QGLWidget(QGLFormat const&, QWidget*, QGLWidget const*, QFlags<Qt::WindowType>)'
area.cpp:(.text+0x573): undefined reference to `QGLFormat::~QGLFormat()'
area.cpp:(.text+0x586): undefined reference to `QGLFormat::~QGLFormat()'
collect2: выполнение ld завершилось с кодом возврата 1
make[2]: *** [src/gui/../../qfrostgui] Ошибка 1
make[1]: *** [src/gui/CMakeFiles/../../qfrostgui.dir/all] Ошибка 2
make: *** [all] Ошибка 2

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от Obey-Kun

инклюды нужные есть, вроде

#include <QtOpenGL/QGLWidget>
#include <QtOpenGL/QGLFormat>
Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от Obey-Kun

разобрался

странная же штука этот cmake :)

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от zJes

всё стало зуммироваться медленнее

думаю, это зависит от железа.

также, не совсем понятно, что следует использовать — http://qt.nokia.com/doc/4.6/qgl.html#FormatOption-enum

в общем, если надо будет, повешу выбор на пользователя

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от Obey-Kun

Что за карта?
Использовать просто очень, QGLFormat(QGL::DoubleBuffer | QGL::StencilBuffer и тд.)
По сути должно хватить и SampleBuffers и вырубить всякие антиальясинги и прочее. И еще, у тебя апдейт на график вью какой стоит? setClip делаешь?

zJes ★★
()
Ответ на: комментарий от zJes

интель

и вырубить всякие антиальясинги

Вырублены

у тебя апдейт на график вью какой стоит

не понял вопроса

setClip делаешь?

нет

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от Obey-Kun

Утром :) Я спать...
Я на пошлой неделе запинывал такое на интеле с атомом... :(
Софтварный рендеринг, вообще еле работал, на опенгл даже кинетику и анимацию удалось запустить... почти без тормозов.

zJes ★★
()
Ответ на: комментарий от zJes

спасибо! добавь, пожалуйста, obey@obey.su

я тоже спать, ещё на пары

хотя ну их нафиг

но спать всё равно надо

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от zJes

спасибо

пункты 2 и 3 выполняется.

пункт 1, как я понял, не требуется, т.к. мои прямоугольнички не меняются. или я неправильно понял его суть?

кстати, когда включаю opengl, почему-то пропадают точки в background'е... ещё разбираться и разбираться...

спокойной ночи, большое спасибо :)

Obey-Kun ★★★★★
() автор топика

Чтобы у сцены была функция addCell(Cell*) и всё такое.

class MyScene: public QGraphicsScene
{
    ...
   public:
     Cell* addCell(const QRectF &r, const QColor &c)
     {
        Cell *cell = new Cell(r, c);
        addItem(cell);
        return cell;
     }
}

Этого хотел?

Devix
()
Ответ на: комментарий от Devix

как-то слишком просто получается... а по removeitem оно ведь cell из памяти не будет удалять... или будет?

Obey-Kun ★★★★★
() автор топика

Кстати, интересно, как можно найти все примыкающие к конкретному прямоугольнику прямоугольники?

Пока решение видится так — тупо сделать selection, чуть превышающий размер прямоугольника. Так как размер создаваемых прямоугольников у меня по условию кратен единице, то можно делать selection на (x+0.1,y+0.1) с центром, совпадающим с центром прямоугольника.

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от Obey-Kun

>вот-вот, так что нужно поступать как-то иначе

removeItem() действует для всех элементов одинаково даже для твоего Cell.

Devix
()
Ответ на: комментарий от Devix

в QGraphicsScene все item-ы хранятся в QList<QGraphicsItem*> а так как у QGraphicsItem деструктор виртуальный то и соотвественно когда будет удалятся твой Cell через указатель хранящийся в QGraphicsItem то удаление поизойдет успешно.

class Base
{
public:
virtual ~Base() { cout << «~Base»; }
};

class Derived: public Base
{
public:
~Derived() { cout << «~Derived»; }
};

int main()
{
Base *b = new Derived;
delete b; // все ок, если бы не был обьявлени деструктор ~Base как виртуальный то деструктор ~Derived не вызвался бы.
return 0;
}

Devix
()
Ответ на: комментарий от Devix

Вот исходник из Qt:

QGraphicsPixmapItem *QGraphicsScene::addPixmap(const QPixmap &pixmap)
{
QGraphicsPixmapItem *item = new QGraphicsPixmapItem(pixmap);
addItem(item);
return item;
}

Devix
()
Ответ на: комментарий от Obey-Kun

> сцену мне не надо свою колотить

в смысле сильно свою :)

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от Obey-Kun

>спасибо, выходит сцену мне не надо свою колотить (ну разве что потом, для хитрого select'а)

Для хитрого селекта если никаких более простых решений не найдешь то используй следующий список:
QList<QGraphicsItem *> QGraphicsScene::items () const

для преобразования из QGraphicsItem* в Cell* можешь использовать dynamic_cast:
QGraphicsItem *i;
Cell *c = dynamci_cast<Cell*>(i);
if (c != 0)
да это Cell
else
нет это не Cell

Devix
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.