A Double Buffering example



  • Hi all,

    I wrote this Double Buffering and tried to run it, but I got this output:

    0_1512824437910_Capture.PNG

    At the bottom it also has been written:
    this function deprecated, ignored

    What 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() { }
    
    
    

  • Moderators

    @tomy Did you try to debug step by step to see when/where these warnings occur?
    Also you can start with all code commented out and then activate one part after the other and see when you get this warning.



  • @jsulm

    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 in main.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??

    0_1513240002608_Capture.PNG



  • @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 deprecated obsolete 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() in Plotter 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.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.