A Double Buffering example
-
Hi all,
I wrote this Double Buffering and tried to run it, but I got this output:
At the bottom it also has been written:
this function deprecated, ignoredWhat are the problems for the plotter that doesn't show anything and also for that message at the bottom, please?
-
Which function call causes that message?
-
@Wieland Hallo
There is no clear lead where that message belongs to. I also analysed the code twice to figure the issue out but couldn't find it.
The project name is Plotter as follows:
plotter.h
:#ifndef PLOTTER_H #define PLOTTER_H #include <QMap> #include <QPixmap> #include <QVector> #include <QWidget> class QToolButton; class PlotSettings; class Plotter : public QWidget { Q_OBJECT public: Plotter(QWidget* parent = 0); ~Plotter(); void setPlotSettings(const PlotSettings&); void setCurveData(int, const QVector<QPointF>&); void clearCurve(int); QSize minimumSizeHint() const; QSize sizeHint() const; public slots: void zoomIn(); void zoomOut(); protected: void paintEvent(QPaintEvent*); void resizeEvent(QResizeEvent*); void mousePressEvent(QMouseEvent*); void mouseMoveEvent(QMouseEvent*); void mouseReleaseEvent(QMouseEvent*); void keyPressEvent(QKeyEvent*); void wheelEvent(QWheelEvent*); private: void updateRubberBandRegion(); void refreshPixmap(); void drawGrid(QPainter*); void drawCurves(QPainter*); enum { Margin = 50 }; QToolButton* zoomInButton; QToolButton* zoomOutButton; QMap<int, QVector<QPointF>> curveMap; QVector<PlotSettings> zoomStack; int curZoom; bool rubberBandIsShown; QRect rubberBandRect; QPixmap pixmap; }; //************************************************ class PlotSettings { public: PlotSettings(); void scroll(int, int); void adjust(); double spanX() const { return maxX - minX; } double spanY() const { return maxY - minY; } double maxX; double minX; int numXTicks; double maxY; double minY; int numYTicks; private: static void adjustAxis(double&, double&, int&); }; #endif // PLOTTER_H
main.cpp
:#include <QtWidgets> #include "plotter.h" void readFlightCurves(Plotter *plotter, const QString &fileName) { QVector<QPointF> data[6]; double factX = 0.0013; double factY[6] = { 0.0008, 0.1, 0.2, 0.2, 0.1, 0.8 }; double offsY[6] = { +500, -55, +309, +308, 0, 0 }; int pos[6] = { 3, 6, 7, 8, 9, 10 }; QFile file(fileName); double offsX = 0.0; if (file.open(QIODevice::ReadOnly)) { QTextStream in(&file); while (!in.atEnd()) { QString line = in.readLine(); QStringList coords = line.split(' ', QString::SkipEmptyParts); if (coords.count() >= 6) { double x = factX * coords[0].toDouble(); if (data[0].isEmpty()) offsX = x; for (int i = 0; i < 6; ++i) { double y = coords[pos[i]].toDouble(); data[i].append(QPointF(x - offsX, factY[i] * (y - offsY[i]))); } } } } plotter->setCurveData(0, data[0]); plotter->setCurveData(1, data[1]); plotter->setCurveData(2, data[2]); plotter->setCurveData(3, data[3]); plotter->setCurveData(4, data[4]); plotter->setCurveData(5, data[5]); } int main(int argc, char *argv[]) { QApplication app(argc, argv); Plotter plotter; plotter.setWindowTitle(QObject::tr("Jambi Plotter")); #if 0 readFlightCurves(&plotter, ":/in1.txt"); #else int numPoints = 100; QVector<QPointF> points0; QVector<QPointF> points1; for (int x = 0; x < numPoints; ++x) { points0.append(QPointF(x, uint(qrand()) % 100)); points1.append(QPointF(x, uint(qrand()) % 100)); } plotter.setCurveData(0, points0); plotter.setCurveData(1, points1); PlotSettings settings; settings.minX = 0.0; settings.maxX = 100.0; settings.minY = 0.0; settings.maxY = 100.0; plotter.setPlotSettings(settings); #endif plotter.show(); return app.exec(); }
plotter.cpp
:#include "plotter.h" #include <QtWidgets> #include <cmath> Plotter::Plotter(QWidget *parent) : QWidget(parent) { setBackgroundRole(QPalette::Dark); setAutoFillBackground(true); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); setFocusPolicy(Qt::StrongFocus); rubberBandIsShown = false; zoomInButton = new QToolButton(this); zoomInButton->setIcon(QIcon(":/images/zoomin.png")); zoomInButton->adjustSize(); connect(zoomInButton, SIGNAL(clicked()), this, SLOT(zoomIn())); zoomOutButton = new QToolButton(this); zoomOutButton->setIcon(QIcon(":/images/zoomout.png")); zoomOutButton->adjustSize(); connect(zoomInButton, SIGNAL(clicked()), this, SLOT(zoomOut())); setPlotSettings(PlotSettings()); } //******************************************** void Plotter::setPlotSettings(const PlotSettings& settings) { zoomStack.clear(); zoomStack.append(settings); curZoom = 0; zoomInButton->hide(); zoomOutButton->hide(); refreshPixmap(); } //*********************************** void Plotter::zoomOut() { if(curZoom > 0) { --curZoom; zoomOutButton->setEnabled(curZoom > 0); zoomInButton->setEnabled(true); zoomInButton->show(); refreshPixmap(); } } //**************************************** void Plotter::zoomIn() { if(curZoom < zoomStack.count() -1) { ++curZoom; zoomInButton->setEnabled(curZoom < zoomStack.count() -1); zoomOutButton->setEnabled(true); zoomOutButton->show(); refreshPixmap(); } } //********************************* void Plotter::setCurveData(int id, const QVector<QPointF>& data) { curveMap[id] = data; refreshPixmap(); } //************************************* void Plotter::clearCurve(int id) { curveMap.remove(id); refreshPixmap(); } //************************************ QSize Plotter::minimumSizeHint() const { return QSize(6 * Margin, 4 * Margin); } //************************************** QSize Plotter::sizeHint() const { return QSize(12 * Margin, 8 * Margin); } //*************************************** // Protected Functions' implementations //*************************************** void Plotter::paintEvent(QPaintEvent*) { QStylePainter painter(this); painter.drawPixmap(0, 0, pixmap); if (rubberBandIsShown) { painter.setPen(palette().light().color()); painter.drawRect(rubberBandRect.normalized() .adjusted(0, 0, -1, -1)); } if (hasFocus()) { QStyleOptionFocusRect option; option.initFrom(this); option.backgroundColor = palette().dark().color(); painter.drawPrimitive(QStyle::PE_FrameFocusRect, option); } } //******************************************* void Plotter::resizeEvent(QResizeEvent*) { int x = width() - (zoomInButton->width() + zoomOutButton->width() + 10); zoomInButton->move(x, 5); zoomOutButton->move(x + zoomInButton->width() + 5, 5); refreshPixmap(); } //******************************** void Plotter::mousePressEvent(QMouseEvent* event) { QRect rect(Margin, Margin, width() - 2 * Margin, height() - 2 * Margin); if (event->button() == Qt::LeftButton) { if (rect.contains(event->pos())) { rubberBandIsShown = true; rubberBandRect.setTopLeft(event->pos()); rubberBandRect.setBottomRight(event->pos()); updateRubberBandRegion(); setCursor(Qt::CrossCursor); } } } //******************************************** void Plotter::mouseMoveEvent(QMouseEvent * event) { if(rubberBandIsShown) { updateRubberBandRegion(); rubberBandRect.setBottomRight(event->pos()); updateRubberBandRegion(); } } //********************************************** void Plotter::mouseReleaseEvent(QMouseEvent * event) { if((event->button() == Qt::LeftButton) && rubberBandIsShown) { rubberBandIsShown = false; updateRubberBandRegion(); unsetCursor(); QRect rect = rubberBandRect.normalized(); if(rect.width() < 4 || rect.height() < 4) return; rect.translate(-Margin, -Margin); PlotSettings prevSettings = zoomStack[curZoom]; PlotSettings settings; double dx = prevSettings.spanX() / (width() - 2 * Margin); double dy = prevSettings.spanY() / (height() - 2 * Margin); settings.minX = prevSettings.minX + dx * rect.left(); settings.maxX = prevSettings.minX + dx * rect.right(); settings.minY = prevSettings.maxY + dy * rect.bottom(); settings.maxY = prevSettings.maxY + dy * rect.top(); settings.adjust(); zoomStack.resize(curZoom + 1); zoomStack.append(settings); zoomIn(); } } //************************************************* void Plotter::keyPressEvent(QKeyEvent* event) { switch (event->key()) { case Qt::Key_Plus: zoomIn(); break; case Qt::Key_Minus: zoomOut(); break; case Qt::Key_Left: zoomStack[curZoom].scroll(-1, 0); refreshPixmap(); break; case Qt::Key_Right: zoomStack[curZoom].scroll(+1, 0); refreshPixmap(); break; case Qt::Key_Down: zoomStack[curZoom].scroll(0, -1); refreshPixmap(); break; case Qt::Key_Up: zoomStack[curZoom].scroll(0, +1); refreshPixmap(); break; default: QWidget::keyPressEvent(event); } } //********************************************* void Plotter::wheelEvent(QWheelEvent* event) { int numDegrees = event->delta() / 8; int numTicks = numDegrees / 15; if(event->orientation() == Qt::Horizontal) zoomStack[curZoom].scroll(numTicks, 0); else zoomStack[curZoom].scroll(0, numTicks); refreshPixmap(); } //********************************************* // The private functions //********************************************** void Plotter::updateRubberBandRegion() { QRect rect = rubberBandRect.normalized(); update(rect.left(), rect.top(), rect.width(), 1); update(rect.left(), rect.top(), 1, rect.height()); update(rect.left(), rect.bottom(), rect.width(), 1); update(rect.right(), rect.top(), 1, rect.height()); } //*************************************************** void Plotter::refreshPixmap() { pixmap = QPixmap(size()); pixmap.fill(this, 0, 0); QPainter painter(&pixmap); painter.initFrom(this); drawGrid(&painter); drawCurves(&painter); update(); } //***************************************** void Plotter::drawGrid(QPainter *painter) { QRect rect(Margin, Margin, width() - 2 * Margin, height() - 2 * Margin); if(!rect.isValid()) return; PlotSettings settings = zoomStack[curZoom]; QPen quiteDark = palette().dark().color().light(); QPen light = palette().light().color(); for(int i=0; i<= settings.numXTicks; ++i) { int x = rect.left() + (i * (rect.width() - 1) / settings.numXTicks); double label = settings.minX + (i * settings.spanX() / settings.numXTicks); painter->setPen(quiteDark); painter->drawLine(x, rect.top(), x, rect.bottom()); painter->setPen(light); painter->drawLine(x, rect.bottom(), x, rect.bottom() + 5); painter->drawText(x - 50, rect.bottom() + 5, 100, 20, Qt::AlignHCenter | Qt::AlignTop, QString::number(label)); } for(int j=0; j<= settings.numYTicks; ++j) { int y = rect.bottom() - (j * (rect.height() - 1) / settings.numYTicks); double label = settings.minY + (j * settings.spanY() / settings.numYTicks); painter->setPen(quiteDark); painter->drawLine(rect.left(), y, rect.right(), y); painter->setPen(light); painter->drawLine(rect.left() - 5, y, rect.left(), y); painter->drawText(rect.left() - Margin, y -10, Margin - 5, 20, Qt::AlignRight | Qt::AlignVCenter, QString::number(label)); } painter->drawRect(rect.adjusted(0, 0, -1, -1)); } //********************************************************** void Plotter::drawCurves(QPainter *painter) { static const QColor colorForIds[6] = { Qt::red, Qt::green, Qt::blue, Qt::cyan, Qt::magenta, Qt::yellow }; PlotSettings settings = zoomStack[curZoom]; QRect rect(Margin, Margin, width() - 2 * Margin, height() - 2 * Margin); if(!rect.isValid()) return; painter->setClipRect(rect.adjusted(+1, +1, -1, -1)); QMapIterator<int, QVector<QPointF> > i(curveMap); while (i.hasNext()) { i.next(); int id = i.key(); QVector<QPointF> data = i.value(); QPolygonF Polyline(data.count()); for(int j=0; j<data.count(); ++j) { double dx = data[j].x() - settings.minX; double dy = data[j].y() - settings.minY; double x = rect.left() + (dx * (rect.width() - 1) / settings.spanX()); double y = rect.bottom() - (dy * (rect.height() -1) / settings.spanY()); Polyline[j] = QPointF(x, y); } painter->setPen(colorForIds[uint(id) % 6]); painter->drawPolyline(Polyline); } } //********************************************************** PlotSettings::PlotSettings() { minX = 0.0; maxX = 10.0; numXTicks = 5; minY = 0.0; maxY = 10.0; numYTicks = 5; } //******************************************* void PlotSettings::scroll(int dx, int dy) { double stepX = spanX() / numXTicks; minX += dx * stepX; maxX += dx * stepX; double stepY = spanY() / numYTicks; minY += dy * stepY; maxY += dy * stepY; } //*********************************************** void PlotSettings::adjust() { adjustAxis(minX, maxX, numXTicks); adjustAxis(minY, maxY, numYTicks); } //************************** void PlotSettings::adjustAxis(double &min, double &max, int &numTicks) { const int MinTicks = 4; double grossStep = (max - min) / MinTicks; double step = std::pow(10.0, std::floor(std::log10(grossStep))); if (5 * step < grossStep) step *= 5; else if (2 * step < grossStep) step *= 2; numTicks = int (std::ceil(max / step) - std::floor(min / step)); if(numTicks < MinTicks) numTicks = MinTicks; min = std::floor(min / step) * step; max = std::ceil(max / step) * step; } //****************************************************** Plotter::~Plotter() { }
-
Did you try to debug step by step to see when/where these warnings occur?
Do you mean to set a breakpoint in each function and run the code by F5?
Also you can start with all code commented out and then activate one part after the other and see when you get this warning.
But that way the program might not successfully run and show compile errors!
-
@tomy said in A Double Buffering example:
Do you mean to set a breakpoint in each function and run the code by F5?
No. You start debugging by pressing F10 ('Start "NameOfProgram" and break at function "main()"'). Then you can walk through your code step by step by pressing F10 again and again.
-
@Wieland
Thanks.
I did it inmain.cpp
. That is, I put a breakpoint in the first statement of that function (as shown in picture below) and pulled up the Application Output window.
At first the message showed when the execution was on line:plotter.setWindowTitle(QObject::tr("Jambi Plotter"));
I commented it out and started again. This time when it passed through:
#if 0 readFlightCurves(&plotter, ":/in1.txt"); #else
the message once again was shown.
I'm pretty sure that this is the source of the problem. What is that at all?? -
@tomy said in A Double Buffering example:
What is that at all?
The example you copy & pasted from the internet was made in ancient Qt 4 times. With Qt 5 the API changed, some functions are marked as deprecated, which means one shouldn't use them in new code. E.g. the example uses a deprecated overload of
QPixmap::fill
. -
@Wieland
Dear, I don't copy code from the Internet and paste them somewhere else; I try to hand-code and "get help from the Internet".
If I wanted to copy code existing on many webpages, including this one, there wouldn't be any need to try to solve their problems, because they are complete and almost flawless.I'm learning Qt using a book and I don't have an instructor sitting next to me guiding me on each and every issue. The work I do is by no way easy but really hard.
Considering this example as an instance, I do not need to create a new one; I need to figure it out, because it's previously written and no need for writing it once again.
There is much to say about my situation, but let's forget these.Anyway, I couldn't find the expression you typed in the code!
Second, I found something else disclosing the reason of that message: it's :setPlotSettings(PlotSettings());
It's clearly not allowed in C++ and one other method, or a lambda expression is needed to fix that. I will work on this idea a little bite later. -
Copying other peoples' code to learn from it is a valid learning strategy, no need to be teed off. The
deprecatedobsolete function I referred to is here:void Plotter::refreshPixmap() { pixmap = QPixmap(size()); pixmap.fill(this, 0, 0); // <--- here QPainter painter(&pixmap); painter.initFrom(this); drawGrid(&painter); drawCurves(&painter); update(); }
And if you take a look at its implementation, you'll see that it prints the message you see when you run your program, from qtbase/src/gui/image/qpixmap.cpp, line 865 ff:
void QPixmap::fill(const QPaintDevice *device, const QPoint &p) { Q_UNUSED(device) Q_UNUSED(p) qWarning("this function is deprecated, ignored"); }
-
@Wieland
When I tested the code by F10 and checkpoints, I got that message in the main() inPlotter plotter;
, so I put another checkpoint in the Plotter's constructor to get into it. The executor passed all expressions:setBackgroundRole(QPalette::Dark); setAutoFillBackground(true); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); setFocusPolicy(Qt::StrongFocus); rubberBandIsShown = false; zoomInButton = new QToolButton(this); zoomInButton->setIcon(QIcon(":/images/zoomin.png")); zoomInButton->adjustSize(); connect(zoomInButton, SIGNAL(clicked()), this, SLOT(zoomIn())); zoomOutButton = new QToolButton(this); zoomOutButton->setIcon(QIcon(":/images/zoomout.png")); zoomOutButton->adjustSize(); connect(zoomOutButton, SIGNAL(clicked()), this, SLOT(zoomOut())); setPlotSettings(PlotSettings());
except the last one so I thought it is the source of the issue. Anyway, you used a method which led you to the website which has written that message too that seems to be correct. What was that method that resulted in a different output from mine? I used checkpoints and F10.
I'm reading the whole code and its explanation in the book to figure the program out completely. After that I'll ask for a remedy no to have that message for the program.