Russian Qt Forum

Qt => 2D и 3D графика => Тема начата: finka от Сентябрь 26, 2007, 16:30



Название: добавление GraphicsItem на сцену
Отправлено: finka от Сентябрь 26, 2007, 16:30
Допустим, код примерно такой:
Код:
QGraphicsScene * scene = new QGraphicsScene;
GraphicsItem * item;
for (int i = 0; i < MAX; i++)
{
    item = new GraphicsItem;
    scene->addItem(item);
}
QList <QGraphicsItem *> :: iterator iter;
int value;
for (iter = scene->items().begin(); iter != scene->items().end(); iter++)
{
    item = (GraphicsItem*)(*iter);
    tmp = item->myMember;
}
GraphicsItem - мой класс, наследованный от QGraphicsItem. При обращении к myMember (добавленное мной поле) происходит ошибка, точнее я вообще не могу обратиться ни к одному члену класса, кроме тех, что были в QGraphicsItem. Не могу понять, в чем дело:(


Название: Re: доваление GraphicsItem на сцену
Отправлено: pastor от Сентябрь 26, 2007, 16:34
А что за ошибку печатает? Возможно у тебя члены класса в private/protected секции. Сделай public аксессоры к твоим членам класса

Можешь показать код GraphicsItem?


Название: Re: доваление GraphicsItem на сцену
Отправлено: finka от Сентябрь 26, 2007, 16:43
Не, члены-то private, но функции доступа к ним public, и к членам я обращаюсь как раз через них, а ошибка происходит именно при обращению к члену (то есть уже в функции доступа). Сейчас посмотрела - там вообще все члены какие-то левые, в поле "value" написано: CXX0030: Error expression cannot be evaluated. А при обращении к какому-то члену класса, дебагер говорит :"0xC0000005: Access violation reading location 0xfeeefef2."


Название: Re: доваление GraphicsItem на сцену
Отправлено: goer от Сентябрь 26, 2007, 16:45
Вобще то для такого преобразования типов в С++ есть dynamic_cast - не стоит им пренебрегать ;)

И на будущее - телепаты уехали заграницу, там больше платят. Пожалуйста, описывайте проблемы так чтоб не приходилось флудить на форуме пустыми словами.


Название: Re: добавление GraphicsItem на сцену
Отправлено: pastor от Сентябрь 26, 2007, 17:19
Приведи код GraphicsItem. У тебя гдето не инициализирован указатель. Проверь item на 0 после сроки:

item = (GraphicsItem*)(*iter);

Для приведения типа здесь достаточно static_cast.


Название: Re: добавление GraphicsItem на сцену
Отправлено: goer от Сентябрь 26, 2007, 17:33
Приведи код GraphicsItem. У тебя гдето не инициализирован указатель. Проверь item на 0 после сроки:

item = (GraphicsItem*)(*iter);

Для приведения типа здесь достаточно static_cast.

Ребят, просил же, не разводите флуд и бесполезный флейм. Форуму это не на пользу, уважайте себя и других, не превращайте форум в помойку!
Цитировать
"Мудрый не все говорит, что знает, а дурак не все знает, что говорит."

Знатоки С++ идут лесом(упс!... читают Страуструпа).


Название: Re: добавление GraphicsItem на сцену
Отправлено: pastor от Сентябрь 26, 2007, 19:56
2 goer: А где флуд в моем посте? Последняя цитата в мой огород?


Название: Re: добавление GraphicsItem на сцену
Отправлено: vaprele07 от Сентябрь 27, 2007, 09:53
Цитировать
Знатоки С++ идут лесом(упс!... читают Страуструпа).
в раздел шаблоны  ::)


Название: Re: добавление GraphicsItem на сцену
Отправлено: finka от Октябрь 01, 2007, 09:19
Заметила интересную вещь. Если в представленном мной коде последний кусок
Код:
for (iter = scene->items().begin(); iter != scene->items().end(); iter++)
{
    item = (GraphicsItem*)(*iter);
    tmp = item->myMember;
}

заменить на следующий:

Код:
for (int i = 0; i < scene->items().size(); i++)
{
    item = (GraphicsItem *)scene->items().at(i);
    tmp = item->myMember;
}
, то все пучком. Другое дело, что если использовать такой метод доступа к элементам списка нерационален по времени.
Кстати, когда вместо тупого приведения к типу (В первом варианте кода) я использовала dynamic_cast, то программа вылетала непосредственно в самом dynamic_cast. А во втором варианте dynamic_cast естесвенно работает.


Название: Re: добавление GraphicsItem на сцену
Отправлено: vaprele07 от Октябрь 01, 2007, 11:36
finka попробуй вот это:
Код:
for (iter = scene->items().begin(); iter != scene->items().end(); iter++)
  qDebug() << "kosjk";
потом сравни кол-во косяков с кол-вом напиханных туда GraphicsItem  :o

такая конструкция прежде всего говорит, что передаётся не ссылка а копия возможно итэмы вообще хранятся не в QList...
QList<QGraphicsItem *> QGraphicsScene::items () const
далее в конструкции iter != scene->items().end() сравниваются указатели не на данные а на Node * (внутренняя структура класса QList ) содержащий указатель на данные! отсюдова и...
так что второй пример работает без ошибок и возможно быстрее...


Название: Re: добавление GraphicsItem на сцену
Отправлено: finka от Октябрь 01, 2007, 12:19
Цитировать
потом сравни кол-во косяков с кол-вом напиханных туда GraphicsItem 

Естественно, количество косяков совпадает с кол-вом итемов.

Цитировать
такая конструкция прежде всего говорит, что передаётся не ссылка а копия возможно итэмы вообще хранятся не в QList...
QList<QGraphicsItem *> QGraphicsScene::items () const
Я с этим и не спорю.

Цитировать
далее в конструкции iter != scene->items().end() сравниваются указатели не на данные а на Node * (внутренняя структура класса QList ) содержащий указатель на данные! отсюдова и...
А вот это непонятно. Что отсюдова?


Название: Re: добавление GraphicsItem на сцену
Отправлено: vaprele07 от Октябрь 01, 2007, 13:01
Цитировать
Естественно, количество косяков совпадает с кол-вом итемов.
нет не естественно :) у меня не совпадает, но и не в падает в вечное зацикливание, возможно везение. В любом случае эта ошибка возможна и вам это скажет каждый, кто боле менее знаком с циклами в стиле си (тем более если вас самих интересует скорость как показатель).

К пример у меня ваша конструкция с преобразованиями не вызывает никаких ошибок при любых раскладах.


Название: Re: добавление GraphicsItem на сцену
Отправлено: Tonal от Октябрь 01, 2007, 13:17
Код:
QGraphicsScene * scene = new QGraphicsScene;
GraphicsItem * item;
for (int i = 0; i < MAX; i++)
{
    item = new GraphicsItem;
    scene->addItem(item);
}
[b]QList <QGraphicsItem *> :: iterator iter;[/b]
int value;
for (iter = scene->items().begin(); iter != scene->items().end(); iter++)
{
    item = (GraphicsItem*)(*iter);
    tmp = item->myMember;
}
GraphicsItem - мой класс, наследованный от QGraphicsItem.
Если ты привела полный код, то ошибка в выделенной строке.
Функция QGraphicsScene::items возвращает QList<QGraphicsItem *> где QGraphicsItem из стандартных заголовков Qt.
А в выделенной строке ты объявляешь итератор по QList<QGraphicsItem *> где QGraphicsItem определён тобой.
Не совсем понятно какое именно преобразование происходит при таком присвоении итераторов.
Попробуй переименовать свой класс, или явно прописать пространство имён для стандартного.

P.S. Кстати, какой компилятор и версия Qt?
P.P.S. Да, если на сцене присутствует хотя бы один итем не того типа, а например стандартного, то глюки тоже обеспечены. Для того чтобы их избежать пользуйся dynamic_cast-ом. Если же ты уверена, что такого быть не может ставь static_cast.
Я, обычно, делаю примерно так:
Код:
  assert(dynamic_cast<GraphicsItem*>(*iter));
  item = static_cast<GraphicsItem*>(*iter);
Т.е. при отладке получаешь assert, а в релизе не тормозит. ;-)


Название: Re: добавление GraphicsItem на сцену
Отправлено: pastor от Октябрь 01, 2007, 13:49
Есть еще такая функция: qgraphicsitem_cast

2 Tonal: что-то я не понял сказанное вами:

Цитировать
Функция QGraphicsScene::items возвращает QList<QGraphicsItem *> где QGraphicsItem из стандартных заголовков Qt.
А в выделенной строке ты объявляешь итератор по QList<QGraphicsItem *> где QGraphicsItem определён тобой.

У неё класс называеться GraphicsItem, который наследованный от QGraphicsItem

2 finka: Можете выложить полный код GraphicsItem?



Название: Re: добавление GraphicsItem на сцену
Отправлено: Tonal от Октябрь 01, 2007, 13:52
Точно, протупил. ;-)


Название: Re: добавление GraphicsItem на сцену
Отправлено: finka от Октябрь 02, 2007, 10:23
vaprele07 , я, честно говоря, не могу понять, почему число добавленных в сцену итемов и число элементов в списке может не совпадать. Хотя, должна сказать, у меня уже был какой-то глюк при обращении к элементам списка через итератор, но тогда я просто плюнула на итератор, обращалась к элементам напрямую и благополучно забыла и забила на это дело. А тут вот опять.

pastor , полный код выложить не могу, но если вы поверите на слово, то скажу, что там ничего интересного нет:) Парочка лишних полей, которые инициализируются в конструкторе.

Qt 4.3.1 под VS2005.


Название: Re: добавление GraphicsItem на сцену
Отправлено: pastor от Октябрь 02, 2007, 10:34
2 finka: Хотелось бы увидеть ваш код, скомпилить его у себя и пронаблюдать эту проблему. Может проблема ваще не в этом месте


Название: Re: добавление GraphicsItem на сцену
Отправлено: vaprele07 от Октябрь 02, 2007, 11:04
finka, в цикле в самом первом коде обращение идет не к самому спуску на прямую, а к функции которая этот список формирует, в итоге у вас iter возможно сравнивается не с тем end()
сделай хоть вот так:
Код:
QList<QGraphicsItem *> items = scene->items();
for (iter = items.begin(); iter != items.end(); iter++)

вот как выглядит функция QGraphicsScene::items() в QT4.3.0:
Код:
QList<QGraphicsItem *> QGraphicsScene::items() const
{
    ...

    // Rebuild the list of items to avoid holes. ### We could also just
    // compress the item lists at this point.
    QList<QGraphicsItem *> itemList;
    foreach (QGraphicsItem *item, d->indexedItems + d->unindexedItems) {
        if (item)
            itemList << item;
    }
    return itemList;
}
сразу видно что у меня ваш код генерировал бы ошибку   :-\ делайте выводы...


Название: Re: добавление GraphicsItem на сцену
Отправлено: finka от Октябрь 02, 2007, 11:15
vaprele07, спасибо, как только соберу проект, попробую. Действительно, стормозила.


Название: Re: добавление GraphicsItem на сцену
Отправлено: finka от Октябрь 02, 2007, 11:22
Кстати, чтобы не открывать очередную тему по VS2005, задам тут вопрос:
Ставила все по инструкции с этой ссылки http://qtnode.net/wiki?title=Qt4_with_Visual_Studio#Obtain_and_install_the_Qt_source
Собираю проект:
qmake -project -t vcapp -o projectName.pro
qmake
Появляются ворнинги:
Warning: Failure to find: c:\...\sample.h
Warning: Failure to find: c:\...\sample.cpp
Warning: Failure to find: c:\...\sample.h
Warning: Failure to find: c:\...\sample.cpp

Причем файлы sample.h и sample.cpp существуют и находятся в той же директории, в которой я собираю проект, а также присутствуют в projectName.pro. Может это слово sample какое-то особенное?

Кстати, несмотря на эти ворнинги, все компилируется и работает потом нормально.

vaprele07 , спасибо, теперь все работает, как надо:)