PDA

View Full Version : QGLWidget crashes on frequent updates



kkk777kkk
10th September 2010, 10:57
Hi. I draw in paintGL () on my Widget inherited from QGLWidget through QPainter functions, but after receiving a certain number of points the application crashes, the impression that somewhere something is overflowing, but I can not understand why. With 6 copies of the widget on the form it holds for 400-600 points for each graph, with 3 - to 900. I add 1 point and than update paintGL() and if i draw the graph with around 20000 points at once and update paintGl() it will be ok but when i start normal cycle at about 20600 it will crash in same way. I understand that something overflowing, help me please understand where is my problem.
System: WinXp, Qt 4.6.3 (mingw 4.4.3) . Project in attachment.


void GraphDraw::paintGL()
{
QPainter painter(this);
if (points.count()>2 || pointsx.count()>2) {
float maxXp;
float minXp;
float maxYp;
float minYp;
float maxXt;
float minXt;
float maxYt;
float minYt;
float stepX;
float stepY;

painter.translate(0, float(height())/2);

if (!zoom) {
maxXt = maxX;
minXt = minX;
maxYt = maxY;
minYt = minY;
}
else {
maxXt = zoomListMax[zoom-1].first;
minXt = zoomListMin[zoom-1].first;
maxYt = zoomListMax[zoom-1].second;
minYt = zoomListMin[zoom-1].second;
}

stepX = qAbs(maxXt - minXt)/10;
stepY = qAbs(maxYt - minYt)/10;
maxXp = maxXt + 0.4*stepX;
minXp = minXt - 0.4*stepX;
maxYp = maxYt + 0.4*stepY;
minYp = minYt - 0.4*stepY; //
wsx = float(width()) / qAbs(maxXp - minXp);
wsy = float(height()) / qAbs(maxYp - minYp);
wdx = float(width())/2 - (maxXp*wsx + minXp*wsx)/2;
wdy = - (maxYp*wsy + minYp*wsy)/2;


for (float i=minXt;i<maxXt+stepX;i+=stepX) {
painter.setPen(palette().dark().color());
painter.drawLine(QPointF(i*wsx + wdx, -float(height())/2), QPointF(i*wsx + wdx, float(height())/2));
painter.setPen(QPen(Qt::darkGreen));
painter.drawText(QPointF(i*wsx + wdx -float(fm->width(QString::number(i,'f',1))/2), float(25)/2), QString::number(i,'f',1));
}
for (float i=minYt;i<=maxYt+stepY;i+=stepY) {
painter.setPen(palette().dark().color());
painter.drawLine(QPointF(0, -(i*wsy + wdy)), QPointF(width(), -(i*wsy + wdy)));
painter.setPen(QPen(Qt::darkGreen));
painter.drawText(QPointF(5, -(i*wsy + wdy+4)),QString::number(i,'f',4));
}

painter.setRenderHint(QPainter::Antialiasing, antialiasing);//сглаживание
painter.setPen(QPen(Qt::red, 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));

if (sorting) {
QPointF *mpoints = new QPointF[points.count()];
QList<float> pointsk(points.keys());
for (int m = 0; m<points.count(); m++)
mpoints[m]=QPointF(pointsk[m]*wsx + wdx, -(points.value(pointsk[m])*wsy + wdy));
painter.drawPolyline(mpoints, points.count());
delete []mpoints;
}
else {
QPointF *mpoints = new QPointF[pointsx.count()];
for (int m = 0; m<pointsx.count(); m++)
mpoints[m]=QPointF(pointsx[m]*wsx + wdx, -(pointsy[m]*wsy + wdy));
painter.drawPolyline(mpoints, pointsx.count());
delete []mpoints;
}

painter.translate(0, -float(height())/2);

painter.setPen(QPen(Qt::black, 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
painter.drawRect(QRect(0, 0, width(), height()));
// font.setStyleStrategy(QFont::OpenGLCompatible);
// font.setStyleStrategy(QFont::PreferAntialias);

painter.drawText(float(width())-fm->width("<--- " + xlegend)-10, 15, "<--- " + xlegend);

painter.rotate(90);

painter.drawText(30, -width()+20, ylegend + " --->");

painter.rotate(-90);

if (mouseState)
painter.drawRect(QRectF(clickPoint, currPoint));
}
}


GraphDraw::GraphDraw(QWidget *parent) //: QWidget(parent)
: QGLWidget(QGLFormat(QGL::SampleBuffers/* | QGL::DoubleBuffer | QGL::DirectRendering*/), parent)
{
// setAttribute(Qt::WA_OpaquePaintEvent);
setBackgroundRole(QPalette::Base);
setAutoFillBackground(true);
setMouseTracking(true);
setCursor(Qt::CrossCursor);
maxX = -(numeric_limits<float>::max());
minX = numeric_limits<float>::max();
maxY = -(numeric_limits<float>::max());
minY = numeric_limits<float>::max();
QFont fonttemp(font()); fonttemp.setPointSize(6); setFont(fonttemp);
fm = new QFontMetrics(font());
sorting = false;
antialiasing = false;

mouseState = 0;
zoom = 0;
wsx = 0;
wsy = 0;
wdx = 0;
wdy = 0;
}

JohannesMunk
13th September 2010, 11:35
Hi there!

With 6 of your widgets you are creating 6 OpenGL contexts. And for each repaint you create a new painter on it. Thats quite expensive.

Try the following: Make your GraphDraw a simple Widget like it was before. Move your paint calls to its paintEvent and use the passed painter.

Add your 6 widgets to a big graphicsscene using addWidget. Setup the GraphicsView to use OpenGL. That way all drawing is done via OpenGL, but with only one bigger OpenGL context.



scene = new QGraphicsScene();

graphicsView = new QGraphicsView(this);

graphicsView->setRenderHint(QPainter::Antialiasing, true);
graphicsView->setOptimizationFlags(QGraphicsView::DontSavePainte rState);
graphicsView->setViewportUpdateMode(QGraphicsView::SmartViewport Update);
graphicsView->setResizeAnchor(QGraphicsView::AnchorViewCenter);

graphicsView->setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));

graphicsView->setScene(scene);
graphicsView->centerOn(0,0);
graphicsView->show();

scene->addWidget ..

HIH

BTW: Have you checked QwtPlot http://qwt.sourceforge.net/

Joh