Qt 4.7 - Drawing a 2 point line with dynamic feedback using paintEvent
-
12-12-2019 - |
Question
so I am trying to draw a line between two points. Left mouse click starts the line then I would like the line to by dynamically drawn as the mouse moves (almost like a preview of the line). Left mouse click again and the line will be permanently drawn. I know there are a lot of other posts about QPaintEvents and I have combined some of the techniques used, but for some reason nothing is being drawn to the canvas. Below is the code:
void Main::mousePressEvent(QMouseEvent * event)
{
if (event->button() == Qt::LeftButton) {
QPointF pos = event->pos();
if( mStartPoint.isNull() ) {
if(josh.contains(pos))
mStartPoint = pos;
} else {
canvas.addLine(mStartPoint.x(),mStartPoint.y(),pos.x(),pos.y());
mStartPoint = QPointF();
}
}
}
bool Main::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::MouseMove)
{
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
if (!mStartPoint.isNull()) {
m_targetImage = QImage(canvas.width(),canvas.height(),QImage::Format_ARGB32);
QPainter p;
p.begin(&m_targetImage);
p.drawLine(mStartPoint, mouseEvent->pos());
p.end();
}
statusBar()->showMessage(QString("Mouse move (%1,%2)").arg(mouseEvent->pos().x()).arg(mouseEvent->pos().y()));
}
return false;
}
void Main::paintEvent(QPaintEvent *pe)
{
QPainter painter(this);
QPen pen(Qt::red);
pen.setWidth(10);
painter.setPen(pen);
painter.drawImage(0, 0, m_targetImage);
}
Any help is appreciated! Thanks! Josh
Solution
I think this is what you want. Change parameters according to your requirements.
//In your constructor
m_nInitialX = 0;
m_nInitialY = 0;
m_nFinalX = 0;
m_nFinalY = 0;
m_nPTargetPixmap = 0;
m_nPTargetPixmap = new QPixmap(400,400);
m_nbMousePressed = false;
void Main::mousePressEvent(QMouseEvent* event)
{
m_nbMousePressed = true;
m_nInitialX = event->pos().x();
m_nInitialY = event->pos().y();
}
void Main::mouseReleaseEvent(QMouseEvent *event)
{
m_nbMousePressed = false;
}
void Main::paintEvent(QPaintEvent *e)
{
if(m_nbMousePressed)
{
QPainter PixmapPainter(m_nPTargetPixmap);
QPen pen(Qt::green);
PixmapPainter.setPen(pen);
PixmapPainter.drawLine(m_nInitialX, m_nInitialY, m_nFinalX, m_nFinalY);
}
QPainter painter(this);
painter.drawPixmap(0, 0, *m_nPTargetPixmap);
}
void Main::mouseMoveEvent(QMouseEvent *event)
{
if (event->type() == QEvent::MouseMove)
{
QPainter PixmapPainter(m_nPTargetPixmap);
QPen pen(Qt::black);
PixmapPainter.setPen(pen);
PixmapPainter.drawLine(m_nInitialX, m_nInitialY, m_nFinalX, m_nFinalY);
update(); // update your view
m_nFinalX = event->pos().x();
m_nFinalY = event->pos().y();
}
update(); // update your view
}
This piece of code will draw a 2 point line
that you want.
OTHER TIPS
Here's my example of how to paint lines in your way directly on the widget.
Declaration:
private:
void drawLines(QPainter *p);
QPoint startPos;
QPoint endPos;
bool inDrawing;
QVector<QLine> lines;
Setting initial values in constructor:
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
startPos = QPoint();
endPos = QPoint();
inDrawing = false;
setMouseTracking(true);
}
Starting or ending the line drawing:
void Widget::mousePressEvent(QMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton)
{
if (!inDrawing)
{
startPos = event->pos();
}
else
{
endPos = event->pos();
QLine line = QLine(startPos, event->pos());
lines.append(line);
}
inDrawing = !inDrawing;
}
}
void Widget::mouseMoveEvent(QMouseEvent *event)
{
if (inDrawing)
{
endPos = event->pos();
update();
}
}
Drawing current and saved lines:
void Widget::drawLines(QPainter *p)
{
if (!startPos.isNull() && !endPos.isNull())
{
p->drawLine(startPos, endPos);
}
p->drawLines(lines);
}
Drawing:
void Widget::paintEvent(QPaintEvent *event)
{
QPainter p(this);
QPen pen;
pen.setColor(Qt::red);
pen.setWidth(4);
p.setPen(pen);
drawLines(&p);
}