Russian Qt Forum

Qt => 2D и 3D графика => Тема начата: ecspertiza от Июль 30, 2012, 12:28



Название: QGraphics размытие
Отправлено: ecspertiza от Июль 30, 2012, 12:28
Есть задача сделать размытие выделенной области. Стало быть у меня есть QGraphicsView я для него задал background, стало быть помещаю на сцену QGraphicsItem для него задаю эффект setGraphicsEffect(new QGraphicsBlurEffect) , но размытие есть только на самом итеме, а хотелось бы что бы эффект был применен ко всему что есть под итемом размытия. Как это можно реализовать ? Есть конечно вариант, мол сграбливать изображение которое под итемом, но он может перемещать и изменять свои размеры, боюсь это может на скорости сильно сказаться, поэтому хотелось бы какой нибудь вариант покрасивее.


Название: Re: QGraphics размытие
Отправлено: ecspertiza от Июль 31, 2012, 13:42
Так и думал что будут с этим сложности :) Может есть вариант как можно просто размыть часть сцены ?


Название: Re: QGraphics размытие
Отправлено: Igors от Июль 31, 2012, 16:30
Ну размывать сцену мне кажется "не очень хорошо", напр может быть др айтем который пострадает безвинно. Может быть просто увеличить айтем (или добавить ему спец бордюр) чтобы "компенсировать" эффект и добиться лучшего вида. Вообще скриншот показывающий проблему здесь был бы к месту. 


Название: Re: QGraphics размытие
Отправлено: ecspertiza от Июль 31, 2012, 18:40
В том и дело что пострадать(размыть) должно все что есть в выделенной области, задача такая что должен быть итем который размывает все что находиться под ним, будь то сцена с background или другой итем.

Вложил скрин, на нем видно что есть сцена с background, на ней итем у которого задан эффект размытия 

Код:
setGraphicsEffect(new QGraphicsBlurEffect);

получается так что размывается только итем. Есть идея, при рисовании итемов на сцене кешировать рисунок в фции paint. Затем при рисовании размытия, проверять на пересекающиеся итемы, получать от них координаты пересечения ,а так же из кеша выдирать рисунок, и рисовать его на итеме размытия. Но есть подозрение что это не путь джедая.


Название: Re: QGraphics размытие
Отправлено: Igors от Июль 31, 2012, 19:06
получается так что размывается только итем. Есть идея, при рисовании итемов на сцене кешировать рисунок в фции paint. Затем при рисовании размытия, проверять на пересекающиеся итемы, получать от них координаты пересечения ,а так же из кеша выдирать рисунок, и рисовать его на итеме размытия. Но есть подозрение что это не путь джедая.
Выглядит сложновато/геморройно. Вы можете направить весь вывод сначала в QImage а потом уже на экран? Координаты где блюрить знаете? Если да то остальное (заблюрить в QImage) - ну на полчаса работы максимум   


Название: Re: QGraphics размытие
Отправлено: ecspertiza от Июль 31, 2012, 20:04
Боюсь направить весь вывод в QImage не прокатит, так было в старой версии программы, и отказались от этого в пользу итемов и сцены, что бы можно было управлять итемами. Ну например ресайзить, перемещать, ворочать.

А координаты знаю, они равны координатам итема размытия.
Алгоритм размытия тож есть от старой версии проги остался.

Я просто почему то думал что есть простой путь, мол там свойство задали и эффект будет распространяться на все что под итемом.


Название: Re: QGraphics размытие
Отправлено: Igors от Июль 31, 2012, 20:26
Боюсь направить весь вывод в QImage не прокатит, так было в старой версии программы, и отказались от этого в пользу итемов и сцены, что бы можно было управлять итемами. Ну например ресайзить, перемещать, ворочать.
Не верится что "не прокатит", ведь, грубо говоря, сцена - виджет, а значит рендерить ее в QImage можно, и управлению айтемами это никак не противоречит. А что делать если напр сцена - всего лишь один "слой" который комбинируется еще со многими? Должно быть

Я просто почему то думал что есть простой путь, мол там свойство задали и эффект будет распространяться на все что под итемом.
Да, Qt плюшки конечно очень вкусные и с огромным удовольствием поедаются. Но что будет с человеком если он жрет только плюшки? Так что "не совсем простой" путь полезнее  :)


Название: Re: QGraphics размытие
Отправлено: ecspertiza от Июль 31, 2012, 20:46
Не верится что "не прокатит", ведь, грубо говоря, сцена - виджет, а значит рендерить ее в QImage можно, и управлению айтемами это никак не противоречит. А что делать если напр сцена - всего лишь один "слой" который комбинируется еще со многими? Должно быть

Ну то есть как не прокатит, прокатит конечно. Но я тогда не совсем представляю архитектуру приложения. Вот допустим пользователю нужно нарисовать квадрат, затем он понял что нарисовал его не там и его нужно переместить. Как я вижу это при работе с QImage сначала мы создаем итем квадрат и пользователь его двигает или ресайзит, все хорошо, пользователь закончил рисование, и мы этот квадрат нарисовали в QImage который в свою очередь отрендерили на сцене. Все хорошо. Но пользователь понял что ему просто жизненно необходимо переместить квадрат, он на него кликает и должен тянуть его куда то дальше, как быть в этом случае не совсем понятно ведь QImage то уже отрисован. Возможно просто я не всю задачу обрисовал :) должно получиться что то вроде examples/graphicsview/diagramscene только будут другие элементы, но то что все что создано на сцене можно будет таскать это точно.


Название: Re: QGraphics размытие
Отправлено: lighting от Август 01, 2012, 10:04
Как я вижу это при работе с QImage сначала мы создаем итем квадрат и пользователь его двигает или ресайзит, все хорошо, пользователь закончил рисование, и мы этот квадрат нарисовали в QImage который в свою очередь отрендерили на сцене. Все хорошо. Но пользователь понял что ему просто жизненно необходимо переместить квадрат, он на него кликает и должен тянуть его куда то дальше, как быть в этом случае не совсем понятно ведь QImage то уже отрисован.
Так вы не просто отрисовывайте в QImage квадрат а сохраните его в списке объектов (координаты, z, цвет) и каждый раз  отрисовывайте его заново если он изменился. Правда в таком случае это уже будет свой педальный GraphicsView и я не уверен что целесообразно будет такой велосипед строить, все от конкретной задачи зависит.


Название: Re: QGraphics размытие
Отправлено: ecspertiza от Август 01, 2012, 10:33
по сути в таком случае нужно свой граф фреймворк писать :) даже не знаю что проще выйдет, искать все пересечения, или эту тему с QImage. Мне же еще придется как то определять в зависимости от координат и z на какой объект кликнули и какой потянули. Кажется что тема с кешированием выглядит попроще :)


Название: Re: QGraphics размытие
Отправлено: Igors от Август 01, 2012, 11:00
Ну то есть как не прокатит, прокатит конечно. Но я тогда не совсем представляю архитектуру приложения. Вот допустим пользователю нужно нарисовать квадрат, затем он понял что нарисовал его не там и его нужно переместить. Как я вижу это при работе с QImage сначала мы создаем итем квадрат и пользователь его двигает или ресайзит, все хорошо, пользователь закончил рисование, и мы этот квадрат нарисовали в QImage который в свою очередь отрендерили на сцене.
Я имел ввиду перехватить вывод всей сцены. Т.е. пусть двигает что и как хочет, все равно в конце концов paintEvent придет, вот там и блюрить.


Название: Re: QGraphics размытие
Отправлено: ecspertiza от Август 01, 2012, 11:15
Всмысле в painEvent получаем координаты всех итемов размытия и там уже делаем само размытие :-\
Нужно попробовать, звучит хорошо, спасибо :)


Название: Re: QGraphics размытие
Отправлено: GreatSnake от Август 01, 2012, 14:18
Попробуй это:

Код
C++ (Qt)
Q_GUI_EXPORT void qt_blurImage( QPainter* p, QImage& blurImage, qreal radius, bool quality, bool alphaOnly, int transposed = 0 );
 
class BlurRectItem : public QGraphicsRectItem
{
public:
BlurRectItem( const QRectF& rect )
: QGraphicsRectItem( rect )
, radius_( 5 )
, in_grab_( false )
{
setZValue( 10000 );
setFlag( ItemIsMovable );
setCursor( Qt::OpenHandCursor );
}
void paint( QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0 )
{
if( in_grab_ )
return;
in_grab_ = true;
QImage img( rect().size().toSize(), QImage::Format_RGB32 );
QPainter p( &img );
p.eraseRect( rect() );
p.setRenderHint( QPainter::Antialiasing );
scene()->render( &p, QRectF(), sceneBoundingRect() );
p.end();
in_grab_ = false;
painter->save();
qt_blurImage( painter, img, radius_, true, false );
painter->restore();
painter->drawRect( rect() );
}
qreal blurRadius() const { return radius_; }
void setBlurRadius( qreal r ) { radius_ = r; }
 
private:
bool in_grab_;
qreal radius_;
};
 

Просто создаёшь на сцене BlurRectItem и не используешь QGraphicsBlurEffect.


Название: Re: QGraphics размытие
Отправлено: ecspertiza от Август 01, 2012, 15:00
GreatSnake, спасибо , только нашел решение с render, зашел на форум отписать ,а тут твой ответ :)

Вообщем как всегда все оказалось просто, можно получить часть сцены прямо в итеме используя при этом ф-цию render(), она от рисует в QPainter фрагмент который в нее будет передан


Название: Re: QGraphics размытие
Отправлено: ecspertiza от Август 01, 2012, 15:10
А про

Код:
Q_GUI_EXPORT void qt_blurImage( QPainter* p, QImage& blurImage, qreal radius, bool quality, bool alphaOnly, int transposed = 0 );

я не знал, использовал свою похожую функцию, буду знать про такую фичу, спасибо :)