Skip to content
  • 0 Votes
    12 Posts
    442 Views
    Pl45m4P

    @StudentScripter said in QGraphicsRectItem item translation instead of movement?:

    Well the real problem seems to be that rect().setTopLeft() and all other direct changes to the parentitems rect result in a changed Origin Point of the object in the scene, while with setScale() the OriginPoint stays intact.

    AFAIK the "topLeft" of an item rotated by 90° clockwise is still the same point as when not being transformed... the original item stays the same, because you can revert the transformation at any time to get your initial item back. The QTranform only "maps" the initial item matrix to your transformed one.
    So I think calling setTopLeft manually will mess up your item and the current transformation completely.

  • 0 Votes
    3 Posts
    207 Views
    S

    I tried to debug further but some things i get are just strange. I can't figure out why this happens:

    ORIG TOP LEFT 0 ORIG BOTTOM RIGHT QPointF(450,292) ORIG TOP LEFT 0 ORIG BOTTOM RIGHT QPointF(450,292) ORIG TOP LEFT 0 ORIG BOTTOM RIGHT QPointF(450,250) ORIG TOP LEFT nan ORIG BOTTOM RIGHT QPointF(450,250) ORIG TOP LEFT nan ORIG BOTTOM RIGHT QPointF(450,250) ORIG TOP LEFT nan ORIG BOTTOM RIGHT QPointF(450,250) ORIG TOP LEFT nan ORIG BOTTOM RIGHT QPointF(450,250) ORIG TOP LEFT nan ORIG BOTTOM RIGHT QPointF(450,250)

    Here is the code i get the debbug from:

    #include "handleitem.h" #include "resizablehandlerect.h" #include <QGraphicsSceneMouseEvent> #include <QDebug> #include "resizablepixmapitem.h" HandleItem::HandleItem(Position position) : handlePosition(position) { setFlag(QGraphicsItem::ItemIsMovable); } void HandleItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { ResizableHandleRect *rectItem = dynamic_cast<ResizableHandleRect *>(parentItem()); if (!rectItem) { return; // Wenn das Parent-Item kein ResizableHandleRect ist, beende die Funktion } QRectF boundingFrameRect = rectItem->selectorFrameBounds(); OriginTopLeft = mapToScene(boundingFrameRect.topLeft()); OriginBottomRight = mapToScene(boundingFrameRect.bottomRight()); QRectF SceneBoundingFrameRect(OriginTopLeft, OriginBottomRight); qDebug() << "ORIG TOP LEFT" << OriginLeftCenter << "ORIG BOTTOM RIGHT" << OriginBottomRight; OriginBottomCenter = SceneBoundingFrameRect.bottom(); OriginTopCenter = SceneBoundingFrameRect.top(); BottomCenterWasDragged = false; TopCenterWasDragged = false; } void HandleItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { ResizableHandleRect *rectItem = dynamic_cast<ResizableHandleRect *>(parentItem()); if (!rectItem) { return; // Wenn das Parent-Item kein ResizableHandleRect ist, beende die Funktion } QRectF boundingFrameRect = rectItem->selectorFrameBounds(); QPointF topLeft = mapToScene(boundingFrameRect.topLeft()); QPointF bottomRight = mapToScene(boundingFrameRect.bottomRight()); QRectF SceneBoundingFrameRect(topLeft, bottomRight); //qDebug() << "HandlePosition: " << handlePosition; switch (handlePosition) { case TopLeft: break; case TopCenter: SceneBoundingFrameRect.setTop(event->scenePos().y()); if(SceneBoundingFrameRect.bottom() < SceneBoundingFrameRect.top() && BottomCenterWasDragged == false){ qDebug() << "-- (2)SWITCH Top to Bottom"; handlePosition = BottomCenter; TopCenterWasDragged = true; } break; case TopRight: break; case RightCenter: break; case BottomRight: break; case BottomCenter: SceneBoundingFrameRect.setBottom(event->scenePos().y()); if(SceneBoundingFrameRect.bottom() < SceneBoundingFrameRect.top() && TopCenterWasDragged == false){ qDebug() << "(1)SWITCH Bottom to Top--"; handlePosition = TopCenter; BottomCenterWasDragged = true; } break; case BottomLeft: break; case LeftCenter: break; default: break; } if(SceneBoundingFrameRect.topLeft() != OriginTopLeft && BottomCenterWasDragged == true){ SceneBoundingFrameRect.setTopLeft(OriginTopLeft); BottomCenterWasDragged = false; qDebug() << "(1*)Correct Top, Bottom was Dragged!" << SceneBoundingFrameRect.topLeft(); } if(SceneBoundingFrameRect.bottomRight() != OriginBottomRight && TopCenterWasDragged == true){ SceneBoundingFrameRect.setBottomRight(OriginBottomRight); TopCenterWasDragged = false; qDebug() << "(2*)Correct Bottom, Top was Dragged!" << SceneBoundingFrameRect.bottomRight(); } QPointF topLeft2 = mapFromScene(SceneBoundingFrameRect.topLeft()); QPointF bottomRight2 = mapFromScene(SceneBoundingFrameRect.bottomRight()); QRectF NEWBoundingFrameRect2(topLeft2, bottomRight2); rectItem->setSelectorFrameBounds(NEWBoundingFrameRect2);
  • 0 Votes
    13 Posts
    856 Views
    S

    @Asperamanca Thanks thats a good call, gonna have a look at it. Thanks for the time and effort. <3 Gonna write again here if i encounter other questions regarding this. :D

  • 0 Votes
    11 Posts
    706 Views
    S

    @Pl45m4 Got i solved by just handling the selection in the mousepress and release event. However now im stuck with painting handles to resize the groupitem. I don't really know how to do that as qgraphicsgrouptitem has no setRect method.

    Here is my graphicsgroupitem;

    #include "resizablegraphicsgroupitem.h" #include "qpainter.h" #include <QPen> ResizableGraphicsGroupItem::ResizableGraphicsGroupItem() { // Initialisierungen hier, falls benötigt setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemSendsScenePositionChanges | QGraphicsItem::ItemSendsGeometryChanges); setOwnerItem(this); } QRectF ResizableGraphicsGroupItem::boundingRect() const { return childrenBoundingRect(); } void ResizableGraphicsGroupItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { qDebug() << "Test"; Q_UNUSED(option); Q_UNUSED(widget); painter->save(); //Malt eine Linie um das Rechteck painter->setPen(QPen(Qt::green)); painter->drawRect(boundingRect()); painter->restore(); }

    I coded such a handle class before, but i don't know how to get it to work with a qgraphicsgroupitem:

    #include "resizablehandlerect.h" #include <QGraphicsScene> #include <QDebug> #include <QCursor> ResizableHandleRect::ResizableHandleRect() { } ResizableHandleRect::~ResizableHandleRect() { } void ResizableHandleRect::drawHandles() { qDebug() << "ResizableHandleRect DrawHandles triggered!"; // Erstellen und Hinzufügen der Handles zur Szene //Populate handles in list if(handleList.count() == 0){ handleList.append(new HandleItem(HandleItem::TopLeft)); handleList.append(new HandleItem(HandleItem::TopCenter)); handleList.append(new HandleItem(HandleItem::TopRight)); handleList.append(new HandleItem(HandleItem::RightCenter)); handleList.append(new HandleItem(HandleItem::BottomRight)); handleList.append(new HandleItem(HandleItem::BottomCenter)); handleList.append(new HandleItem(HandleItem::BottomLeft)); handleList.append(new HandleItem(HandleItem::LeftCenter)); } //Set up pen QPen mPen; mPen.setWidth(2); mPen.setColor(Qt::black); //Top left handle QPointF topLeftCorner = selectorFrameBounds().topLeft() + QPointF(-8.0,-8.0); topLeftHandleRect = QRectF(topLeftCorner,QSize(8,8)); handleList[0]->setRect(topLeftHandleRect); if(!handleList.isEmpty() && (!handlesAddedToScene)){ handleList[0]->setPen(mPen); //handleList[0]->setBrush(QBrush(Qt::black)); ownerItem->scene()->addItem(handleList[0]); handleList[0]->setParentItem(ownerItem); handleList[0]->setCursor(Qt::SizeFDiagCursor); } //Top Center QPointF topCenterCorner = QPointF(selectorFrameBounds().left() + selectorFrameBounds().width() / 2.0 - 4.0, selectorFrameBounds().top()-4.0); topCenterHandleRect = QRectF(topCenterCorner,QSize(8,8)); handleList[1]->setRect(topCenterHandleRect); if(!handleList.isEmpty() && (!handlesAddedToScene)){ handleList[1]->setPen(mPen); //handleList[1]->setBrush(QBrush(Qt::gray)); ownerItem->scene()->addItem(handleList[1]); handleList[1]->setParentItem(ownerItem); handleList[1]->setCursor(Qt::SizeVerCursor); } //Top right QPointF topRightCorner = selectorFrameBounds().topRight() + QPointF(0,-8.0); topRightHandleRect = QRectF(topRightCorner,QSize(8,8)); handleList[2]->setRect(topRightHandleRect); if(!handleList.isEmpty() && (!handlesAddedToScene)){ handleList[2]->setPen(mPen); //handleList[1]->setBrush(QBrush(Qt::gray)); ownerItem->scene()->addItem(handleList[2]); handleList[2]->setParentItem(ownerItem); handleList[2]->setCursor(Qt::SizeBDiagCursor); } //Right Center QPointF rightCenterCorner = QPointF(selectorFrameBounds().right() - 4.0, selectorFrameBounds().top() + selectorFrameBounds().height() / 2.0 - 4.0); rightCenterHandleRect = QRectF(rightCenterCorner, QSize(8, 8)); handleList[3]->setRect(rightCenterHandleRect); if (!handleList.isEmpty() && (!handlesAddedToScene)) { handleList[3]->setPen(mPen); ownerItem->scene()->addItem(handleList[3]); handleList[3]->setParentItem(ownerItem); handleList[3]->setCursor(Qt::SizeHorCursor); } //Bottom right QPointF bottomRightCorner = selectorFrameBounds().bottomRight() + QPointF(0,0); bottomRightHandleRect = QRectF(bottomRightCorner,QSize(8,8)); handleList[4]->setRect(bottomRightHandleRect); if(!handleList.isEmpty() && (!handlesAddedToScene)){ handleList[4]->setPen(mPen); //handleList[2]->setBrush(QBrush(Qt::gray)); ownerItem->scene()->addItem(handleList[4]); handleList[4]->setParentItem(ownerItem); handleList[4]->setCursor(Qt::SizeFDiagCursor); } // Bottom Center QPointF bottomCenterCorner = QPointF(selectorFrameBounds().left() + selectorFrameBounds().width() / 2.0 - 4.0, selectorFrameBounds().bottom()-4.0); bottomCenterHandleRect = QRectF(bottomCenterCorner, QSize(8, 8)); handleList[5]->setRect(bottomCenterHandleRect); if (!handleList.isEmpty() && (!handlesAddedToScene)) { handleList[5]->setPen(mPen); ownerItem->scene()->addItem(handleList[5]); handleList[5]->setParentItem(ownerItem); handleList[5]->setCursor(Qt::SizeVerCursor); } //Bottom left QPointF bottomLeftCorner = selectorFrameBounds().bottomLeft() + QPointF(-8,0); bottomLeftHandleRect = QRectF(bottomLeftCorner,QSize(8,8)); handleList[6]->setRect(bottomLeftHandleRect); if(!handleList.isEmpty() && (!handlesAddedToScene)){ handleList[6]->setPen(mPen); //handleList[3]->setBrush(QBrush(Qt::gray)); ownerItem->scene()->addItem(handleList[6]); handleList[6]->setParentItem(ownerItem); handleList[6]->setCursor(Qt::SizeBDiagCursor); } // Left Center QPointF leftCenterCorner = QPointF(selectorFrameBounds().left() - 4.0, selectorFrameBounds().top() + selectorFrameBounds().height() / 2.0 - 4.0); leftCenterHandleRect = QRectF(leftCenterCorner, QSize(8, 8)); handleList[7]->setRect(leftCenterHandleRect); if (!handleList.isEmpty() && (!handlesAddedToScene)) { handleList[7]->setPen(mPen); ownerItem->scene()->addItem(handleList[7]); handleList[7]->setParentItem(ownerItem); handleList[7]->setCursor(Qt::SizeHorCursor); } handlesAddedToScene = true; } void ResizableHandleRect::setOwnerItem(QGraphicsItem *value) { ownerItem = value; } void ResizableHandleRect::drawHandlesIfNecessary(bool ShouldDrawHandles) { qDebug() << "DrawHandles" << ShouldDrawHandles << ownerItem->isSelected(); if(!ownerItem){ qWarning() << "ResizableHandleRect : No ownerItem set. Not drawing any\ handle. Please call setOwnerItem on your ResizableHandleRect subclass"; return; } if(ownerItem->isSelected() && ShouldDrawHandles == true){ drawHandles(); handlesAddedToScene = true; }else if(!ownerItem->isSelected() | (ShouldDrawHandles == false)){ //Remove the handles foreach (HandleItem * handleItem, handleList) { ownerItem->scene()->removeItem(handleItem); } qDeleteAll(handleList); handleList.clear(); handlesAddedToScene = false; } }
  • 0 Votes
    2 Posts
    221 Views
    Pl45m4P

    @StudentScripter

    Have you checked the QGraphicsLayout example already?

    https://doc.qt.io/qt-6/qtwidgets-graphicsview-basicgraphicslayouts-example.html
  • 0 Votes
    10 Posts
    817 Views
    A

    Hi,

    See if this provides some explanation (read the comments as well):

    StackOverflow: Qt6 QLabel / QPixmap excessive memory usage

  • 0 Votes
    5 Posts
    593 Views
    S

    @JonB thanks for googling :) . I have seen some more example. In case of GraphicsView fill transparent on scene did not help. I am pretty sure there is some way to do it, need to google more

  • 0 Votes
    4 Posts
    396 Views
    Pl45m4P

    Either I haven't figured out, what you are doing or it's complete nonsense (esp. the boundingRect)
    Maybe you can add the rest of your code and a screenshot of how your result looks.

    @ugo_ said in How to change cordinate sistem in QGraphicsItem:

    I want to plot my custom item inside a chart.

    Are you talking about QChart? So you have a QChart and want your item in your chart?!

  • 0 Votes
    3 Posts
    399 Views
    W

    @JonB Thanks for your reply! My goal is to draw a filled triangle like this:

    sample3.png

    The only way I'm able to achieve this that I draw two shapes: one fills the whole boundingRect() and a second one draws the outline in boundingRect() adjusted by the pen width.

    I'm not sure that it's a good way to solve this problem. Any tips?

  • 0 Votes
    6 Posts
    512 Views
    W

    @jsulm Thanks!

    @JonB I see, thanks for the clarification!

  • 0 Votes
    3 Posts
    690 Views
    T

    Hey, not sure if you found the solution yet. But you can try this:

    QGraphicsPixmapItem *pixmapItem = new QGraphicsPixmapItem; pixmapItem->setPixmap(QPixmap(":/images/pixmap.png")); _scene->addItem(pixmapItem); pixmapItem->setRotation(pixmapItem->rotation() + 45.0); QGraphicsRectItem *boundingRect = new QGraphicsRectItem(pixmapItem->sceneBoundingRect()); QPen outlinePen; outlinePen.setWidth(2); outlinePen.setColor(Qt::red); boundingRect->setPen(outlinePen); _scene->addItem(boundingRect);

    I believe what you want is the sceneBoundingRect() and not the boundingRect().

  • 0 Votes
    5 Posts
    556 Views
    JonBJ

    @Christian-Ehrlicher said in Collisions with custom QGraphicsItem that inherits from QObject:

    @JonB But it will behave exactly as his class wrt to the pointers:

    Absolutely true! Hence I said

    Apart from the answer @Christian-Ehrlicher has given to the question you ask.

    This is just a suggestion for if OP does want equivalent for the class CustomRect : public QObject, public QGraphicsItem. Not that it will change any behaviour wrt to pointers question.

  • 0 Votes
    5 Posts
    503 Views
    B

    @JonB You’re right, Thanks, QGraphicsItemGroup did the trick. I just needed to set the transform origin point to the centre of the red rectangle. Now the desired effect is achieved by this code:

    #include "game.h" #include <QGraphicsItemGroup> QGraphicsItemGroup* g = new QGraphicsItemGroup; Game::Game() { player = new QGraphicsRectItem(); rectItem = new QGraphicsRectItem(); m_view = new QGraphicsView(this); m_view->setSceneRect(QRectF(0,0,800,600)); this->setBackgroundBrush(Qt::black); m_view->setScene(this); m_view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); m_view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); m_view->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); m_view->setViewportUpdateMode(QGraphicsView::NoViewportUpdate); m_view->show(); player->setRect(0,0,100,100); player->setBrush(Qt::red); player->setPos(400,300); player->setFocus(); rectItem->setRect(0,0,100,100); rectItem->setBrush(Qt::green); rectItem->setPos(400,330); this->addItem(g); player->setZValue(10); rectItem->setZValue(1); g->addToGroup(player); g->addToGroup(rectItem); g->setTransformOriginPoint(player->pos().x() + player->boundingRect().width()/2 ,player->pos().y() + player->boundingRect().height()/2); } void Game::advance() { } void Game::keyPressEvent(QKeyEvent *event) { switch(event->key()) { case Qt::Key_Left : g->moveBy(-5,0); break; case Qt::Key_Right : g->moveBy(5,0); break; case Qt::Key_Up : g->moveBy(0,-5); break; case Qt::Key_Down : g->moveBy(0,5); break; case Qt::Key_Q : g->setRotation(g->rotation()- 3); break; case Qt::Key_W : g->setRotation(g->rotation() +3); break; } update(); }
  • 0 Votes
    34 Posts
    9k Views
    jeremy_kJ

    I guess I provided inadequate subtext for that example. It's documentation in a project I work on, explaining that qObject.signal.connect(lambda: anotherQObject.function(arg)) is unsafe in PyQt if anotherQObject might be destroyed before qObject. The same would happen in C++ with QObject::connect(qObject, &MyClass::signal, [&]() { anotherQObject->function(arg); });

    In C++, one possible solution is to use QObject::Connect(sender, signal, context object, functor). To the best of my knowledge In PyQt5, and I suspect in PySide2/Qt for Python, there is no equivalent. You can write one by taking the connection object returned by object.signal.connect() and using it in a slot connected to anotherQObject.destroyed.

  • 0 Votes
    8 Posts
    2k Views
    JonBJ

    @MegAmaNeo1
    In @jsulm's outline code you need a signal named pressed in CustomItem for connect(&item, CustomItem::pressed ..., and you also need an array/QVector of bool named pressed for pressed[i]. You'll presumably need to rename one of them. And where he writes void QGraphicsItem::mousePressEvent he means your void CustomItem::mousePressEvent override.

  • 0 Votes
    3 Posts
    783 Views
    Alex SUNPPA

    @SGaist yes, hovering will be okay too. I just didn't think that constant mouse tracking is such a problem.