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. Should I use QDialog widget to draw line?
QtWS25 Last Chance

Should I use QDialog widget to draw line?

Scheduled Pinned Locked Moved Solved General and Desktop
draw line
24 Posts 4 Posters 2.7k Views
  • 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.
  • L Offline
    L Offline
    lansing
    wrote on 12 Aug 2020, 19:26 last edited by
    #1

    I have a QDialog with a sole purpose to draw lines and display image. In the dialog ui, I have added a QGraphicsView, and then in the code, I gave it a QGraphicsScene and created a QGraphicsLineItem ready to draw.

    The problem is what widget do I initiate the draw? I need the mousePressEvent(), mouseMoveEvent() and mouseReleaseEvent() in order to start drawing.

    I tried the mouseEvent with QDialog, but it doesn't have any event function. I couldn't even get the current mouse position from its event.

    void DrawingDialog::mousePressEvent(QMouseEvent *a_pEvent)
    {
        a_pEvent->  // autocompleter didn't show anything
    }
    
    J 1 Reply Last reply 12 Aug 2020, 19:29
    0
    • L lansing
      12 Aug 2020, 19:26

      I have a QDialog with a sole purpose to draw lines and display image. In the dialog ui, I have added a QGraphicsView, and then in the code, I gave it a QGraphicsScene and created a QGraphicsLineItem ready to draw.

      The problem is what widget do I initiate the draw? I need the mousePressEvent(), mouseMoveEvent() and mouseReleaseEvent() in order to start drawing.

      I tried the mouseEvent with QDialog, but it doesn't have any event function. I couldn't even get the current mouse position from its event.

      void DrawingDialog::mousePressEvent(QMouseEvent *a_pEvent)
      {
          a_pEvent->  // autocompleter didn't show anything
      }
      
      J Offline
      J Offline
      JonB
      wrote on 12 Aug 2020, 19:29 last edited by
      #2

      @lansing
      You want to deal with mouse events on the QGraphicsView. So there you have QGraphicsView::mouseMoveEvent etc.

      There is perhaps some Qt example of a "scribble/draw" app among its samples.

      L 1 Reply Last reply 12 Aug 2020, 19:33
      0
      • J JonB
        12 Aug 2020, 19:29

        @lansing
        You want to deal with mouse events on the QGraphicsView. So there you have QGraphicsView::mouseMoveEvent etc.

        There is perhaps some Qt example of a "scribble/draw" app among its samples.

        L Offline
        L Offline
        lansing
        wrote on 12 Aug 2020, 19:33 last edited by
        #3

        @JonB

        So I will have to extends the QGraphicsView class and add that extended class to the dialog?

        J 1 Reply Last reply 12 Aug 2020, 19:36
        0
        • L lansing
          12 Aug 2020, 19:33

          @JonB

          So I will have to extends the QGraphicsView class and add that extended class to the dialog?

          J Offline
          J Offline
          JonB
          wrote on 12 Aug 2020, 19:36 last edited by
          #4

          @lansing
          As I understand it, all you are wanting to do is draw some lines on a GraphicsScence/View, which happens to be on a dialog. It is the graphics view which is the "window" onto your drawing area.

          1 Reply Last reply
          0
          • L Offline
            L Offline
            lansing
            wrote on 13 Aug 2020, 23:33 last edited by lansing
            #5

            I have been following the scribbling example to draw the image and line in a QGraphicsScene. But I don't know why my QPainter doesn't work in paintEvent();

            header

            class Canvas : public QGraphicsScene
            {
            ...
            protected:
                void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
                void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
                void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
                void drawForeground(QPainter *painter, const QRectF &rect) override;
            
                void paintEvent(QPaintEvent * event);
            }
            

            source

            void Canvas::paintEvent(QPaintEvent *event)
            {
                QPainter painter(this);
                QRect dirtyRect = event->rect();
                painter.drawImage(dirtyRect, image, dirtyRect);
            }
            

            I got the error

            canvas.cpp:69:14: error: no matching constructor for initialization of 'QPainter' qpainter.h:127:14: note: candidate constructor not viable: no known conversion from 'Canvas *' to 'QPaintDevice *' for 1st argument

            1 Reply Last reply
            0
            • B Offline
              B Offline
              Bonnie
              wrote on 13 Aug 2020, 23:48 last edited by Bonnie
              #6

              Just as the error told you: QGraphicsScene is not a QPaintDevice, you cannot use QPainter like that.
              There's even not a paintEvent in QGraphicsScene, only QGraphicsView have that.
              The example draws on a non-graphics QWidget, but you are not.
              If you want to draw like this, then don't use QGraphicsView / QGraphicsScene, just inherit a QWidget.

              L 1 Reply Last reply 14 Aug 2020, 00:10
              0
              • B Bonnie
                13 Aug 2020, 23:48

                Just as the error told you: QGraphicsScene is not a QPaintDevice, you cannot use QPainter like that.
                There's even not a paintEvent in QGraphicsScene, only QGraphicsView have that.
                The example draws on a non-graphics QWidget, but you are not.
                If you want to draw like this, then don't use QGraphicsView / QGraphicsScene, just inherit a QWidget.

                L Offline
                L Offline
                lansing
                wrote on 14 Aug 2020, 00:10 last edited by
                #7

                @Bonnie

                Sorry I got mixed up with the suggestion here to always use QGraphicsScene to draw. I will use QGraphicsView to see how it goes.

                B 1 Reply Last reply 14 Aug 2020, 00:17
                0
                • L lansing
                  14 Aug 2020, 00:10

                  @Bonnie

                  Sorry I got mixed up with the suggestion here to always use QGraphicsScene to draw. I will use QGraphicsView to see how it goes.

                  B Offline
                  B Offline
                  Bonnie
                  wrote on 14 Aug 2020, 00:17 last edited by Bonnie
                  #8

                  @lansing
                  Just pick from those two methods (QGraphicsScene + QGraphicsView / QWidget + QPainter), they are totally different.
                  You shouldn't "paint" by yourself if you use QGraphicsScene + QGraphicsView.
                  Use QGraphicsScene::addLine to add the line, the painting part will be finished by themselves.

                  L 1 Reply Last reply 14 Aug 2020, 00:22
                  1
                  • B Bonnie
                    14 Aug 2020, 00:17

                    @lansing
                    Just pick from those two methods (QGraphicsScene + QGraphicsView / QWidget + QPainter), they are totally different.
                    You shouldn't "paint" by yourself if you use QGraphicsScene + QGraphicsView.
                    Use QGraphicsScene::addLine to add the line, the painting part will be finished by themselves.

                    L Offline
                    L Offline
                    lansing
                    wrote on 14 Aug 2020, 00:22 last edited by
                    #9

                    @Bonnie

                    Oh, I am looking to draw like in photoshop. So I should be using QWidget + QPainter?

                    B 1 Reply Last reply 14 Aug 2020, 02:15
                    0
                    • L lansing
                      14 Aug 2020, 00:22

                      @Bonnie

                      Oh, I am looking to draw like in photoshop. So I should be using QWidget + QPainter?

                      B Offline
                      B Offline
                      Bonnie
                      wrote on 14 Aug 2020, 02:15 last edited by Bonnie
                      #10

                      @lansing
                      Depending on how complicated it will be.
                      If you only want to draw like "press, drag, release, done", then you may use QWidget + QPainter.
                      But you need to save the lines you draw as member variables (the Scribble example save them to a QImage).
                      If you want move or do other transform operations to the drawn lines, you need to use QGraphicsScene + QGraphicsView.
                      You may also look at this example: Diagram Scene Example
                      It have some line drawing thing in a QGraphicsScene (but in this example the line will be deleted when releasing the mouse)

                      1 Reply Last reply
                      0
                      • L Offline
                        L Offline
                        lansing
                        wrote on 14 Aug 2020, 20:54 last edited by
                        #11

                        I have followed the scribble example to use QWidget and QPainter to draw line. I have used QPixmap to hold the line drawing instead of QImage from the example. The drawing works fine until I centered the QPixmap in paintEvent(), my drawing wasn't centered along with the QPixmap.

                        void Canvas::mousePressEvent(QMouseEvent *a_pEvent)
                        {
                            if (a_pEvent->button() == Qt::LeftButton) {
                                m_drawing = true;
                                m_lastPoint =  a_pEvent->pos();
                            }
                        }
                        
                        void Canvas::mouseMoveEvent(QMouseEvent *a_pEvent)
                        {
                            if ((a_pEvent->buttons() & Qt::LeftButton) && m_drawing) {
                                drawPointTo(a_pEvent->pos());        
                            }
                        }
                        
                        void Canvas::paintEvent(QPaintEvent *event)
                        {
                            QPainter painter(this);
                            /* center image */
                            painter.drawPixmap((rect().bottomRight() - m_drawingPixmap.rect().bottomRight()) / 2, m_drawingPixmap); 
                            painter.end();
                        }
                        
                        void Canvas::drawPointTo(const QPointF &a_endPoint)
                        {
                            QPainter painter(&m_drawingPixmap);
                            painter.setPen(QPen(Qt::black, 2));
                            painter.drawLine(m_lastPoint, a_endPoint);
                            update();
                            m_lastPoint = a_endPoint;
                        }
                        
                        
                        B 1 Reply Last reply 15 Aug 2020, 04:11
                        0
                        • L lansing
                          14 Aug 2020, 20:54

                          I have followed the scribble example to use QWidget and QPainter to draw line. I have used QPixmap to hold the line drawing instead of QImage from the example. The drawing works fine until I centered the QPixmap in paintEvent(), my drawing wasn't centered along with the QPixmap.

                          void Canvas::mousePressEvent(QMouseEvent *a_pEvent)
                          {
                              if (a_pEvent->button() == Qt::LeftButton) {
                                  m_drawing = true;
                                  m_lastPoint =  a_pEvent->pos();
                              }
                          }
                          
                          void Canvas::mouseMoveEvent(QMouseEvent *a_pEvent)
                          {
                              if ((a_pEvent->buttons() & Qt::LeftButton) && m_drawing) {
                                  drawPointTo(a_pEvent->pos());        
                              }
                          }
                          
                          void Canvas::paintEvent(QPaintEvent *event)
                          {
                              QPainter painter(this);
                              /* center image */
                              painter.drawPixmap((rect().bottomRight() - m_drawingPixmap.rect().bottomRight()) / 2, m_drawingPixmap); 
                              painter.end();
                          }
                          
                          void Canvas::drawPointTo(const QPointF &a_endPoint)
                          {
                              QPainter painter(&m_drawingPixmap);
                              painter.setPen(QPen(Qt::black, 2));
                              painter.drawLine(m_lastPoint, a_endPoint);
                              update();
                              m_lastPoint = a_endPoint;
                          }
                          
                          
                          B Offline
                          B Offline
                          Bonnie
                          wrote on 15 Aug 2020, 04:11 last edited by Bonnie
                          #12

                          @lansing
                          I think that's not hard to understand.
                          If your pixmap's top left isn't the same with the widget, then they have different coordinate system.
                          You need to map your points' coordinates from the widget to the pixmap when saving.

                          L 1 Reply Last reply 15 Aug 2020, 04:37
                          0
                          • B Bonnie
                            15 Aug 2020, 04:11

                            @lansing
                            I think that's not hard to understand.
                            If your pixmap's top left isn't the same with the widget, then they have different coordinate system.
                            You need to map your points' coordinates from the widget to the pixmap when saving.

                            L Offline
                            L Offline
                            lansing
                            wrote on 15 Aug 2020, 04:37 last edited by
                            #13

                            @Bonnie

                            How do I do that? I did a few trials and errors but still couldn't get it right.

                            So I ended up subclassing a QLabel class and added it to the canvas, and then set the pixmap and move all the paintEvent, mouse event functions to this label class.

                            Do I not need to do this?

                            B 1 Reply Last reply 15 Aug 2020, 05:06
                            0
                            • L lansing
                              15 Aug 2020, 04:37

                              @Bonnie

                              How do I do that? I did a few trials and errors but still couldn't get it right.

                              So I ended up subclassing a QLabel class and added it to the canvas, and then set the pixmap and move all the paintEvent, mouse event functions to this label class.

                              Do I not need to do this?

                              B Offline
                              B Offline
                              Bonnie
                              wrote on 15 Aug 2020, 05:06 last edited by
                              #14

                              @lansing
                              If you feel the mapping difficult I think it is no problem to put a centered "painting QWidget" inside your canvas.
                              But what's wrong with just subclass a QWidget and add that to the canvas?
                              Do you have a reason that you must use a QLabel?

                              L 1 Reply Last reply 15 Aug 2020, 06:42
                              0
                              • B Bonnie
                                15 Aug 2020, 05:06

                                @lansing
                                If you feel the mapping difficult I think it is no problem to put a centered "painting QWidget" inside your canvas.
                                But what's wrong with just subclass a QWidget and add that to the canvas?
                                Do you have a reason that you must use a QLabel?

                                L Offline
                                L Offline
                                lansing
                                wrote on 15 Aug 2020, 06:42 last edited by
                                #15

                                @Bonnie

                                The QLabel is the "centered Qwidget" you talked of. Because it can hold a QPixmap for the line drawing, have all the mouse event functions and paintEvent, as well as able to retrieve the position.

                                canvas

                                Canvas::Canvas(QWidget *a_pParent): QWidget(a_pParent),  
                                {
                                    m_drawingLabel = new DrawingLabel(this);
                                    QHBoxLayout *layout = new QHBoxLayout();
                                    layout->addWidget(m_drawingLabel );
                                    setLayout(layout);
                                }
                                
                                void Canvas::drawFrame(const QPixmap &a_drawingPixmap)
                                {
                                    // center the Qlabel when loading in the pixmap
                                    int x = (rect().width() - a_drawingPixmap.width()) / 2 ;
                                    int y = (rect().height() - a_drawingPixmap.height()) /2;
                                    m_drawingLabel ->setGeometry (x, y, a_drawingPixmap.width(), a_drawingPixmap.height());
                                
                                    m_drawingLabel ->setDrawingPixmap(a_drawingPixmap);
                                }
                                

                                qlabel

                                void DrawingLabel::paintEvent(QPaintEvent *event)
                                {
                                    QPainter painter(this);
                                    painter.drawPixmap(0,0,m_drawingPixmap);
                                    painter.end();
                                }
                                
                                void DrawingLabel::setDrawingPixmap(const QPixmap & a_pixmap)
                                {
                                    m_drawingPixmap= a_pixmap;
                                    update();
                                }
                                
                                void DrawingLabel::mousePressEvent(QMouseEvent *a_pEvent)
                                {
                                    if (a_pEvent->button() == Qt::LeftButton) {
                                        m_drawing = true;
                                        m_lastPoint = a_pEvent->pos();
                                    }
                                }
                                ...
                                mousePressEvent()
                                mouseReleaseEvent()
                                drawPointTo()
                                
                                B 1 Reply Last reply 15 Aug 2020, 06:47
                                0
                                • L lansing
                                  15 Aug 2020, 06:42

                                  @Bonnie

                                  The QLabel is the "centered Qwidget" you talked of. Because it can hold a QPixmap for the line drawing, have all the mouse event functions and paintEvent, as well as able to retrieve the position.

                                  canvas

                                  Canvas::Canvas(QWidget *a_pParent): QWidget(a_pParent),  
                                  {
                                      m_drawingLabel = new DrawingLabel(this);
                                      QHBoxLayout *layout = new QHBoxLayout();
                                      layout->addWidget(m_drawingLabel );
                                      setLayout(layout);
                                  }
                                  
                                  void Canvas::drawFrame(const QPixmap &a_drawingPixmap)
                                  {
                                      // center the Qlabel when loading in the pixmap
                                      int x = (rect().width() - a_drawingPixmap.width()) / 2 ;
                                      int y = (rect().height() - a_drawingPixmap.height()) /2;
                                      m_drawingLabel ->setGeometry (x, y, a_drawingPixmap.width(), a_drawingPixmap.height());
                                  
                                      m_drawingLabel ->setDrawingPixmap(a_drawingPixmap);
                                  }
                                  

                                  qlabel

                                  void DrawingLabel::paintEvent(QPaintEvent *event)
                                  {
                                      QPainter painter(this);
                                      painter.drawPixmap(0,0,m_drawingPixmap);
                                      painter.end();
                                  }
                                  
                                  void DrawingLabel::setDrawingPixmap(const QPixmap & a_pixmap)
                                  {
                                      m_drawingPixmap= a_pixmap;
                                      update();
                                  }
                                  
                                  void DrawingLabel::mousePressEvent(QMouseEvent *a_pEvent)
                                  {
                                      if (a_pEvent->button() == Qt::LeftButton) {
                                          m_drawing = true;
                                          m_lastPoint = a_pEvent->pos();
                                      }
                                  }
                                  ...
                                  mousePressEvent()
                                  mouseReleaseEvent()
                                  drawPointTo()
                                  
                                  B Offline
                                  B Offline
                                  Bonnie
                                  wrote on 15 Aug 2020, 06:47 last edited by Bonnie
                                  #16

                                  @lansing
                                  I mean I don't think it is necessary to use a QLabel as the centered widget since you don't seem to use any QLabel functions.
                                  Why can't you just subclass a QWidget as the "DrawingLabel"?

                                  And also, why are you setting the geometry while you are using a layout?
                                  That don't make any sense.

                                  L 1 Reply Last reply 15 Aug 2020, 06:55
                                  0
                                  • B Bonnie
                                    15 Aug 2020, 06:47

                                    @lansing
                                    I mean I don't think it is necessary to use a QLabel as the centered widget since you don't seem to use any QLabel functions.
                                    Why can't you just subclass a QWidget as the "DrawingLabel"?

                                    And also, why are you setting the geometry while you are using a layout?
                                    That don't make any sense.

                                    L Offline
                                    L Offline
                                    lansing
                                    wrote on 15 Aug 2020, 06:55 last edited by lansing
                                    #17

                                    @Bonnie

                                    I can change to that, I just need some wrapper that can do all the things I mentioned above.

                                    The layout was used to add the QLabel to the canvas.

                                    B T 2 Replies Last reply 15 Aug 2020, 07:04
                                    0
                                    • L lansing
                                      15 Aug 2020, 06:55

                                      @Bonnie

                                      I can change to that, I just need some wrapper that can do all the things I mentioned above.

                                      The layout was used to add the QLabel to the canvas.

                                      B Offline
                                      B Offline
                                      Bonnie
                                      wrote on 15 Aug 2020, 07:04 last edited by Bonnie
                                      #18

                                      @lansing
                                      You either use a layout to keep the label centered, or set the geometry by yourself and don't use any layout.
                                      Set geometry to a widget managed by a layout is meaningless, the layout may reset its geometry at any time.
                                      You can use the layout like that:

                                      layout->addWidget(m_drawingLabel, Qt::AlignCenter);
                                      
                                      void Canvas::drawFrame(const QPixmap &a_drawingPixmap)
                                      {
                                          m_drawingLabel->setFixedSize(a_drawingPixmap.size());
                                          m_drawingLabel->setDrawingPixmap(a_drawingPixmap);
                                      }
                                      
                                      1 Reply Last reply
                                      0
                                      • L lansing
                                        15 Aug 2020, 06:55

                                        @Bonnie

                                        I can change to that, I just need some wrapper that can do all the things I mentioned above.

                                        The layout was used to add the QLabel to the canvas.

                                        T Offline
                                        T Offline
                                        Thomas Stein
                                        wrote on 15 Aug 2020, 13:13 last edited by
                                        #19
                                        This post is deleted!
                                        1 Reply Last reply
                                        0
                                        • L Offline
                                          L Offline
                                          lansing
                                          wrote on 16 Aug 2020, 00:40 last edited by
                                          #20

                                          I'm not spreading myself too thin right now, I'll stick to one method first until it worked well before I try other methods.

                                          So I got it working under normal condition. I have changed the canvas to subclass a QScrollArea because I need to zoom in. I did the zoom function in the wheelEvent(). However, the problem now is with the QPixmap.scaled function, the more I zoomed in, the more laggy the program got.

                                          void Canvas::wheelEvent(QWheelEvent *a_pEvent)
                                          {
                                              QPoint delta = a_pEvent->angleDelta();
                                              // zooming
                                              if (delta.y() > 0) {
                                                  m_zoomRatio += 0.6;
                                              } else {
                                                  m_zoomRatio -= 0.6;
                                              }
                                              m_drawingLabel->setFixedSize(m_drawingPixmap.size() * m_zoomRatio);
                                          
                                              QSize zoomSize = m_drawingPixmap.size() * m_zoomRatio;
                                              m_drawingLabel->setDrawingPixmap(m_drawingPixmap.scaled(zoomSize));
                                          }
                                          
                                          void Canvas::drawFrame(const QPixmap &a_drawingPixmap)
                                          {
                                              m_drawingPixmap = a_drawingPixmap; // save a copy for zooming
                                              
                                              m_drawingLabel->setFixedSize(a_drawingPixmap.size());
                                              m_drawingLabel->setDrawingPixmap(a_drawingPixmap);
                                          }
                                          
                                          1 Reply Last reply
                                          0

                                          4/24

                                          12 Aug 2020, 19:36

                                          20 unread
                                          • Login

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