Search code examples
c++qtqtgui

To set limit to draggable line segments


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

sample image

I can drag the lines by mouse.

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:

.h is:

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 file:

// 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


Solution

  • You need to check the new y value, not the current value:

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