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. Selection of lines through mouse click is not sharp in Qt

Selection of lines through mouse click is not sharp in Qt

Scheduled Pinned Locked Moved Unsolved General and Desktop
14 Posts 4 Posters 938 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.
  • T Offline
    T Offline
    tushu
    wrote on last edited by tushu
    #1

    s.PNG

    In my view there are 3 lines. 1 Polyline, and 2 straight lines. I have named them as P1 and s1 and s2

    I am not able to select s1 line. If I try to select it , P1 gets selected ( though I have not clicked on P1 )
    
    Selection of p1 is also not sharp. If I clicked somewhere around P1 ( not on P1 ) still P1 gets selected.
    
    void Widget::on_designButoon_clicked()
    {
      // For line S2
        QPolygonF net0;
        net0 << QPointF(50,180);
        net0 << QPointF(600,180);
        QPainterPath pPath0;
        pPath0.addPolygon(net0);
        MyPoly* _poly0 = new MyPoly();
        _poly0->DrawPolyline(pPath0);
    
        scene->addItem(static_cast<QGraphicsPathItem*>(_poly0));
    
        // Same logic for Line S1 and P1
    }
    

    MyPoly.h

    class MyPoly : public QGraphicsPathItem
    {
        //Q_OBJECT
    public:
        explicit MyPoly();
        void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
        void DrawPolyline(QPainterPath pPath);
    };
    

    MyPoly.cpp

    void MyPoly::DrawPolyline(QPainterPath pPath)
    {
        this->setPen(QPen(QColor("red"), 2));
        this->setPath(pPath);
        this->setFlag(QGraphicsItem::ItemIsSelectable);
        //this->setBoundingRegionGranularity(1.0); this has no effect
    
    }
    
    void MyPoly::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
                                 QWidget *widget)
    {
        auto copied_option = *option;
        copied_option.state &= ~QStyle::State_Selected;
        auto selected = option->state & QStyle::State_Selected;
        QGraphicsPathItem::paint(painter, &copied_option, widget);
        if (selected) {
            painter->save();
            painter->setBrush(Qt::NoBrush);
            painter->setPen(QPen(option->palette.windowText(), 0, Qt::SolidLine));
            painter->drawPath(shape());
            painter->restore();
        }
    }
    
    T 1 Reply Last reply
    0
    • T tushu

      s.PNG

      In my view there are 3 lines. 1 Polyline, and 2 straight lines. I have named them as P1 and s1 and s2

      I am not able to select s1 line. If I try to select it , P1 gets selected ( though I have not clicked on P1 )
      
      Selection of p1 is also not sharp. If I clicked somewhere around P1 ( not on P1 ) still P1 gets selected.
      
      void Widget::on_designButoon_clicked()
      {
        // For line S2
          QPolygonF net0;
          net0 << QPointF(50,180);
          net0 << QPointF(600,180);
          QPainterPath pPath0;
          pPath0.addPolygon(net0);
          MyPoly* _poly0 = new MyPoly();
          _poly0->DrawPolyline(pPath0);
      
          scene->addItem(static_cast<QGraphicsPathItem*>(_poly0));
      
          // Same logic for Line S1 and P1
      }
      

      MyPoly.h

      class MyPoly : public QGraphicsPathItem
      {
          //Q_OBJECT
      public:
          explicit MyPoly();
          void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
          void DrawPolyline(QPainterPath pPath);
      };
      

      MyPoly.cpp

      void MyPoly::DrawPolyline(QPainterPath pPath)
      {
          this->setPen(QPen(QColor("red"), 2));
          this->setPath(pPath);
          this->setFlag(QGraphicsItem::ItemIsSelectable);
          //this->setBoundingRegionGranularity(1.0); this has no effect
      
      }
      
      void MyPoly::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
                                   QWidget *widget)
      {
          auto copied_option = *option;
          copied_option.state &= ~QStyle::State_Selected;
          auto selected = option->state & QStyle::State_Selected;
          QGraphicsPathItem::paint(painter, &copied_option, widget);
          if (selected) {
              painter->save();
              painter->setBrush(Qt::NoBrush);
              painter->setPen(QPen(option->palette.windowText(), 0, Qt::SolidLine));
              painter->drawPath(shape());
              painter->restore();
          }
      }
      
      T Offline
      T Offline
      tushu
      wrote on last edited by
      #2

      @JonB @SGaist @ChrisW67 @jsulm

      Sorry for last 2 times , I was not framing my problem properly. So it was annoying you all. But this time I have framed it as simple as possible.

      Moreover I got to know that, in such cases I need to override QGraphicsItem::contains() and write my own logic to check whenther, clicked point is inside any QGraphicsItem.

      I tried to override it but I could not do.

      bool MyPoly::contains(const QPointF &point) const
      {
          qreal x = point.x();
          qreal y = point.y();
          if(shape().contains(point))
          {
                  qDebug()<<"Shape found ";
                  qDebug()<< "shape point is = " << shape().elementAt(0);
                  return true;
              }
              else
              {
                  qDebug()<<"Shape not found ";
                  return false;
              }
         }
      }
      

      Will overriding contains() solve my issue ? or do you know any better way ?

      JonBJ 1 Reply Last reply
      0
      • T tushu

        @JonB @SGaist @ChrisW67 @jsulm

        Sorry for last 2 times , I was not framing my problem properly. So it was annoying you all. But this time I have framed it as simple as possible.

        Moreover I got to know that, in such cases I need to override QGraphicsItem::contains() and write my own logic to check whenther, clicked point is inside any QGraphicsItem.

        I tried to override it but I could not do.

        bool MyPoly::contains(const QPointF &point) const
        {
            qreal x = point.x();
            qreal y = point.y();
            if(shape().contains(point))
            {
                    qDebug()<<"Shape found ";
                    qDebug()<< "shape point is = " << shape().elementAt(0);
                    return true;
                }
                else
                {
                    qDebug()<<"Shape not found ";
                    return false;
                }
           }
        }
        

        Will overriding contains() solve my issue ? or do you know any better way ?

        JonBJ Offline
        JonBJ Offline
        JonB
        wrote on last edited by
        #3

        @tushu said in Selection of lines through mouse click is not sharp in Qt:

        if(shape().contains(point))

        Will overriding contains() solve my issue ?

        bool QGraphicsItem::contains(const QPointF &point) const:

        By default, this function calls shape(), but you can reimplement it in a subclass to provide a (perhaps more efficient) implementation.

        So what does your override do/achieve that is any different?

        If anything I would have thought virtual QPainterPath QGraphicsItem::shape() const:

        The default implementation calls boundingRect() to return a simple rectangular shape, but subclasses can reimplement this function to return a more accurate shape for non-rectangular items. For example, a round item may choose to return an elliptic shape for better collision detection. For example:

        Maybe this is what you need to override (I don't know)?

        T 2 Replies Last reply
        0
        • JonBJ JonB

          @tushu said in Selection of lines through mouse click is not sharp in Qt:

          if(shape().contains(point))

          Will overriding contains() solve my issue ?

          bool QGraphicsItem::contains(const QPointF &point) const:

          By default, this function calls shape(), but you can reimplement it in a subclass to provide a (perhaps more efficient) implementation.

          So what does your override do/achieve that is any different?

          If anything I would have thought virtual QPainterPath QGraphicsItem::shape() const:

          The default implementation calls boundingRect() to return a simple rectangular shape, but subclasses can reimplement this function to return a more accurate shape for non-rectangular items. For example, a round item may choose to return an elliptic shape for better collision detection. For example:

          Maybe this is what you need to override (I don't know)?

          T Offline
          T Offline
          tushu
          wrote on last edited by
          #4

          @JonB Thank you for your reply.
          I understood what you want to say. I should override shape() instead of contains(). I should create a shape using stroke using QPainterPathStroker as I want to include outline in the item's shape.
          But main problem is, it is too tough for me. Because from start to end , process is not clear.
          I saw the example,

          QPainterPath RoundItem::shape() const
          {
              QPainterPath path;
              path.addEllipse(boundingRect());
              return path;
          }
          

          but not understanding, which item I need to add ? when I will return it, where will it go ? How my paint() will get signal and it will highlight that item ?
          Confusing. Can you help me in it ?

          1 Reply Last reply
          0
          • JonBJ JonB

            @tushu said in Selection of lines through mouse click is not sharp in Qt:

            if(shape().contains(point))

            Will overriding contains() solve my issue ?

            bool QGraphicsItem::contains(const QPointF &point) const:

            By default, this function calls shape(), but you can reimplement it in a subclass to provide a (perhaps more efficient) implementation.

            So what does your override do/achieve that is any different?

            If anything I would have thought virtual QPainterPath QGraphicsItem::shape() const:

            The default implementation calls boundingRect() to return a simple rectangular shape, but subclasses can reimplement this function to return a more accurate shape for non-rectangular items. For example, a round item may choose to return an elliptic shape for better collision detection. For example:

            Maybe this is what you need to override (I don't know)?

            T Offline
            T Offline
            tushu
            wrote on last edited by
            #5

            @JonB I understood the problem exactly.
            While selecting any of the overlapping lines, the one with bounding rect on top is selected. And this is the exact my problem.
            For that I need to override shape() ( you were right as usual ).
            I googled and I got a few code samples.

            QPainterPath Item::shape() const
            {
                QPainterPath path;
                QPolygon polygon;
                polygon << QPoint(0, 0);
                polygon << QPoint(5, 5);
                polygon << QPoint(width, height);
                polygon << QPoint(width - 5, height - 5);
                path.addPolygon(polygon);
            
                return path;
            }
            
            QPainterPath Line::shape()
            {
                QRectF rect(start_p, end_p).normalized();
            
                // increase the rect beyond the width of the line
                rect.adjust(-2, -2, 2, 2); 
            
                QPainterPath path;
                path.addRect(rect);
            
                return path;    // return the item's defined shape
            }
            

            So here the question is, how will I know start_p, end_p ( starting and ending points of a line ) width, height ?

            JonBJ 1 Reply Last reply
            0
            • T tushu

              @JonB I understood the problem exactly.
              While selecting any of the overlapping lines, the one with bounding rect on top is selected. And this is the exact my problem.
              For that I need to override shape() ( you were right as usual ).
              I googled and I got a few code samples.

              QPainterPath Item::shape() const
              {
                  QPainterPath path;
                  QPolygon polygon;
                  polygon << QPoint(0, 0);
                  polygon << QPoint(5, 5);
                  polygon << QPoint(width, height);
                  polygon << QPoint(width - 5, height - 5);
                  path.addPolygon(polygon);
              
                  return path;
              }
              
              QPainterPath Line::shape()
              {
                  QRectF rect(start_p, end_p).normalized();
              
                  // increase the rect beyond the width of the line
                  rect.adjust(-2, -2, 2, 2); 
              
                  QPainterPath path;
                  path.addRect(rect);
              
                  return path;    // return the item's defined shape
              }
              

              So here the question is, how will I know start_p, end_p ( starting and ending points of a line ) width, height ?

              JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by
              #6

              @tushu
              I'm not at all familiar, never done this sort of thing, so limited point asking me about it. You seem to draw it in DrawPolyline()? So isn't that the information you need for this Line::shape()?

              1 Reply Last reply
              0
              • M Offline
                M Offline
                mchinand
                wrote on last edited by
                #7

                Have your sub-classed QGraphicsItem keep track of them. Store the points and/or polygon to a member variable. Then you can use them in your custom shape() method.

                T 1 Reply Last reply
                1
                • M mchinand

                  Have your sub-classed QGraphicsItem keep track of them. Store the points and/or polygon to a member variable. Then you can use them in your custom shape() method.

                  T Offline
                  T Offline
                  tushu
                  wrote on last edited by
                  #8

                  @mchinand I am following below approach. So not understanding how to keep remeber co-ordinates in a variables.

                      QPolygon net;
                      net << QPoint(67,202);
                      net << QPoint(120,202);
                      net<< QPoint(120,67);
                      net <<QPoint(320,67);
                      net <<QPoint(320,202);
                      net <<QPoint(520,202);
                      net <<QPoint(520,67);
                      QPainterPath pPath;
                      pPath.addPolygon(net);
                      MyPoly* _poly = new MyPoly();
                      _poly->DrawPolyline(pPath);
                      scene->addItem(static_cast<QGraphicsPathItem*>(_poly));
                  
                  1 Reply Last reply
                  0
                  • M Offline
                    M Offline
                    mchinand
                    wrote on last edited by
                    #9
                    class MyPoly : public QGraphicsPathItem {
                         //Q_OBJECT
                     public:
                         explicit MyPoly();
                         void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
                         void DrawPolyline(QPainterPath pPath);
                    private:
                         QPolygon polygon_;
                     };
                    
                    void MyPoly::DrawPolyline(QPolygon polygon)
                    {
                        polygon_ = polygon;
                        QPainterPath pPath;
                        pPath.addPolygon(polygon);
                        this->setPen(QPen(QColor("red"), 2));
                        this->setPath(pPath);
                        this->setFlag(QGraphicsItem::ItemIsSelectable);
                        //this->setBoundingRegionGranularity(1.0); this has no effect
                    
                    }
                    
                        QPolygon net;
                        net << QPoint(67,202);
                        net << QPoint(120,202);
                        net<< QPoint(120,67);
                        net <<QPoint(320,67);
                        net <<QPoint(320,202);
                        net <<QPoint(520,202);
                        net <<QPoint(520,67);
                        MyPoly* _poly = new MyPoly();
                        _poly->DrawPolyline(net);
                    T 1 Reply Last reply
                    0
                    • M mchinand
                      class MyPoly : public QGraphicsPathItem {
                           //Q_OBJECT
                       public:
                           explicit MyPoly();
                           void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
                           void DrawPolyline(QPainterPath pPath);
                      private:
                           QPolygon polygon_;
                       };
                      
                      void MyPoly::DrawPolyline(QPolygon polygon)
                      {
                          polygon_ = polygon;
                          QPainterPath pPath;
                          pPath.addPolygon(polygon);
                          this->setPen(QPen(QColor("red"), 2));
                          this->setPath(pPath);
                          this->setFlag(QGraphicsItem::ItemIsSelectable);
                          //this->setBoundingRegionGranularity(1.0); this has no effect
                      
                      }
                      
                          QPolygon net;
                          net << QPoint(67,202);
                          net << QPoint(120,202);
                          net<< QPoint(120,67);
                          net <<QPoint(320,67);
                          net <<QPoint(320,202);
                          net <<QPoint(520,202);
                          net <<QPoint(520,67);
                          MyPoly* _poly = new MyPoly();
                          _poly->DrawPolyline(net);
                      T Offline
                      T Offline
                      tushu
                      wrote on last edited by
                      #10

                      @mchinand Thank you for your reply.
                      I have a doubt :

                      1. QPolygon has many points ( in above example it has 7 points ) How the polygon gets drawn ? Segment by segment ? Means 1st 2 points are taken QPoint(67,202) and QPoint(120,202) and then line is drawn. Then next 2 points.
                      2. In shape() , how am I going to access all these points ?
                      1 Reply Last reply
                      0
                      • M Offline
                        M Offline
                        mchinand
                        wrote on last edited by mchinand
                        #11

                        I thought your code already worked for drawing, is that not the case? I thought you just needed to figure out how to use the same points that are used for drawing the polyline in the custom shape() method as well.

                        JonBJ T 2 Replies Last reply
                        1
                        • M mchinand

                          I thought your code already worked for drawing, is that not the case? I thought you just needed to figure out how to use the same points that are used for drawing the polyline in the custom shape() method as well.

                          JonBJ Offline
                          JonBJ Offline
                          JonB
                          wrote on last edited by
                          #12

                          @mchinand Yeah that's what I thought too....

                          1 Reply Last reply
                          0
                          • M mchinand

                            I thought your code already worked for drawing, is that not the case? I thought you just needed to figure out how to use the same points that are used for drawing the polyline in the custom shape() method as well.

                            T Offline
                            T Offline
                            tushu
                            wrote on last edited by tushu
                            #13

                            @mchinand Yes, my code is working for drawing. But all these concept ( QPolygon, QPainterPath, QPainterPathStroker, shape() , boundingRect() are new to me. ) I just learned how to extract points from QPolygon. Qt is new to me. I am learning from taking help from people like you.
                            Sorry if you get irritated. But this is how the inexperienced people learn.

                            P.S. Just few days ago I learned the concept behind paint() from JonB.

                            1 Reply Last reply
                            0
                            • JoeCFDJ Offline
                              JoeCFDJ Offline
                              JoeCFD
                              wrote on last edited by
                              #14

                              you may try to inherit QGraphicsPolygonItem and check some examples out.

                              1 Reply Last reply
                              0

                              • Login

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