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. Draggable line segment
Forum Updated to NodeBB v4.3 + New Features

Draggable line segment

Scheduled Pinned Locked Moved Solved General and Desktop
20 Posts 4 Posters 2.5k Views 4 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.
  • SGaistS Offline
    SGaistS Offline
    SGaist
    Lifetime Qt Champion
    wrote on last edited by
    #2

    Hi,

    Out of curiosity, why not use the graphics view framework where you have the building blocks ready for that kind of development ?

    Interested in AI ? www.idiap.ch
    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

    1 Reply Last reply
    4
    • mrjjM Offline
      mrjjM Offline
      mrjj
      Lifetime Qt Champion
      wrote on last edited by
      #3

      Hi
      As @SGaist says, the graphics view framework offer alot of features of out the box with little effort.
      Check out the mini diagram app.
      https://doc.qt.io/qt-5/qtwidgets-graphicsview-diagramscene-example.html

      Anyway, a draggable line when its straight is not super hard to code.

      class MainWindow : public QMainWindow
      {
        .... 
      private:
          bool dragging = false; // status var to see if we are dragging
      protected:
         // we then override / make our own of these function to track mouse movement and clicks
          virtual void mousePressEvent(QMouseEvent *event) override;
          virtual void mouseReleaseEvent(QMouseEvent *event) override;
          virtual void mouseMoveEvent(QMouseEvent *event) override;
      
      };
      
      Then in.cpp
      
      // small helper to give us the distance
      int distance(QPoint p1, QPoint p2)
      {
          return abs(p2.y() - p1.y());
      }
      
      // when user clicks
      void MainWindow::mousePressEvent(QMouseEvent *event)
      {
          QPoint mp = event->pos(); // where is mouse
          // test if we hit the line. give user 10 pixels slack as its hard to hit one pixel
          if (distance ( mp, p1) < 10 && ( mp.x() > p1.x() && mp.x() < p2.x() ) ) {
              dragging = true; // flag we are dragging
          }
      }
      
      void MainWindow::mouseReleaseEvent(QMouseEvent *event)
      {
          dragging = false; // if user release mouse we are not draggign anymore
      }
      
      // then when mouse move
      void MainWindow::mouseMoveEvent(QMouseEvent *event)
      {
         // If we are dragging, call your normal slider changed function to update your points.
          if ( dragging ) {
              changeP1value(event->y());
          }
      }
      
      

      And that is it.

      alt text

      1 Reply Last reply
      3
      • V Offline
        V Offline
        viniltc
        wrote on last edited by viniltc
        #4

        @SGaist , @mrjj Thanks a lot for introducing me to Graphic view framework. Will definitely give it a try.
        I was trying out the example @mrjj pointed out for the draggable line.

        Here,

        void MainWindow::mousePressEvent(QMouseEvent *event)
        {
            QPoint mp = event->pos(); //---->
            // test if we hit the line. give user 10 pixels slack as its hard to hit one pixel
            if (distance ( mp, p1) < 10 && ( mp.x() > p1.x() && mp.x() < p2.x() ) ) {
                dragging = true;
            }
        }
        

        I get the following error:

        mainwindow.cpp:44:22: error: member access into incomplete type 'QMouseEvent'
        qwidget.h:72:7: note: forward declaration of 'QMouseEvent'
        
        

        Also, I get error related to points p1 and p2

        mainwindow.cpp:28: error: C2065: 'p1': undeclared identifier
        mainwindow.cpp:28: error: C2228: left of '.x' must have class/struct/union
        mainwindow.cpp:28: type is 'unknown-type'
        mainwindow.cpp:28: error: C2065: 'p2': undeclared identifier
        
        

        I decalred p1 and p2 are private as:

        private:
            Ui::MainWindow *ui;
            bool dragging = false; 
            QPoint p1, p2;
        

        what might be the issue?

        jsulmJ 1 Reply Last reply
        0
        • V viniltc

          @SGaist , @mrjj Thanks a lot for introducing me to Graphic view framework. Will definitely give it a try.
          I was trying out the example @mrjj pointed out for the draggable line.

          Here,

          void MainWindow::mousePressEvent(QMouseEvent *event)
          {
              QPoint mp = event->pos(); //---->
              // test if we hit the line. give user 10 pixels slack as its hard to hit one pixel
              if (distance ( mp, p1) < 10 && ( mp.x() > p1.x() && mp.x() < p2.x() ) ) {
                  dragging = true;
              }
          }
          

          I get the following error:

          mainwindow.cpp:44:22: error: member access into incomplete type 'QMouseEvent'
          qwidget.h:72:7: note: forward declaration of 'QMouseEvent'
          
          

          Also, I get error related to points p1 and p2

          mainwindow.cpp:28: error: C2065: 'p1': undeclared identifier
          mainwindow.cpp:28: error: C2228: left of '.x' must have class/struct/union
          mainwindow.cpp:28: type is 'unknown-type'
          mainwindow.cpp:28: error: C2065: 'p2': undeclared identifier
          
          

          I decalred p1 and p2 are private as:

          private:
              Ui::MainWindow *ui;
              bool dragging = false; 
              QPoint p1, p2;
          

          what might be the issue?

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

          @viniltc said in Draggable line segment:

          member access into incomplete type 'QMouseEvent'

          include QMouseEvent header

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

          1 Reply Last reply
          3
          • V Offline
            V Offline
            viniltc
            wrote on last edited by
            #6

            @jsulm Thanks.

            Still have following issues related to points p1 and p2:

            mainwindow.cpp:28: error: C2065: 'p1': undeclared identifier
            mainwindow.cpp:28: error: C2228: left of '.x' must have class/struct/union
            mainwindow.cpp:28: type is 'unknown-type'
            mainwindow.cpp:28: error: C2065: 'p2': undeclared identifier
            
            1 Reply Last reply
            0
            • V Offline
              V Offline
              viniltc
              wrote on last edited by viniltc
              #7

              That's was a typo, my bad. It is working now ! :)
              Thanks a lot guys :)

              1 Reply Last reply
              1
              • V Offline
                V Offline
                viniltc
                wrote on last edited by
                #8

                @mrjj

                I wonder if I have multiple line segments to drag, having more drag status variables is the best way to implement?

                for example:

                    bool dragging1 = false; // for line 1
                    bool dragging2 = false; // fpr line 2
                

                and

                void MainWindow::mousePressEvent(QMouseEvent *event)
                {
                    QPoint mp = event->pos(); 
                    if (distance ( mp, p1) < 10 && ( mp.x() > p1.x() && mp.x() < p2.x() ) ) {
                        dragging1 = true;
                    }
                    else if (distance ( mp, p3) < 10 && ( mp.x() > p3.x() && mp.x() < p4.x() ) ) {
                        dragging2 = true; 
                    }
                }
                
                void MainWindow::mouseMoveEvent(QMouseEvent *event)
                {
                    if ( dragging1 ) {
                        changeP1value(event->y());
                
                    }
                    else if (dragging2) {
                        changeP2value(event->y());
                    }
                }
                
                

                Whats your suggestion?

                mrjjM 1 Reply Last reply
                0
                • V viniltc

                  @mrjj

                  I wonder if I have multiple line segments to drag, having more drag status variables is the best way to implement?

                  for example:

                      bool dragging1 = false; // for line 1
                      bool dragging2 = false; // fpr line 2
                  

                  and

                  void MainWindow::mousePressEvent(QMouseEvent *event)
                  {
                      QPoint mp = event->pos(); 
                      if (distance ( mp, p1) < 10 && ( mp.x() > p1.x() && mp.x() < p2.x() ) ) {
                          dragging1 = true;
                      }
                      else if (distance ( mp, p3) < 10 && ( mp.x() > p3.x() && mp.x() < p4.x() ) ) {
                          dragging2 = true; 
                      }
                  }
                  
                  void MainWindow::mouseMoveEvent(QMouseEvent *event)
                  {
                      if ( dragging1 ) {
                          changeP1value(event->y());
                  
                      }
                      else if (dragging2) {
                          changeP2value(event->y());
                      }
                  }
                  
                  

                  Whats your suggestion?

                  mrjjM Offline
                  mrjjM Offline
                  mrjj
                  Lifetime Qt Champion
                  wrote on last edited by mrjj
                  #9

                  @viniltc
                  Hi
                  Well that is a ok way if you have 2.
                  But if you had many, i would go with a
                  QPoint *CurPoint1=nullptr;
                  QPoint *CurPoint2=nullptr;

                  and then in

                  void MainWindow::mousePressEvent(QMouseEvent *event)
                  {
                      QPoint mp = event->pos(); 
                      if (distance ( mp, p1) < 10 && ( mp.x() > p1.x() && mp.x() < p2.x() ) ) {
                          dragging = true;
                         CurPoint1 = &p1;
                         CurPoint2 = &p2;
                      }
                      else if (distance ( mp, p3) < 10 && ( mp.x() > p3.x() && mp.x() < p4.x() ) ) {
                          dragging = true; 
                          CurPoint1 = &p3;
                          CurPoint1 = &p4;
                      }
                  }
                  

                  and then use that in to update the points in ValueChanged
                  as not to have same code over and over for more points.

                  the check and && ( mp.x() > p3.x() && mp.x() < p4.x() ) )
                  and assignment could also be changed to use the pointers instead as not to replicate code since
                  its the same but just with other points.
                  A list could also be used to allow as many as you need.

                  Word of warning. make sure to test if CurPoint1/2 is null before using them as
                  if you start with dragging slider, the values are null as we first assign on mouse.

                  1 Reply Last reply
                  2
                  • V Offline
                    V Offline
                    viniltc
                    wrote on last edited by
                    #10

                    @mrjj Thanks a lot for your feedback, it works well.
                    I also did this in the constructor to show the line in a predefined height:

                    MainWindow::MainWindow(QWidget *parent)
                        : QMainWindow(parent)
                        , ui(new Ui::MainWindow)
                    {
                        ui->setupUi(this);
                        p1.setY(100);
                        p2.setY(100);
                        p3.setY(100);
                        p4.setY(100);
                    
                    }
                    

                    what is the best way to set a range to drag, for example from 100 the line should only draggable within (50,150).

                    mrjjM 1 Reply Last reply
                    0
                    • V viniltc

                      @mrjj Thanks a lot for your feedback, it works well.
                      I also did this in the constructor to show the line in a predefined height:

                      MainWindow::MainWindow(QWidget *parent)
                          : QMainWindow(parent)
                          , ui(new Ui::MainWindow)
                      {
                          ui->setupUi(this);
                          p1.setY(100);
                          p2.setY(100);
                          p3.setY(100);
                          p4.setY(100);
                      
                      }
                      

                      what is the best way to set a range to drag, for example from 100 the line should only draggable within (50,150).

                      mrjjM Offline
                      mrjjM Offline
                      mrjj
                      Lifetime Qt Champion
                      wrote on last edited by
                      #11

                      @viniltc

                      Hi
                      You need to keep the original y values (in its own variables in .h/class)
                      and then in mousepress store then values ( or value since they have same y both points)
                      so in
                      mouseMoveEvent you can check if its still within allowed drag range and if not then do not call
                      the ValueChanged.

                      It will then stay with in your range.

                      1 Reply Last reply
                      1
                      • V Offline
                        V Offline
                        viniltc
                        wrote on last edited by viniltc
                        #12

                        @mrjj

                        I did this:

                        private:
                            Ui::MainWindow *ui;
                             bool dragging = false;
                             QPoint p1 = QPoint(400,100);
                             QPoint p2 = QPoint(450,100);
                             QPoint p3 = QPoint(450,100);
                             QPoint p4 = QPoint(500,100);
                        
                             QPoint *CurPoint1=nullptr;
                             QPoint *CurPoint2=nullptr;
                        

                        I'm a bit confused how to implement those conditons in mousePressEvent and mouseMoveEvent
                        If I do this in the mouseMoveEvent

                         if (dragging)
                            {
                        
                                if( CurPoint1->y()>50 && CurPoint1->y()<150)
                                {
                        
                                changeP1value(event->y());
                        
                                }
                            }
                        

                        It just stop update if I go beyond the limit. What might be the issue?

                        1 Reply Last reply
                        0
                        • mrjjM Offline
                          mrjjM Offline
                          mrjj
                          Lifetime Qt Champion
                          wrote on last edited by
                          #13

                          Hi
                          If it stops showing the line maybe

                           if (dragging)
                              {
                                  if( CurPoint1->y()>50 && CurPoint1->y()<150)
                                  {
                                  changeP1value(event->y());
                                  }        
                                 else       
                                   update();    
                          }
                          
                          

                          To redraw the point with the last points value.

                          V 1 Reply Last reply
                          1
                          • mrjjM mrjj

                            Hi
                            If it stops showing the line maybe

                             if (dragging)
                                {
                                    if( CurPoint1->y()>50 && CurPoint1->y()<150)
                                    {
                                    changeP1value(event->y());
                                    }        
                                   else       
                                     update();    
                            }
                            
                            

                            To redraw the point with the last points value.

                            V Offline
                            V Offline
                            viniltc
                            wrote on last edited by
                            #14

                            @mrjj

                            Actually it just stops when I hit 50 or 150 , it is not updating after that.

                            I doubt if it's a problem with mousePressEvent , now I do this:

                            void MainWindow::mousePressEvent(QMouseEvent *event)
                            {
                                QPoint mp = event->pos(); 
                                if (distance ( mp, p1) < 10 && ( mp.x() > p1.x() && mp.x() < p2.x() ) ) {
                                    dragging = true; 
                                    CurPoint1 = &p1;
                                    CurPoint2 = &p2;        
                                }
                                else if (distance ( mp, p3) < 10 && ( mp.x() > p3.x() && mp.x() < p4.x() ) ) {
                                    dragging = true; 
                                    CurPoint1 = &p3;
                                    CurPoint2 = &p4;
                                }
                            }
                            
                            // then when mouse move
                            void MainWindow::mouseMoveEvent(QMouseEvent *event)
                            {
                               // If we are dragging, call your normal slider changed function to update your points.
                                if (dragging)
                                {
                            
                                    if( CurPoint1->y()>50 && CurPoint1->y()<150)
                                    {
                                    changeP1value(event->y());
                                    }
                                    else
                                    update();
                                }
                            
                            }
                            
                            void MainWindow::changeP1value(int value)
                            {
                            
                                CurPoint1->setY(value);
                                CurPoint2->setY(value);
                                update();
                            }
                            
                            
                            1 Reply Last reply
                            0
                            • mrjjM Offline
                              mrjjM Offline
                              mrjj
                              Lifetime Qt Champion
                              wrote on last edited by
                              #15

                              @viniltc said in Draggable line segment:

                              it is not updating after that.

                              You mean it stops drawing the line or in what way ?

                              1 Reply Last reply
                              0
                              • V Offline
                                V Offline
                                viniltc
                                wrote on last edited by
                                #16

                                @mrjj

                                I mean, if I drag beyond 50 or 150 (y values). The line just stops at those points and freezes, can't drag anymore.

                                mrjjM 1 Reply Last reply
                                0
                                • V viniltc

                                  @mrjj

                                  I mean, if I drag beyond 50 or 150 (y values). The line just stops at those points and freezes, can't drag anymore.

                                  mrjjM Offline
                                  mrjjM Offline
                                  mrjj
                                  Lifetime Qt Champion
                                  wrote on last edited by mrjj
                                  #17

                                  @viniltc
                                  Yes, was that not the goal ??
                                  Or do u mean it get stucked and cannot be dragged down again ?

                                  V 1 Reply Last reply
                                  0
                                  • mrjjM mrjj

                                    @viniltc
                                    Yes, was that not the goal ??
                                    Or do u mean it get stucked and cannot be dragged down again ?

                                    V Offline
                                    V Offline
                                    viniltc
                                    wrote on last edited by
                                    #18

                                    @mrjj
                                    Yeah, I can't drag down again. Once I hit 50 or 150. The line just freezes there.

                                    1 Reply Last reply
                                    0
                                    • V Offline
                                      V Offline
                                      viniltc
                                      wrote on last edited by viniltc
                                      #19

                                      @mrjj

                                      This is what I'm doing now, but the situation is same, the line gets stuck and can't drag down:

                                      public:
                                          MainWindow(QWidget *parent = nullptr);
                                          ~MainWindow();
                                           void paintEvent(QPaintEvent *e);
                                      
                                      public slots:
                                      
                                            void changeP1value(int);
                                      
                                      
                                      private:
                                          Ui::MainWindow *ui;
                                           bool dragging = false; 
                                           QPoint p1 = QPoint(400,100);
                                           QPoint p2 = QPoint(450,100);
                                           QPoint p3 = QPoint(450,100);
                                           QPoint p4 = QPoint(500,100);
                                      
                                           QPoint *CurPoint1=nullptr;
                                           QPoint *CurPoint2=nullptr;
                                      
                                      protected:
                                           virtual void mousePressEvent(QMouseEvent *event) override;
                                           virtual void mouseReleaseEvent(QMouseEvent *event) override;
                                           virtual void mouseMoveEvent(QMouseEvent *event) override;
                                      };
                                      #endif // MAINWINDOW_H
                                      

                                      and in .cpp

                                      int distance(QPoint x1, QPoint x2)
                                      {
                                          return abs(x2.y() - x1.y());
                                      }
                                      
                                      
                                      void MainWindow::paintEvent(QPaintEvent *e)
                                      {
                                          QPainter painter1(this);
                                      
                                          QPen pointpen(Qt::black);
                                          pointpen.setWidth(5);
                                          QPen linepen1(Qt::red);
                                          linepen1.setWidth(2);
                                          QPen linepen2(Qt::green);
                                          linepen2.setWidth(2);
                                      
                                          painter1.setPen(linepen1);
                                          painter1.drawLine(p1,p2);
                                          painter1.setPen(linepen2);
                                          painter1.drawLine(p3,p4);
                                      
                                          qDebug()<<"Values of p1.y and p2.y:"<<p1.y()<<"and"<<p2.y();
                                      }
                                      
                                      
                                      void MainWindow::mousePressEvent(QMouseEvent *event)
                                      {
                                          QPoint mp = event->pos(); 
                                      
                                          if (distance ( mp, p1) < 20 && ( mp.x() > p1.x() && mp.x() < p2.x() ) ) {
                                              dragging = true;
                                      
                                              CurPoint1 = &p1;
                                              CurPoint2 = &p2;
                                          }
                                          else if (distance ( mp, p3) < 20 && ( mp.x() > p3.x() && mp.x() < p4.x() ) ) {
                                              dragging = true;
                                              CurPoint1 = &p3;
                                              CurPoint2 = &p4;
                                          }
                                      }
                                      
                                      void MainWindow::mouseReleaseEvent(QMouseEvent *event)
                                      {
                                          dragging = false; 
                                      }
                                      
                                      
                                      void MainWindow::mouseMoveEvent(QMouseEvent *event)
                                      {
                                       
                                          if(CurPoint1!=nullptr)
                                              qDebug()<<"Curr point is NOT null";
                                      
                                          if (dragging)
                                          {
                                            if(CurPoint1->y()>50 && CurPoint1->y()<150)
                                              {
                                              changeP1value(event->y());
                                              }
                                      
                                            else
                                            update();
                                          }
                                      
                                      }
                                      
                                      void MainWindow::changeP1value(int value)
                                      {
                                      
                                          CurPoint1->setY(value);
                                          CurPoint2->setY(value);
                                          update();
                                      
                                      }
                                      
                                      

                                      Can you spot any spot any issues?

                                      1 Reply Last reply
                                      0
                                      • mrjjM Offline
                                        mrjjM Offline
                                        mrjj
                                        Lifetime Qt Champion
                                        wrote on last edited by
                                        #20

                                        Hi
                                        There is no errors as such but since we can continue drag mouse after the endpoint,
                                        the mouse event coordinates drifts and hence even dragging is still true some of the other checks is not valid anymore. ( like you are not on the line anymore)

                                        I do not know any good solution to it currently.

                                        1 Reply Last reply
                                        1

                                        • Login

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