Russian Qt Forum

Qt => 2D и 3D графика => Тема начата: break от Январь 03, 2009, 18:54



Название: рисование карандашом на виджете
Отправлено: break от Январь 03, 2009, 18:54
Как наиболее простым способом заставить рисовать как бы карандашом сверху фона (кот. из себф представляет простой рисунок) - рисование хочется производить мышкой?

Наверное правильнее создать свой виджет (или нет?)

Можно ли как то заюзать существующие - например выводить фон с помощью QLabel и только рисовать сверху перехватывая смобытия мышки?
Или правильнее использовать QGraphicsView - если да то как?


Название: Re: рисование карандашом на виджете
Отправлено: Dendy от Январь 03, 2009, 19:07
Свой виджет, что хранит QImage и перехватывая события мыши дорисовывает в него QPainter'ом. Эту картирку рисует сам в paintEvent().


Название: Re: рисование карандашом на виджете
Отправлено: break от Январь 03, 2009, 19:12
Да это как раз понятно - вопрос можно ли без создания своего виджета?


Название: Re: рисование карандашом на виджете
Отправлено: Dendy от Январь 03, 2009, 19:20
Думаю можно, а толку? Классы должны писаться всегда, когда создаётся новая сущность. Даже если технически можно обойтись без создания оного.


Название: Re: рисование карандашом на виджете
Отправлено: break от Январь 03, 2009, 19:46
Мне нужно наиболее простое решение задачи у кот. четкое т.з. и новосозданный компонент (если его все же прийдется писать) больше никогда не будет использоваться. Поэтому и создавать его не хочется.


Название: Re: рисование карандашом на виджете
Отправлено: break от Январь 03, 2009, 20:00
Пока нашел такое решение:

void CMyForm::mouseMoveEvent ( QMouseEvent * event )
{
   QPixmap * pix = (QPixmap*)ui.lbClearImage->pixmap();
   QImage  image = pix->toImage();
   
   image.setPixel( event->pos(), 1 );
   
   
   ui.lbClearImage->setPixmap( QPixmap::fromImage( image ) );
};

На форме лежит QLabel (ui.lbClearImage) с картинкой - рисовать на нем получается - осталось толко как то правильно преобразовать координаты от мыши event->pos().


Название: Re: рисование карандашом на виджете
Отправлено: Dendy от Январь 03, 2009, 20:10
Мне нужно наиболее простое решение задачи у кот. четкое т.з. и новосозданный компонент (если его все же прийдется писать) больше никогда не будет использоваться. Поэтому и создавать его не хочется.

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

Мой совет - вам самому нужно писать paintEvent(). Желательно в собственном классе.


Название: Re: рисование карандашом на виджете
Отправлено: break от Январь 03, 2009, 20:27
1) Выходит что в QT нет готового класса -сущности для рисования на нем мышкой?
2) Перекрывая PainEvent - я могу как угодно разрисовать свой виджет - но события от мыши для QWidget ловятся в mouseEvent - как их правильно связать?


Название: Re: рисование карандашом на виджете
Отправлено: Dendy от Январь 03, 2009, 20:39
1) Выходит что в QT нет готового класса -сущности для рисования на нем мышкой?

А также нет утилиты для чтения мыслей девелопера и генерации исходного кода из астрала. Во блин.

2) Перекрывая PainEvent - я могу как угодно разрисовать свой виджет - но события от мыши для QWidget ловятся в mouseEvent - как их правильно связать?

Вот видите, вы мыслите в верном направлении. События мыши должны быть энкапсулированы в тот же класс что и показывает картинку на экран.


Название: Re: рисование карандашом на виджете
Отправлено: break от Январь 03, 2009, 20:41
Запоминать позиции полученные в MouseEvent и вызывать update() - в котором по всем этим позициям пройдет прорисовка?


Название: Re: рисование карандашом на виджете
Отправлено: Dendy от Январь 03, 2009, 21:03
Развлёкся, нарисовал код.

Код:
#include <QApplication>
#include <QPainter>
#include <QImage>
#include <QMouseEvent>
#include <QPaintEvent>
#include <QWidget>


class Pa : public QWidget
{
public:
Pa()
{
pixmap_ = QPixmap( 4096, 4096 );
pixmap_.fill( 0xffffffff );
pen_ = QPen( QBrush( Qt::black ), 5.0f );
}

protected:
void mousePressEvent( QMouseEvent * e )
{
if ( e->button() == Qt::LeftButton )
{
QPainter p( &pixmap_ );
p.setPen( pen_ );
p.drawPoint( e->pos() );
p.end();

lastPoint_ = e->pos();

update();
}
}

void mouseMoveEvent( QMouseEvent * e )
{
if ( e->buttons() & Qt::LeftButton )
{
QPainter p( &pixmap_ );
p.setPen( pen_ );
p.drawLine( lastPoint_, e->pos() );
p.end();

lastPoint_ = e->pos();

update();
}
}

void paintEvent( QPaintEvent * )
{
QPainter p( this );
p.setCompositionMode( QPainter::CompositionMode_Source );
p.drawPixmap( QPoint(), pixmap_ );
}

private:
QPen pen_;
QPixmap pixmap_;
QPoint lastPoint_;
};




int main( int argc, char ** argv )
{
QApplication app( argc, argv );

Pa pa;
pa.show();

return app.exec();
}


Название: Re: рисование карандашом на виджете
Отправлено: break от Январь 04, 2009, 01:02
Спасибо!


Название: Re: рисование карандашом на виджете
Отправлено: break от Январь 04, 2009, 01:18
Еще маленький вопросик - при выводе фонового изображения как сделать чтобы была возможность изменения внутренней картинки под размеры виджета. То что достигалось свойством scaledContents в QLabel?


Название: Re: рисование карандашом на виджете
Отправлено: Dendy от Январь 04, 2009, 01:31
Фоновое - это на котором мы рисуем? Оно растровое, размер менять нельзя. Если про картинку на фоне - лучше один раз растянуть и закешировать через QPixmap::scaled() внутри resizeEvent(), а потом подкладывать под рисуемую картинку. Или тайлить оригинал. Главное понять суть задачи.


Название: Re: рисование карандашом на виджете
Отправлено: break от Январь 04, 2009, 04:37
Ok! Спасибо!