Russian Qt Forum

Qt => 2D и 3D графика => Тема начата: allco от Апрель 01, 2008, 10:50



Название: Реализация скроллинга в QGraphicsScene
Отправлено: allco от Апрель 01, 2008, 10:50
Недавно столкнулся с интересной задачей:

В QGraphicsScene необходимо создать элемент управления (порожденный от QGraphicsItem), который представлял бы из себя список большого количества строк (более 1000) с возможностью вертикального скроллинга.


Пытался решить так:
ScrollableArea -  небольшой QGraphicsItem (400x400), с установленным флагом "QGraphicsItem::ItemClipsChildrenToShape", который должен служить областью скроллирования.

StringSpace - QGraphicsItem огромного размера, достаточного для того чтобы вместить все строки (> 1000). Каждая строка представляет собой также отдельный QGraphicsItem, который является дочерним по отношению к StringSpace.

Затем StringSpace сделал дочерним по отношению к ScrollableArea.
Т.о. на экране всегда видно только часть StringSpace, которая попадает внутрь ScrollableArea.
Скроллинг организовал путем перемещения StringSpace относительно ScrollableArea.

В итоге получил жуткие тормоза.


Как решить проблему ?
Может кто-то сможет предложить другой способ реализации скроллинга ?



Название: Re: Реализация скроллинга в QGraphicsScene
Отправлено: shadone от Апрель 01, 2008, 17:35
Начиная с версии qt-4.4 имеется возможность добавлять стандартные widget'ы на QGraphicsScene/QGraphicsView. Вероятно именно это и нужно использовать (точно сказать трудно не зная задачи - что за 1000 строк - только ли строки (QLabel/QTextEdit?) это?

Хотя сильно тормозить все равно не должно и в вашем решении. Но не видя кода сказать нечего.


Название: Re: Реализация скроллинга в QGraphicsScene
Отправлено: allco от Апрель 02, 2008, 08:54
Qt_4.4 конечно хорошая штука, но пока нет релиза, использовать ее - не могу.

Следующий пример кода, хотя немного проще чем моя идея по реализации скроллинга, но, тем не менее, он достаточно ярко демонстрирует проблему.

Создается огромного размера рект, в который сажается 1000 маленьких ректов.
Основной рект делается таскаемым.

Попробуйте октомпилить этот код, и потаскать рект.
Получите жуткие тормоза.

Код:
#include <QApplication>
#include <QGraphicsRectItem>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QtGlobal>

#define CNCHILDS 1000
#define getrandom(min, max) ((qrand()%(int)(((max) + 1)-(min)))+ (min))

int main(int argc, char *argv[])
{
QApplication a(argc, argv);

QGraphicsScene* pscene = new QGraphicsScene();
QGraphicsRectItem* pMainRect = new QGraphicsRectItem;

QSizeF szChild(200, 40);
pMainRect->setFlag(QGraphicsItem::ItemIsMovable);
pMainRect->setRect(0,0, szChild.width(), CNCHILDS*szChild.height());
pMainRect->setBrush(Qt::green);

for (int i=0; i < CNCHILDS; i++)
{
QGraphicsRectItem* prcChild = new QGraphicsRectItem(pMainRect);
prcChild->setRect(0, i*(szChild.height()), szChild.width(), szChild.height());
prcChild->setBrush(QColor(
getrandom(100,150),
getrandom(100,150),
getrandom(100,150)
));
}

pscene->addItem(pMainRect);
QGraphicsView* pview = new QGraphicsView;
pview->setGeometry(50,50,800,600);
pview->setScene(pscene);
pview->show();

a.connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()));
a.exec();

return 0;
}


Еще была идея использовать еще одну сцену в памяти, рисовать элементы в нее, а затем выплевывать на экран изображение с помощью QGraphicsScene::render(...). Таскание тогда дполучаеться приемлимое, но теряется  интерактивность элементов (перерисовка при ховере, клики и пр.)

Если бы можно было бы как-то завернуть QGraphicsScene внутрь QGraphicsItem и не потерять интеративность, то возможно проблема бы решалась. Но как это сделать - вопрос.

Здесь Qt_4.4 конечно могла бы помочь, за счет вставления QGraphicsView как виджета в сцену, но пока нет релиза использовать ее - опасно.


Название: Re: Реализация скроллинга в QGraphicsScene
Отправлено: shadone от Октябрь 19, 2008, 15:03
мда, я видимо упустил шанс ответить в этой теме :)
но все равно - попробовал этот код на celeron 900mhz (asus eeepc 900) - элемент таскается с небольшими задержками, но их нельзя назвать жуткими.