Equivalent to QGraphicsView and QGraphicsScene?
-
Hello people, I'm trying to create a QML desktop app based on an existing app built with Widgets. It is a dashboard-like app where you can drag and place "tiles" of different functions freely on a whiteboard. The general hierarchy was something like this: QGraphicsView<-QGraphicsScene<-QGraphicsRectItem<-QWidget
I'm new to QML and have done a little bit of searching around, but I haven't got a good idea as to how, or if it's possible, to implement this in QML. It'd be very helpful if you could point me to some specific Items that can be used here. Thanks in advance.
If it helps to visualize what I'm trying to build, here is a simple sketch:
-
Hi @SWMCODER, and welcome!
I suggest you start by opening Qt Creator's "Examples" pane and searching for Qt Quick Examples - Drag and Drop. Build it, run it, and try it out.
-
@JoeCFD I use QML Canvas to draw some basic shapes. Not sure if it is good enough for you.
For complicated geometries, you may need
https://doc.qt.io/qt-6/qtquick-visualcanvas-scenegraph.htmlBut the license of this module is GPL, not LGPL.
https://doc.qt.io/qt-6/qtgraphs-index.html#licenses-and-attributions -
Basically, you can prepare a set of QML files (e.g. for basic shapes), and load them dynamically from C++ using something like
QQmlComponent component(engine, fileName); QVariantMap propertyMap; // Here you can add properties to the map that you want to set to the newly created component, e.g. a position QQuickItem* pItem = dynamic_cast<QQuickItem*>(component.createWithInitialProperties(propertyMap)); // Add to the correct parent, which is e.g. your QML root item
Note: This is probably not the idiomatic QML way of doing things, because it means you manage your scene from C++. It's a very flexible way though.
A potentially simpler way is this:
- Choose a set of basic primitives (Rectangle, Ellipse, Polyline, ...)
- Create a model for each primitive (list model should be fine) - you can do this in C++ or in QML
- Create a Repeater for each model - it will display all the items currently in the model
- Adding a new item to a model will automatically display it
- Make sure you can set important properties via model - position, size, color,...
-
Using a single c++ model with a Repeater + DelegateChooser would be the idomatic and simpler way.
-
In general, I see little benefit by hosting a widget application (with CPU rendering) in a QML wrapper.
If you want to experience the power of Qt Quick / Quick controls, better refactor the application and benefit from GPU rendering boosting your drag & drop stuff. If that's too much / not necessary: Why not stay in widgets? -
Hi @SWMCODER, and welcome!
I suggest you start by opening Qt Creator's "Examples" pane and searching for Qt Quick Examples - Drag and Drop. Build it, run it, and try it out.
Thanks to y'all who replied. @JoeCFD @Asperamanca @GrecKo @Axel-Spoerl
@JKSH
I had looked at the Drag and Drop examples but they used the DropArea type which didn't fit my need because it wouldn't allow me to place the tiles freely in a shared plane, or at least that's my understanding.With the help of AI tools (which I've found extremely useful in fast prototyping a project, especially in a framework that I'm not familiar with like in this case QML), I've created exactly what I needed with basic Qt Quick Items. Here's the basic structure:
Window { // button to add a new tile Button { onClicked: { tileComponent.createObject(dashboardArea, { "x": /* x position in dashboard area */, "y": /* y position in dashboard area */, "tile specific properties": data }); } } // dashboard area Item { id: dashboardArea // this component holds dynamically created tiles Component { id: tileComponent Tile {} } } } // Tile.qml Rectangle { // tile specific properties ... // Make the tile draggable MouseArea {} }