Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to draw something with QPainter when the button is pushed



  • I am working on my project from programming and I need to draw, for example, a circle every time the pushButton is pressed using QPainter. This is the first problem, and the second one here is that I need some information to be sent to the drawing function too, for example, int vector, and being able to draw so many circles, as there are elements in the vector with radii of the elements itself. I have found some code based on signals and slots.
    The sender:

    public:
        Listener(QObject *p = 0) : QObject(p) {
            QTimer * t = new QTimer(this);
            t->setInterval(200);
            connect(t, SIGNAL(timeout()), this, SLOT(sendData()));
            t->start();
        }
    signals:
        void dataAvaiable(int, int);
    
    public slots:
        void sendData() {
            emit dataAvaiable(qrand() % 200, qrand() % 200);
        }
    

    The reciever:

        void receiveData(int x, int y) {
            QPainter painter(this);
            QPen pen(Qt::white, 5);
            painter.setRenderHint(QPainter::HighQualityAntialiasing);
            painter.setPen(pen);
            QPoint point(x, y);
            painter.drawEllipse(x, y, 100, 100);
            data.append(point);
        }
    

    The connection itself in main.cpp

    QObject::connect(&l, SIGNAL(dataAvaiable(int,int)), &w, SLOT(receiveData(int,int)));
    

    But the code doesn't suit for my exact task with buttons and doesn't even want to draw anythig, just any circle at all. Howewer, in debugger the code executes properly, and I am relatively new to Qt and C++ so I can't figure out by myself, where the problem is and how to solve my task.
    Can someone please do a minimal of code or simply explain to me, where exactly the problem is? Need to solve the problem as soon as possible. Thank you.



  • From the QPainter class description:

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

    You can force calling paintEvent() by invoking update(), so you must connect the onclicked() signal of your button to the update() slot of the widget you're drawing on.

    For your second problem, the data can be a member variable.
    Here's an example:

    // mywidget.h
    #include <QVector>
    #include <QPoint>
    // other includes and the constructor...
    protected:
        virtual void paintEvent(QPaintEvent *event);
    
    private slots:
        void onButtonClicked();
    
    private:
        QPushButton* mButton;
        QVector<QPoint> mCirclesData;
    
    // mywidget.cpp
    
    MyWidget::MyWidget(QWidget *parent) : QWidget(parent)
    {
        mButton = new QPushButton(this);
       // customise your button...
        connect(mButton, &QPushButton::clicked, this, &MyWidget::onButtonClicked); 
    }
    
    //...
    void MyWidget::onButtonClicked(){
        int x = qrand() % 200, y = x;
        mCirclesData << QPoint(x,y); 
        update(); // force calling paintEvent
    }
    
    void MyWidget::paintEvent(QPaintEvent *event)
    {
         QPainter painter(this);
         QPen pen(Qt::white, 5);
         painter.setRenderHint(QPainter::HighQualityAntialiasing);
         painter.setPen(pen);     
         painter.drawEllipse(mCirclesData.last().x(), mCirclesData.last().y(), 100, 100);
    }
    

    As you can see the "data" is added to the array before being used to draw the circles...Anyway, I hope you got the idea.



  • @SamurayH The solution is perfect to me. Thank you very much!