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

To set limit to a draggable line segment



  • Hi all,

    I'm trying to implement a line segment which can be draggable by mouse between two points (shown below where green and red lines must be draggable between black dash lines).

    dragLine.JPG

    I can now drag the lines by mouse (which I followed a sample program given by @mrjj , here).

    As a next step I want to set a limit to this draggable area, which I'm having issues to implement with. I really appreciate if someone can help me to do this. I now explain the situation in a bit detail:

    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

    // small helper to give us the distance
    int distance(QPoint x1, QPoint x2)
    {
        return abs(x2.y() - x1.y());
    }
    
    // the Paint event to draw lines
    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);
    
    }
    
    // when user clicks
    void MainWindow::mousePressEvent(QMouseEvent *event)
    {
        QPoint mp = event->pos(); // where is mouse
    // test if we hit the line. give user 20 pixels slack as its hard to hit one pixel
        if (distance ( mp, p1) < 20 && ( mp.x() > p1.x() && mp.x() < p2.x() ) ) {
            dragging = true; // flag we are dragging
            
            
            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; // 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)
        {
          if(CurPoint1->y()>50 && CurPoint1->y()<150) 
            {
            changeP1value(event->y());
            }
          else
          update();
        }
    
    }
    
    void MainWindow::changeP1value(int value)
    {
    
        CurPoint1->setY(value);
        CurPoint2->setY(value);
        update();
    
    }
    
    

    In the mouseMoveEvent, I've condition to check if I'm dragging a line and if the hight is between 50 and 150:

     if (dragging)
        {
          if(CurPoint1->y()>50 && CurPoint1->y()<150) //----> it get stucked and cannot be dragged down again 
            {
            changeP1value(event->y());
            }
          else
          update();
        }
    

    In this case I can drag , the line stops at the set limits but I cant drag down again. Can you spot an issue?

    Thanks in advance



  • That problem got solved finally!
    The correct way is to check the new y value, not the current value:

    void MainWindow::mouseMoveEvent(QMouseEvent *event)
    {
      if (dragging)
      {
        if(event->y() > 50 && event->y() < 150)  //--> check new y value,
        {
          changeP1value(event->y());
        }
        else
          update();
      }
    }
    

Log in to reply