PDA

View Full Version : Drawing polygon using event filter in Qt



benz6699
17th September 2014, 07:30
I am working on a feature in my GUI that allow user to draw polygon by clicking the points.
First the user needs to enable this function by clicking a button. After that the user clicks any four points on the screen. When the fourth point is clicked, all the 4 points will be connected to form a polygon.

However the polygon is not appearing after the fourth is clicked. Instead there is a message of "QPainter::begin: Paint device returned engine == 0, type: 1". What is the problem in my code?


bool QTGraphicsShape::eventFilter(QObject *obj, QEvent *event)
{
double static x[4],y[4];
int static i;
if ((event->type() == QEvent::GraphicsSceneMouseRelease) && (Draw3Points == true)) {
QGraphicsSceneMouseEvent *mouseEvent = static_cast< QGraphicsSceneMouseEvent* >( event );
QPointF img_coord_pt = mouseEvent->scenePos();
x[i] = img_coord_pt.x();
y[i] = img_coord_pt.y();
i++;
if (i >= 4)
{
Draw3Points = false;
i=0;
static const QPointF points[4] = {
QPointF(x[0], y[0]),
QPointF(x[1], y[1]),
QPointF(x[2], y[2]),
QPointF(x[3], y[3])
};
QPainter painter(this);
painter.drawPolygon(points, 4);
}
return true;
} else {
return QObject::eventFilter(obj, event);
}
}

void QTGraphicsShape::on_pushButton_clicked()
{
ui.graphicsView->setMouseTracking(true);
Draw3Points = true;
m_pGraphicsScene->installEventFilter(this);
}

anda_skoa
17th September 2014, 09:13
You are drawing on "this". Is "this" an object of a class that is a QPaintDevice?

Any specific reason for the event filter hack instead of implementing the event handling in the scene?

Cheers,
_

d_stranz
17th September 2014, 18:11
In addition, you cannot use a QPainter to draw on screen anywhere except in a paintEvent(). See the docs:


Warning: When the paintdevice is a widget, QPainter can only be used inside a paintEvent() function or in a function called by paintEvent().

so, you need to collect the points in a data structure as the user clicks, and then draw the polygon in a paintEvent().

Of course, you understand that with the code you are trying to implement (ie using a single static data structure to hold the points and the count of clicks), even if you move it into a paintEvent(), the QPainter will very briefly draw the polygon after the 4th click, then immediately erase it on the next paint event because you've set i = 0 and Draw3Points = false.

You need to rethink what you really want your software to do and implement a set of data structures and logic that does it.

benz6699
19th September 2014, 07:09
You are drawing on "this". Is "this" an object of a class that is a QPaintDevice?

Any specific reason for the event filter hack instead of implementing the event handling in the scene?

Cheers,
_

"this" is "class QTGraphicsShape : public QMainWindow"

The reason I use event filter is that my drawing feature is only activated when I click certain button. Is it unnecessary in this case?

anda_skoa
19th September 2014, 08:55
"this" is "class QTGraphicsShape : public QMainWindow"

You can only draw on a QWidget in its paintEvent() method.
You can of course draw into a buffer elsewhere and then draw the buffer in paintEvent().

In the case of QMainWindow it is very uncommon to do any drawing there, usually it contains further widgets as its content.



The reason I use event filter is that my drawing feature is only activated when I click certain button. Is it unnecessary in this case?

That is not related at all.

Mouse event processing should happen at the widget that receives them, or in the case of a QGraphicsView potentially in the scene or its items.

Cheers,
_