Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Draw in QPainter
Forum Updated to NodeBB v4.3 + New Features

Draw in QPainter

Scheduled Pinned Locked Moved Solved General and Desktop
14 Posts 4 Posters 1.1k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • ODБOïO Offline
    ODБOïO Offline
    ODБOï
    wrote on last edited by ODБOï
    #1

    hi,
    im trying to periodically generate random lines and append them to each other to create a path. i use QPainter

    i'm calling my custom method in the paintEvent

    but all i get is

    QPainter::setPen: Painter not active
    how should i activate it ?

    is there a more suited qt class for what i'm doing

    thanks

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include <QPainter>
    #include <QTimer>
    #include <QDebug>
    
    QT_BEGIN_NAMESPACE
    namespace Ui { class MainWindow; }
    QT_END_NAMESPACE
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    protected:
        void paintEvent(QPaintEvent *event)
        {
            Q_UNUSED(event)
    
            drawLineW(qrand()*100, qrand()*100,(qrand()%10 > 5)?true:false);
    
        }
    
        void drawLineW(int x, int y, bool down){
            qDebug()<<down;
    
            if(down){
                painter->setPen(QPen(Qt::blue, 8, Qt::DashDotLine, Qt::RoundCap));
            }else{
                painter->setPen(QPen(Qt::red, 2, Qt::DashDotLine, Qt::RoundCap));
            }
    
            painter->drawLine(lastX,lastY,x,y);
    
            lastX = x;
            lastY = y;
        }
    
    private:
        int lastX=0;
        int lastY=0;
        QPainter* painter;
        QTimer * drawTimer;
        Ui::MainWindow *ui;
    };
    #endif // MAINWINDOW_H
    
    //________________________________________
    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        drawTimer = new QTimer(this);
       
        painter = new QPainter(this);
        
        drawTimer->setInterval(100);
    
        QObject::connect(drawTimer,&QTimer::timeout,[=](){
            update();
        });
    
        drawTimer->start();
    
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    
    
    1 Reply Last reply
    0
    • ODБOïO Offline
      ODБOïO Offline
      ODБOï
      wrote on last edited by ODБOï
      #14

      This was 1000 times easier using Graphics View...

      class MainWindow : public QMainWindow
      {
          Q_OBJECT
      
      public:
          MainWindow(QWidget *parent = nullptr);
          ~MainWindow();
      private:
          int oldX=0;
          int oldY=0;
          Ui::MainWindow *ui;
          QGraphicsScene *scene;
          QTimer *drawTimer;
          QGraphicsLineItem *vect;
      
          QVector <QPoint> path;
      
          int nLine = 0;
      
          void createPath(){
              for(int i=1;i<20;i++){
                    path.append(QPoint(i*10,(i%2)*10));
              }
          }
      };
      //___ cpp
      MainWindow::MainWindow(QWidget *parent)
          : QMainWindow(parent)
          , ui(new Ui::MainWindow)
      {
          ui->setupUi(this);
          scene = new QGraphicsScene(this);
          ui->graphicsView->setScene(scene);
      
          drawTimer = new QTimer(this);
          drawTimer->setInterval(50);
      
          createPath();
      
          QObject::connect(drawTimer,&QTimer::timeout,[=](){
              if(nLine>=path.length()){
      
                  drawTimer->stop();
                  return;
              }
      
              int newX = path.at(nLine).x();
              int newY = path.at(nLine).y();
      
              vect = scene->addLine(oldX,oldY,newX,newY);
      
              oldX= newX;
              oldY= newY;
      
              nLine++;
      
          });
          drawTimer->start();
      }
      
      1 Reply Last reply
      2
      • sierdzioS Offline
        sierdzioS Offline
        sierdzio
        Moderators
        wrote on last edited by
        #2

        You need to create the painter in the paint event, I think, just like in the docs: https://doc.qt.io/qt-5/qpainter.html

        (Z(:^

        ODБOïO 1 Reply Last reply
        0
        • sierdzioS sierdzio

          You need to create the painter in the paint event, I think, just like in the docs: https://doc.qt.io/qt-5/qpainter.html

          ODБOïO Offline
          ODБOïO Offline
          ODБOï
          wrote on last edited by ODБOï
          #3

          hi @sierdzio
          that is the first test thing i did, yes.

          but if i create one QPainter on the stack it is deleted every time

          i want to keep the old path picture and add new line to it

          J.HilkJ sierdzioS 2 Replies Last reply
          0
          • ODБOïO ODБOï

            hi @sierdzio
            that is the first test thing i did, yes.

            but if i create one QPainter on the stack it is deleted every time

            i want to keep the old path picture and add new line to it

            J.HilkJ Online
            J.HilkJ Online
            J.Hilk
            Moderators
            wrote on last edited by
            #4

            @LeLev Why don't you then simply append the new lines to a member QVector and simply call drawLines(vector) inside the paint event?


            Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


            Q: What's that?
            A: It's blue light.
            Q: What does it do?
            A: It turns blue.

            1 Reply Last reply
            1
            • ODБOïO ODБOï

              hi @sierdzio
              that is the first test thing i did, yes.

              but if i create one QPainter on the stack it is deleted every time

              i want to keep the old path picture and add new line to it

              sierdzioS Offline
              sierdzioS Offline
              sierdzio
              Moderators
              wrote on last edited by
              #5

              @LeLev said in Draw in QPainter:

              hi @sierdzio
              that is the first test thing i did, yes.

              but if i create one QPainter on the stack it is deleted every time

              i want to keep the old path picture and add new line to it

              Then at the end of paint event, save the painter to a picture (QPixmap). Then in next paint event, first paint the pixmap, then add your new line to it (and save another pixmap).

              (Z(:^

              1 Reply Last reply
              1
              • sierdzioS Offline
                sierdzioS Offline
                sierdzio
                Moderators
                wrote on last edited by
                #6

                Perhaps you can work around this by using member pointer like you do, but then calling QPainter::begin() in the beginning of your event handler. I'm not sure if it will work, though.

                (Z(:^

                ODБOïO 1 Reply Last reply
                1
                • sierdzioS sierdzio

                  Perhaps you can work around this by using member pointer like you do, but then calling QPainter::begin() in the beginning of your event handler. I'm not sure if it will work, though.

                  ODБOïO Offline
                  ODБOïO Offline
                  ODБOï
                  wrote on last edited by ODБOï
                  #7

                  @J-Hilk i will try,
                  but that means every time you add a new line, you re-draw all the lines in the vector (from the beginning) ?

                  @sierdzio
                  like this, the first line is drawn and then a crash.

                    void paintEvent(QPaintEvent *event)
                      {
                          Q_UNUSED(event)
                          if(!painter->isActive()){
                           painter->begin(this);
                          }
                          drawLineW(qrand()*100, qrand()*100,(qrand()%10 > 5)?true:false);
                      }
                  

                  is there an other type that will not clear the screen, and i can simply add lines ? im not forced to use QPainter

                  jsulmJ 1 Reply Last reply
                  0
                  • ODБOïO ODБOï

                    @J-Hilk i will try,
                    but that means every time you add a new line, you re-draw all the lines in the vector (from the beginning) ?

                    @sierdzio
                    like this, the first line is drawn and then a crash.

                      void paintEvent(QPaintEvent *event)
                        {
                            Q_UNUSED(event)
                            if(!painter->isActive()){
                             painter->begin(this);
                            }
                            drawLineW(qrand()*100, qrand()*100,(qrand()%10 > 5)?true:false);
                        }
                    

                    is there an other type that will not clear the screen, and i can simply add lines ? im not forced to use QPainter

                    jsulmJ Offline
                    jsulmJ Offline
                    jsulm
                    Lifetime Qt Champion
                    wrote on last edited by
                    #8

                    @LeLev said in Draw in QPainter:

                    you re-draw all the lines in the vector (from the beginning) ?

                    You can draw in a QImage when you add a line and draw the image in paintEvent

                    https://forum.qt.io/topic/113070/qt-code-of-conduct

                    ODБOïO 1 Reply Last reply
                    2
                    • jsulmJ jsulm

                      @LeLev said in Draw in QPainter:

                      you re-draw all the lines in the vector (from the beginning) ?

                      You can draw in a QImage when you add a line and draw the image in paintEvent

                      ODБOïO Offline
                      ODБOïO Offline
                      ODБOï
                      wrote on last edited by ODБOï
                      #9

                      hi
                      @jsulm said in Draw in QPainter:

                      You can draw in a QImage

                      sorry i can't find methods to draw in a QImage nor in QPaintDevice

                      i have to pass the image to my QPainter so i can draw right ?

                      #ifndef MAINWINDOW_H
                      #define MAINWINDOW_H
                      
                      #include <QMainWindow>
                      #include <QPainter>
                      #include <QTimer>
                      #include <QVector>
                      #include <QDebug>
                      
                      QT_BEGIN_NAMESPACE
                      namespace Ui { class MainWindow; }
                      QT_END_NAMESPACE
                      
                      class MainWindow : public QMainWindow
                      {
                          Q_OBJECT
                      
                      public:
                          MainWindow(QWidget *parent = nullptr);
                          ~MainWindow();
                      protected:
                          void paintEvent(QPaintEvent *event)
                          {
                              Q_UNUSED(event)
                              if(!painter->isActive()){
                               painter->begin(this);
                              }
                      
                              drawLineW(qrand()*100, qrand()*100,(qrand()%10 > 5)?true:false);
                          }
                      
                          void drawLineW(int x, int y, bool down){
                             
                              painter->drawLine(lastX,lastY,x,y);
                              lastX = x;
                              lastY = y;
                          }
                      
                      private:
                          int lastX=0;
                          int lastY=0;
                          //QVector <QPoint> lines; 
                          QImage pathImg;
                      
                          QPainter* painter;
                          QTimer * drawTimer;
                          Ui::MainWindow *ui;
                      };
                      #endif // MAINWINDOW_H
                      
                      //__________________________________
                      MainWindow::MainWindow(QWidget *parent)
                          : QMainWindow(parent)
                          , ui(new Ui::MainWindow)
                      {
                          ui->setupUi(this);
                      
                          drawTimer = new QTimer(this);
                      
                          painter = new QPainter(&pathImg);
                      
                          drawTimer->setInterval(100);
                      
                          QObject::connect(drawTimer,&QTimer::timeout,[=](){
                      
                              update();
                          });
                      
                          drawTimer->start();
                      
                      }
                      
                      

                      sorry im struggling so hard now, i can't get this done fo 3 houres.. I m not used to QWidgets at all.
                      i did the same thing in qml/js in about 10minutes

                      sierdzioS jsulmJ 2 Replies Last reply
                      0
                      • ODБOïO ODБOï

                        hi
                        @jsulm said in Draw in QPainter:

                        You can draw in a QImage

                        sorry i can't find methods to draw in a QImage nor in QPaintDevice

                        i have to pass the image to my QPainter so i can draw right ?

                        #ifndef MAINWINDOW_H
                        #define MAINWINDOW_H
                        
                        #include <QMainWindow>
                        #include <QPainter>
                        #include <QTimer>
                        #include <QVector>
                        #include <QDebug>
                        
                        QT_BEGIN_NAMESPACE
                        namespace Ui { class MainWindow; }
                        QT_END_NAMESPACE
                        
                        class MainWindow : public QMainWindow
                        {
                            Q_OBJECT
                        
                        public:
                            MainWindow(QWidget *parent = nullptr);
                            ~MainWindow();
                        protected:
                            void paintEvent(QPaintEvent *event)
                            {
                                Q_UNUSED(event)
                                if(!painter->isActive()){
                                 painter->begin(this);
                                }
                        
                                drawLineW(qrand()*100, qrand()*100,(qrand()%10 > 5)?true:false);
                            }
                        
                            void drawLineW(int x, int y, bool down){
                               
                                painter->drawLine(lastX,lastY,x,y);
                                lastX = x;
                                lastY = y;
                            }
                        
                        private:
                            int lastX=0;
                            int lastY=0;
                            //QVector <QPoint> lines; 
                            QImage pathImg;
                        
                            QPainter* painter;
                            QTimer * drawTimer;
                            Ui::MainWindow *ui;
                        };
                        #endif // MAINWINDOW_H
                        
                        //__________________________________
                        MainWindow::MainWindow(QWidget *parent)
                            : QMainWindow(parent)
                            , ui(new Ui::MainWindow)
                        {
                            ui->setupUi(this);
                        
                            drawTimer = new QTimer(this);
                        
                            painter = new QPainter(&pathImg);
                        
                            drawTimer->setInterval(100);
                        
                            QObject::connect(drawTimer,&QTimer::timeout,[=](){
                        
                                update();
                            });
                        
                            drawTimer->start();
                        
                        }
                        
                        

                        sorry im struggling so hard now, i can't get this done fo 3 houres.. I m not used to QWidgets at all.
                        i did the same thing in qml/js in about 10minutes

                        sierdzioS Offline
                        sierdzioS Offline
                        sierdzio
                        Moderators
                        wrote on last edited by
                        #10

                        @LeLev said in Draw in QPainter:

                        i have to pass the image to my QPainter so i can draw right ?

                        You can use setBackground() or drawPixmap() first, then proceed with your drawLine() call.

                        (Z(:^

                        ODБOïO 1 Reply Last reply
                        0
                        • ODБOïO ODБOï

                          hi
                          @jsulm said in Draw in QPainter:

                          You can draw in a QImage

                          sorry i can't find methods to draw in a QImage nor in QPaintDevice

                          i have to pass the image to my QPainter so i can draw right ?

                          #ifndef MAINWINDOW_H
                          #define MAINWINDOW_H
                          
                          #include <QMainWindow>
                          #include <QPainter>
                          #include <QTimer>
                          #include <QVector>
                          #include <QDebug>
                          
                          QT_BEGIN_NAMESPACE
                          namespace Ui { class MainWindow; }
                          QT_END_NAMESPACE
                          
                          class MainWindow : public QMainWindow
                          {
                              Q_OBJECT
                          
                          public:
                              MainWindow(QWidget *parent = nullptr);
                              ~MainWindow();
                          protected:
                              void paintEvent(QPaintEvent *event)
                              {
                                  Q_UNUSED(event)
                                  if(!painter->isActive()){
                                   painter->begin(this);
                                  }
                          
                                  drawLineW(qrand()*100, qrand()*100,(qrand()%10 > 5)?true:false);
                              }
                          
                              void drawLineW(int x, int y, bool down){
                                 
                                  painter->drawLine(lastX,lastY,x,y);
                                  lastX = x;
                                  lastY = y;
                              }
                          
                          private:
                              int lastX=0;
                              int lastY=0;
                              //QVector <QPoint> lines; 
                              QImage pathImg;
                          
                              QPainter* painter;
                              QTimer * drawTimer;
                              Ui::MainWindow *ui;
                          };
                          #endif // MAINWINDOW_H
                          
                          //__________________________________
                          MainWindow::MainWindow(QWidget *parent)
                              : QMainWindow(parent)
                              , ui(new Ui::MainWindow)
                          {
                              ui->setupUi(this);
                          
                              drawTimer = new QTimer(this);
                          
                              painter = new QPainter(&pathImg);
                          
                              drawTimer->setInterval(100);
                          
                              QObject::connect(drawTimer,&QTimer::timeout,[=](){
                          
                                  update();
                              });
                          
                              drawTimer->start();
                          
                          }
                          
                          

                          sorry im struggling so hard now, i can't get this done fo 3 houres.. I m not used to QWidgets at all.
                          i did the same thing in qml/js in about 10minutes

                          jsulmJ Offline
                          jsulmJ Offline
                          jsulm
                          Lifetime Qt Champion
                          wrote on last edited by
                          #11

                          @LeLev said in Draw in QPainter:

                          sorry i can't find methods to draw in a QImage

                          Sorry, it's drawPixmap.

                          "i have to pass the image to my QPainter so i can draw right ?" - no, use one of the drawPixmap() methods..

                          https://forum.qt.io/topic/113070/qt-code-of-conduct

                          1 Reply Last reply
                          1
                          • sierdzioS sierdzio

                            @LeLev said in Draw in QPainter:

                            i have to pass the image to my QPainter so i can draw right ?

                            You can use setBackground() or drawPixmap() first, then proceed with your drawLine() call.

                            ODБOïO Offline
                            ODБOïO Offline
                            ODБOï
                            wrote on last edited by
                            #12

                            @sierdzio

                            i call begin() as you suggested
                            and i also have to call end() at the end of my method.

                            now i can see my randomly generated lines, but every time i add a line the rest of lines are deleted/cleaned.

                            @sierdzio said in Draw in QPainter:

                            Then at the end of paint event, save the painter to a picture (QPixmap). Then in next paint event, first paint the pixmap

                            now i'm trying to do this.
                            There is a QPainter::drawPixmap to draw the saved image, but i can't find how to save the QPainter content to a QPixmap first, can you please give me a hint ?

                            1 Reply Last reply
                            0
                            • ODБOïO Offline
                              ODБOïO Offline
                              ODБOï
                              wrote on last edited by ODБOï
                              #13

                              almost working, just need to fix the save and reload feature

                              
                              class MainWindow : public QMainWindow
                              {
                                  Q_OBJECT
                              
                              public:
                                  MainWindow(QWidget *parent = nullptr);
                                  ~MainWindow();
                              protected:
                                  void paintEvent(QPaintEvent *event)
                                  {
                              
                                      Q_UNUSED(event)
                                      if(!painter->isActive()){
                                          painter->begin(this);
                                      }
                              
                                      drawLineW(qrand()%250, qrand()%250,(qrand()%10 > 5)?true:false);
                                  }
                              
                                  void drawLineW(int x, int y, bool down){
                              
                                      // load last path/picture
                                      painter->drawPixmap(0,0,this->height(),this->width(),oldPath);
                              
                                      if(down){
                                          painter->setPen(QPen(Qt::blue, 3, Qt::DashDotLine, Qt::RoundCap));
                                      }else{
                                          painter->setPen(QPen(Qt::red, 3, Qt::DashDotLine, Qt::RoundCap));
                                      }
                              
                                      painter->drawLine(lastX,lastY,x,y);
                                      painter->end();
                              
                                      lastX = x;
                                      lastY = y;
                              
                                      // save current path/picture
                                      oldPath = QPixmap::fromImage(oldPathImg);
                              
                                  }
                              
                              private:
                                  int lastX=0;
                                  int lastY=0;
                              
                                  QImage oldPathImg;
                              
                                  QPixmap oldPath;
                              
                                  QPainter* painter;
                                  QTimer * drawTimer;
                                  Ui::MainWindow *ui;
                              };
                              #endif // MAINWINDOW_H
                              
                              
                              // ___
                              
                              MainWindow::MainWindow(QWidget *parent)
                                  : QMainWindow(parent)
                                  , ui(new Ui::MainWindow)
                              {
                                  ui->setupUi(this);
                              
                                  drawTimer = new QTimer(this);
                              
                                  painter = new QPainter(&oldPathImg);
                              
                                  drawTimer->setInterval(1000);
                              
                                  QObject::connect(drawTimer,&QTimer::timeout,[=](){
                                      update();
                                  });
                              
                                  drawTimer->start();
                              }
                              
                              
                              
                              1 Reply Last reply
                              0
                              • ODБOïO Offline
                                ODБOïO Offline
                                ODБOï
                                wrote on last edited by ODБOï
                                #14

                                This was 1000 times easier using Graphics View...

                                class MainWindow : public QMainWindow
                                {
                                    Q_OBJECT
                                
                                public:
                                    MainWindow(QWidget *parent = nullptr);
                                    ~MainWindow();
                                private:
                                    int oldX=0;
                                    int oldY=0;
                                    Ui::MainWindow *ui;
                                    QGraphicsScene *scene;
                                    QTimer *drawTimer;
                                    QGraphicsLineItem *vect;
                                
                                    QVector <QPoint> path;
                                
                                    int nLine = 0;
                                
                                    void createPath(){
                                        for(int i=1;i<20;i++){
                                              path.append(QPoint(i*10,(i%2)*10));
                                        }
                                    }
                                };
                                //___ cpp
                                MainWindow::MainWindow(QWidget *parent)
                                    : QMainWindow(parent)
                                    , ui(new Ui::MainWindow)
                                {
                                    ui->setupUi(this);
                                    scene = new QGraphicsScene(this);
                                    ui->graphicsView->setScene(scene);
                                
                                    drawTimer = new QTimer(this);
                                    drawTimer->setInterval(50);
                                
                                    createPath();
                                
                                    QObject::connect(drawTimer,&QTimer::timeout,[=](){
                                        if(nLine>=path.length()){
                                
                                            drawTimer->stop();
                                            return;
                                        }
                                
                                        int newX = path.at(nLine).x();
                                        int newY = path.at(nLine).y();
                                
                                        vect = scene->addLine(oldX,oldY,newX,newY);
                                
                                        oldX= newX;
                                        oldY= newY;
                                
                                        nLine++;
                                
                                    });
                                    drawTimer->start();
                                }
                                
                                1 Reply Last reply
                                2

                                • Login

                                • Login or register to search.
                                • First post
                                  Last post
                                0
                                • Categories
                                • Recent
                                • Tags
                                • Popular
                                • Users
                                • Groups
                                • Search
                                • Get Qt Extensions
                                • Unsolved