Skip to content
  • 0 Votes
    5 Posts
    90 Views
    S

    @JonB Ok ok but back to the transforms i really get problems with the rectangle shifting when the "setOrigin" changes on the fly. So for example i scale with origin in topleft and scale afterwards with changed origin to topright the item is nudged slightly. I will prepare a minimal reproducable example, but maybe you have an idea just out of the description.

    Edit: And of course big thanks for taking the time.

  • 0 Votes
    1 Posts
    37 Views
    No one has replied
  • 0 Votes
    15 Posts
    395 Views
    KenAppleby 0K

    @StudentScripter

    Below is code that I can share. It's a complete example which perhaps does what you need. The void HandlesItem::paint() function is where the graphics transformations are done. It's rather long-winded but it at least shows what's required. It draws a painter path around the model items and deals with scaling and rotation of the model items as well as scaling of the graphics view.

    I'm sorry there is so much code: it's mostly the test framework. It uses mouse wheel events + modifiers to set the scale and rotation of items and the view.

    // main.cpp #include <QGraphicsRectItem> #include <QGraphicsRectItem> #include <QRandomGenerator> #include <QPainter> // A graphics path item that paints a selection graphic rectangle around a model item. class HandlesItem : public QGraphicsPathItem { public: HandlesItem(QGraphicsItem * modelItem, QGraphicsItem * parent =nullptr); void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget =nullptr) override; void setViewScale(double scale); protected: QGraphicsItem * mModelItem{ nullptr }; }; // A contentless graphics item that acts as a proxy for a model item and manages a HandlesItem for it. // The model item position must be set by setting the Proxy item position. // The model item scale and rotation must be set by the setItemScale() and setItemRotation() functions. // Model items and HandleItems are assumed to transform about their center points. class Proxy : public QGraphicsRectItem { public: Proxy(QGraphicsItem * modelItem, QGraphicsItem * parent =nullptr); void setSelected(bool selected); bool isSelected() const; void setItemRotation(double angle); void setItemScale(double scale); void setViewScale(double scale); // call to set the HandleItem's pen width according to the view scale. protected: QGraphicsItem * mModelItem{ nullptr }; HandlesItem * mHandlesItem{ nullptr }; bool mSelected{ false }; }; // -------------------------------------- HandlesItem::HandlesItem(QGraphicsItem * modelItem, QGraphicsItem * parent) : QGraphicsPathItem{ parent }, mModelItem{ modelItem } { setViewScale(1.0); setTransformOriginPoint(mModelItem->boundingRect().center()); } void HandlesItem::setViewScale(double scale) { QPen pen{ Qt::yellow }; pen.setWidthF(4.0/scale); setPen(pen); } void HandlesItem::paint(QPainter * painter, [[ maybe_unused ]] const QStyleOptionGraphicsItem * option, [[ maybe_unused ]] QWidget * widget) { const double scale{ mModelItem->scale() }; const double margin{ 8.0 / scale }; QRectF r{ mModelItem->boundingRect().adjusted(-margin, -margin, margin, margin) }; const QPointF tl{ r.topLeft() }, tr{ r.topRight() }, br{ r.bottomRight() }, bl{ r.bottomLeft() }; QTransform transform; transform.translate(r.center().x(), r.center().y()); transform.scale(mModelItem->scale(), mModelItem->scale()); transform.rotate(mModelItem->rotation()); transform.translate(-r.center().x(), -r.center().y()); const QPointF tlt{ transform.map(tl) }, trt{ transform.map(tr) }, brt{ transform.map(br) }, blt{ transform.map(bl) }; QPainterPath path; path.moveTo(tlt); path.lineTo(trt); path.lineTo(brt); path.lineTo(blt); path.lineTo(tlt); setPath(path); QGraphicsPathItem::paint(painter, option, widget); } Proxy::Proxy(QGraphicsItem * modelItem, QGraphicsItem * parent) : QGraphicsRectItem{ parent }, mModelItem{ modelItem } { mModelItem->setPos(0, 0); // the model item is positioned by the Proxy. mModelItem->setParentItem(this); setFlag(QGraphicsItem::ItemHasNoContents); mHandlesItem = new HandlesItem{ modelItem, this }; setSelected(false); } void Proxy::setSelected(bool selected) { mSelected = selected; mHandlesItem->setVisible(mSelected); update(); } bool Proxy::isSelected() const { return mSelected; } void Proxy::setItemRotation(double angle) { if (mModelItem) { mModelItem->setTransformOriginPoint(mModelItem->boundingRect().center()); mModelItem->setRotation(mModelItem->rotation() + angle); } } void Proxy::setItemScale(double scale) { if (mModelItem) { mModelItem->setTransformOriginPoint(mModelItem->boundingRect().center()); mModelItem->setScale(mModelItem->scale() * scale); } } void Proxy::setViewScale(double scale) { mHandlesItem->setViewScale(scale); } // The remaining code is a QGraphicsView and QGraphicsScene test framework for the above. #include <QGraphicsView> class GraphicsView : public QGraphicsView { public: GraphicsView(QWidget * parent); void initialise(QGraphicsScene& scene); protected: void mousePressEvent(QMouseEvent * event) override; void mouseMoveEvent(QMouseEvent * event) override; void mouseReleaseEvent(QMouseEvent *) override; void wheelEvent(QWheelEvent *) override; void setSelection(Proxy * item); void initialiseScene(); void setViewTransform(); QTransform makeTransform() const; QList<Proxy *> mItems; Proxy * mSelectedItem{ nullptr }; Proxy * mDragging{ nullptr }; QPointF mMoveScenePoint; double mScale{ 1.0 }; double mRotation{ 0.0 }; }; #include <QMainWindow> #include <QGraphicsScene> #include <QBoxLayout> class HandlesMainWindow : public QMainWindow { public: HandlesMainWindow(QWidget * parent =nullptr); protected: QGraphicsScene mScene; }; HandlesMainWindow::HandlesMainWindow(QWidget * parent) : QMainWindow(parent) { QWidget * centralwidget; QVBoxLayout * verticalLayout; GraphicsView * graphicsView; resize(532, 377); centralwidget = new QWidget(this); centralwidget->setObjectName("centralwidget"); verticalLayout = new QVBoxLayout(centralwidget); verticalLayout->setObjectName("verticalLayout"); graphicsView = new GraphicsView(centralwidget); graphicsView->setObjectName("graphicsView"); verticalLayout->addWidget(graphicsView); setCentralWidget(centralwidget); graphicsView->initialise(mScene); } #include <QMouseEvent> #include <QWheelEvent> namespace { QRandomGenerator& rng() { static QRandomGenerator sRng; return sRng; } QColor randomColor() { return QColor{ rng().bounded(64, 255), rng().bounded(64, 255), rng().bounded(64, 255) }; } QPointF randomPoint() { return QPointF{ 1.0*rng().bounded(20, 400), 1.0*rng().bounded(20, 400) }; } QRectF randomRect() { return QRectF{ 0.0, 0.0, 1.0*rng().bounded(20, 100), 1.0*rng().bounded(20, 100) }; } } GraphicsView::GraphicsView(QWidget * parent) : QGraphicsView{ parent } { setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setRenderHint(QPainter::Antialiasing); setTransformationAnchor(ViewportAnchor::NoAnchor); } void GraphicsView::initialise(QGraphicsScene& scene) { setScene(&scene); initialiseScene(); } void GraphicsView::mousePressEvent(QMouseEvent * event) { const QPoint p{ event->pos() }; QGraphicsItem * item{ itemAt(p) }; if (item) { mDragging = qgraphicsitem_cast<Proxy *>(item->parentItem()); mMoveScenePoint = mapToScene(p); } else { mDragging = nullptr; } } void GraphicsView::mouseMoveEvent(QMouseEvent * event) { const QPoint p{ event->pos() }; if (mDragging) { const QPointF sp{ mapToScene(p) }; mDragging->moveBy(sp.x() - mMoveScenePoint.x(), sp.y() - mMoveScenePoint.y()); mMoveScenePoint = sp; } } void GraphicsView::mouseReleaseEvent(QMouseEvent * event) { mDragging = nullptr; const QPoint p{ event->pos() }; QGraphicsItem * item{ itemAt(p) }; if (item) { setSelection(qgraphicsitem_cast<Proxy *>(item->parentItem())); } else { setSelection(nullptr); } } void GraphicsView::wheelEvent(QWheelEvent * event) { if (event->modifiers() == Qt::NoModifier) { double deltaScale{ 1.0 }; QPoint p = event->angleDelta(); if (p.y() > 0) { deltaScale = 1.1; } else if (p.y() < 0) { deltaScale = 1.0/1.1; } event->accept(); if (mSelectedItem) { mSelectedItem->setItemScale(deltaScale); } else { mScale = mScale * deltaScale; setViewTransform(); } } else if (event->modifiers() == Qt::ControlModifier){ QPoint p = event->angleDelta(); double rotation{ 0.0 }; if (p.y() > 0) { rotation = 2.0; } else if (p.y() < 0) { rotation = -2.0; } event->accept(); if (mSelectedItem) { mSelectedItem->setItemRotation(rotation); } else { mRotation += rotation; setViewTransform(); } } } void GraphicsView::setSelection(Proxy * item) { mSelectedItem = item; if (item) { item->setSelected(true); } for (auto i : mItems) { if (not (i == item)) { i->setSelected(false); } } } void GraphicsView::setViewTransform() { setTransform(makeTransform()); for (auto i : mItems) { i->setViewScale(mScale); } } QTransform GraphicsView::makeTransform() const { QTransform result; const QPointF center{ rect().center() }; result.translate(center.x(), center.y()); result.scale(mScale, mScale); result.rotate(mRotation); result.translate(-center.x(), -center.y()); return result; } void GraphicsView::initialiseScene() { scene()->setBackgroundBrush(QBrush{ Qt::cyan }); for (int i = 0; i < 20; i++) { QGraphicsRectItem * item{ new QGraphicsRectItem(::randomRect()) }; item->setBrush(QBrush{ ::randomColor() }); Proxy * proxy{ new Proxy{ item } }; proxy->setPos(::randomPoint()); scene()->addItem(proxy); mItems << proxy; } } #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); HandlesMainWindow w; w.show(); return a.exec(); }
  • 0 Votes
    33 Posts
    3k Views
    A

    for the one interested in this topic, I updated the code on gitHub and now is possible to edit the model and save the changes within the listView with the help of a specialized QStyledItemDelegate.
    link: https://github.com/aVenturelli-qt/CommentsListView

    In the README there are all the information needed for the setUp and run

  • 0 Votes
    12 Posts
    521 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
    5 Posts
    213 Views
    Pl45m4P

    @Axel-Spoerl said in QWidget Drag And Drop inside Layout. Is this a good way?:

    I have troubles to imagine what you mean by that. Colors aside, a widget is typically a rectangle. If I want to indicate a potential landing spot, I'd rather use a rectangle, than a line.

    I think @StudentScripter means the same behavior you see when adding widgets to a layout in QtDesigner.

    A "line" can be a thin rectangle :)

    You also see a rectangle when dragging QDockWidgets around showing the valid DockAreas.

    Maybe check the source code of QtCreator's Designer or QMainWindows dockarea.

  • 0 Votes
    3 Posts
    184 Views
    C

    I forgot to mentioned this ,I am Using TextInputUnit as component ,
    here is the TextInputUnit.qml , i have added the Font.AllUppercase
    TextInput {
    id: textInput
    text: value
    focus: true
    anchors.top: parent.top
    anchors.left: parent.left
    anchors.bottom: parent.bottom
    anchors.leftMargin: 10
    anchors.right: unitsRect.left
    verticalAlignment: Text.AlignVCenter
    color: '#EBF4FF'
    font.family: 'Lato'
    font.pixelSize: 16
    font.capitalization: Font.AllUppercase

    selectByMouse: true

    // validator: validatorIn
    onEditingFinished: {
    root.textChanged()
    }
    readOnly: readonly
    }

    but still its not working . What will be the issue

  • 0 Votes
    14 Posts
    540 Views
    JonBJ

    @jeremy_k said in Console App how to populate a 10.000*10.000 Grid efficiently?:

    A easy optimization for setting a quadrant or an entire 2d space as a single color is to remove all subtrees of that tree,

    Absolutely. If that's the sort of thing you want to do. Doesn't seem to relate to toggling the state of 100,000 adjacent bits in 5 million.

    it stores all squares that shall be changed in a vector.
    The squares changed can be anywhere in this big map,
    eventually reaching many millions of squares needed to be changed at onces.

    If that is what you need to do, again I'm not sure I see any use of these quadtrees. But only you need the exact situation.

  • 0 Votes
    5 Posts
    273 Views
    mrdebugM

    Hi, if you have to straming audio and video files you could use live555 on server side and, client side, only QMediaPlayer using rtsp.

  • 0 Votes
    4 Posts
    242 Views
    S

    bumping this up. Anyone can hint me how to mass paint controls?

  • 0 Votes
    3 Posts
    228 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
    22 Posts
    2k Views
    AdithyaA

    Thanks guys it worked. python3 and readyReadStandardOutput(showed the log ,was expecting it to work like qDebig() and cout .My bad) . Sorry for bothering with wrong misconception.

  • 0 Votes
    5 Posts
    437 Views
    S

    @Pl45m4 Well thank you very much that does the job! Is there any way to make these menu items background heigher without changing the font size.

    EDIT:
    QMenuBar{
    min-height: 20px;
    }

  • 0 Votes
    5 Posts
    261 Views
    Pl45m4P

    @StudentScripter

    This example shows how a use case could look like

    https://doc.qt.io/qt-6/qtwidgets-graphicsview-basicgraphicslayouts-example.html

    But as you can see, the custom items inherit from QGraphicsLayoutItem and QGraphicsItem.
    So to properly use a QGraphicsItem in a layout, you have to inherit QGraphicsLayoutItem or use QGraphicsWidget directly... however I don't know how it fits in your existing logic/structure. It might break something... using layouts and "moving free / free resizable by user" is kinda counterproductive.

  • 0 Votes
    8 Posts
    381 Views
    S

    @Pl45m4 @SGaist Ok well i got is removed by setting the titlebar widget to fixed height of 1 and background transparent. This way it retains its dockability.

  • 0 Votes
    3 Posts
    289 Views
    JonBJ

    @StudentScripter
    You can put pointers to widgets into arrays/lists/maps as you please and use those for iterating through them etc.

    You can't get Designer to do that for you, so you have to manually populate the arrays/lists from the ui->... instance variables yourself (after setupUi()).

    You can also visit all widgets of a given type, without setting anything up, via topWidget->findChildren<QLineEdit *>().

    You can "group" widgets at design-time by e.g. creating a "holding" container QWidget or QFrame or QGroupBox if that helps. For buttons there is also QButtonGroup.

  • 0 Votes
    18 Posts
    695 Views
    S

    @StudentScripter said in Save Programm Settings internally + how to organize with folders?:

    QString filePath = "/path/to/your/settings.ini";

    If you want to use an ini file, please use QStandardPath with ConfigLocation and don't invent your own place where to put the ini file.