Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Update: Forum Guidelines & Code of Conduct


    Qt World Summit: Early-Bird Tickets

    Unsolved QGraphicsScene: moving an item inside an item

    General and Desktop
    4
    8
    186
    Loading More Posts
    • 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.
    • LeoC
      LeoC last edited by

      Hey,

      since I already have some experience using Qt, it is the first time I try using some graphic elements.

      To get a first impression how it works I watched a YouTube video. I did what he says and it works fine.
      I created a QGraphicsScene where I placed a box which is movable and as long as I click on it the colour is changed. "oneBox" inherits from QGraphicsItem.

      oneBox::oneBox()
      {
          bPressed = false;
          setFlag(ItemIsMovable);
      }
      
      QRectF oneBox::boundingRect() const
      {
          return QRectF(0,0,200,200);
      }
      
      void oneBox::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
      {
          QRectF rec = boundingRect();
      
          if(bPressed) {
              brush.setColor(Qt::red);
          }
          else {
              brush.setColor(Qt::green);
          }
      
          painter->fillRect(rec,brush);
          painter->drawRect(rec);
      }
      
      void oneBox::mousePressEvent(QGraphicsSceneMouseEvent *event)
      {
          bPressed = true;
          update();
          QGraphicsItem::mousePressEvent(event);
      }
      
      void oneBox::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
      {
          bPressed = false;
          update();
          QGraphicsItem::mouseReleaseEvent(event);
      }
      

      Now, what I want to have is a horizontal line that divides this box in an upper and a lower part. The user can move the line up and down in order the change the size of the upper and the lower part. So, the line should be movable but only in y - direction. The lower part should have another colour than the upper one.

      I guess I need a qgraphicslineitem. But I am not sure where to place it.
      When I create a new class which lives parallel to "oneBox" I could add the line to the same scene as the "oneBox". But then I can move the line also outside of the box. That should not be the case.
      Then I thought I could create a new QGraphicsScene inside "oneBox" which has the same size as the boundingRect. In this case the line would be only movable inside the "oneBox". But I am not sure if the new GraphicsScene then lies on top of the "oneBox" so I cannot grab the "oneBox" anymore to move it around.

      I really hope you got what I mean and you can tell me what I have to do.

      Cheers
      Chris

      JonB Pl45m4 2 Replies Last reply Reply Quote 0
      • JonB
        JonB @LeoC last edited by

        @LeoC
        I don't think you want anything like "multiple graphics scenes". I'm not sure whether an extra graphics item is the best way to do your dividing line, someone will probably tell you to do it in drawing the box item. But if you do want to do it via a separate item, did you try making that line a child of the box item? This is only a guess, but I would have thought that would be how you would do one graphics item living on top of another?

        1 Reply Last reply Reply Quote 1
        • Pl45m4
          Pl45m4 @LeoC last edited by Pl45m4

          @LeoC

          The short form is:

          • create a line item (QGraphicsLineItem)
          • add it to your box (box becomes parent) and make it moveable.
          • control the movement and the position to re-paint the box below and above that line

          I can give you an example later. Just try it yourself first, based on this information :)


          If debugging is the process of removing software bugs, then programming must be the process of putting them in.

          ~E. W. Dijkstra

          1 Reply Last reply Reply Quote 2
          • M
            mchinand last edited by

            In addition to what Pl45m4 outlined, you may need to reimplement the itemChange() method to limit the movement of the line to horizontal movements.

            1 Reply Last reply Reply Quote 1
            • Pl45m4
              Pl45m4 last edited by Pl45m4

              I didnt limit the movement of the handle in X-direction but that should not be a problem to add later.

              BoxHandle.gif

              #ifndef BOXHANDLE_H
              #define BOXHANDLE_H
              
              #include <QGraphicsLineItem>
              
              class BoxHandle: public QGraphicsLineItem
              {
              public:
              
                  BoxHandle();
                  BoxHandle(qreal x1, qreal y1, qreal x2, qreal y2, QGraphicsItem *parent = nullptr);
              
              protected:
              
                  void mousePressEvent(QGraphicsSceneMouseEvent *event);
                  void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
                  void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
              
              };
              
              #endif // BOXHANDLE_H
              
              
              #include "boxhandle.h"
              
              #include <QDebug>
              #include <QPen>
              BoxHandle::BoxHandle():
                  QGraphicsLineItem()
              {}
              
              BoxHandle::BoxHandle(qreal x1, qreal y1, qreal x2, qreal y2, QGraphicsItem *parent):
                  QGraphicsLineItem(x1, y1, x2, y2, parent)
              {
                  setFlag(ItemIsMovable);
                  QPen pen(Qt::red, 5);
                  setPen(pen);
              }
              
              void BoxHandle::mousePressEvent(QGraphicsSceneMouseEvent *event)
              {
                  QGraphicsItem::mousePressEvent(event);
              }
              
              void BoxHandle::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
              {
                  QGraphicsItem::mouseReleaseEvent(event);
              }
              
              void BoxHandle::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
              {
                  QGraphicsItem::mouseMoveEvent(event);
              }
              
              
              #ifndef MYBOX_H
              #define MYBOX_H
              #include <QGraphicsItem>
              #include <boxhandle.h>
              
              class MyBox: public QGraphicsItem
              {
              public:
                  MyBox();
              
                  QRectF boundingRect() const;
              
                  void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
              
              protected:
              
                  void mousePressEvent(QGraphicsSceneMouseEvent *event);
                  void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
              
              
              private:
              
                  bool pressed;
                  BoxHandle *handle;
              };
              
              #endif // MYBOX_H
              
              #include "mybox.h"
              #include <QBrush>
              #include <QPainter>
              #include <QDebug>
              #include <QGraphicsSceneMouseEvent>
              
              MyBox::MyBox():
                  QGraphicsItem(), pressed(false), handle(new BoxHandle(0, 0, 200, 0, this))
                // HandleSize = BoxWidth, probably requires some adjustment later
              {
                  setFlag(ItemIsMovable);
              }
              
              QRectF MyBox::boundingRect() const
              {
                  return QRectF(0, 0, 200, 200);
              }
              
              void MyBox::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
              {
                  QRectF rec = boundingRect();
              
                  // Get Handle Pos
                  qreal handlePosY = handle->mapToParent(0, 0).y();
              
                  // Rect below handle
                  QRectF below = QRectF(0, handlePosY, boundingRect().width(), boundingRect().height() - handlePosY);
              
              
                  painter->fillRect(below, Qt::green);
              
                  // Rect above handle
                  QRectF above = QRectF(0, 0, boundingRect().width(), boundingRect().height() - (boundingRect().height() - handlePosY));
              
              
                  painter->fillRect(above, Qt::blue);
                  painter->drawRect(rec);
              }
              
              void MyBox::mousePressEvent(QGraphicsSceneMouseEvent *event)
              {
                  pressed = true;
                  update();
                  QGraphicsItem::mousePressEvent(event);
              }
              
              void MyBox::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
              {
                  pressed = false;
                  update();
                  QGraphicsItem::mouseReleaseEvent(event);
              }
              
              

              Also I skipped the itemChange part... Dont want to do all of your work :)
              And there are probably better solutions than doing all the stuff in paint event (I guess?!)

              Btw: The "artifacts" near the border of the box are not really there. They are only visible in the recorded gif.


              If debugging is the process of removing software bugs, then programming must be the process of putting them in.

              ~E. W. Dijkstra

              1 Reply Last reply Reply Quote 4
              • LeoC
                LeoC last edited by

                @Pl45m4 thanks!

                Your little animation is exactly what I wanted to achieve.
                Unfortunately I couldn't try it by myself so far but I will do as soon as I can.

                1 Reply Last reply Reply Quote 0
                • LeoC
                  LeoC last edited by

                  @Pl45m4 now I implemented everything as you suggested and it works. Thank you for your support. It would have took me days to figure this out.

                  I also added the following to BoxHandle

                  void oneBoxHandle::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
                  {
                      QGraphicsItem::mouseMoveEvent(event);
                  
                      setPos(0, y());
                  
                      if(y() < 0)
                          setPos(x(),0);
                      if(y() > rectY)
                          setPos(x(),rectY);
                  }
                  

                  and now the red line only moves in y direction inside the box.

                  So in the end it looks like it should. Now I can create everything else around it.

                  btw: the artifacts are also visible on my screen. So it is not a matter of the gif :)

                  Pl45m4 1 Reply Last reply Reply Quote 0
                  • Pl45m4
                    Pl45m4 @LeoC last edited by

                    @LeoC said in QGraphicsScene: moving an item inside an item:

                    So it is not a matter of the gif :)

                    They were not visible when I ran the program. Only after recording.


                    If debugging is the process of removing software bugs, then programming must be the process of putting them in.

                    ~E. W. Dijkstra

                    1 Reply Last reply Reply Quote 0
                    • First post
                      Last post