Make a custom view for data model or possible use ListView+Canvas?
-
Hi! I have C++ QAbstractItemModel with array of doubles(16 or 32 points)
I need to show this data as mouse editable graph. User moves each poin up and down and edits the graph, updating the model.Now i end up with ListView + delegates representing moveble rectangles(using mouseArea in delegate) and updating of model data seems do be ok. At least it works with ListModel as a data source.
Also i need to connect each dot by lines to draw a graph, so i put Canvas on top of ListView, manually iterate over model's data and draw the lines. This part also works...BUT now i need to draw background grid... Canvas draws on top of ListView and delegates.
As you can see on the screenshot - lines are dwarn on top of the text. It is also on top of rectangles, but we can't see this because color is the same.
SscreenshotSo may be i need completely custom view?
Ok, experiment 1: use text as view for row:0 col:0Text{ x: 220 height: 10 width: 100 text: cppmodel.data(cppmodel.index(0,0), 0x0100+1) }
See this ugly 0x0100+1?
This is because data() want's role as integer and there is enum in my model:enum DMRoles { DataRole = Qt::UserRole + 1, };
So second question is how to resolve role name to int in QML?
My model has roleNames() func, but it's not callable from QML.QHash<int, QByteArray> ArrayDataModel::roleNames() const { QHash<int, QByteArray> roles; roles[DataRole] = "data"; return roles; }
How ListView works then? ListView allows me to use model.data in delegate and everything is ok.
I need a good advice of what to do next...
And may be something about how to implement custom view completely from scratch.. May be in C++? View must be usable from QML. -
BUT now i need to draw background grid... Canvas draws on top of ListView and delegates.
Perhaps you should try setting
z
value higher for the one that you require on top.So may be i need completely custom view?
Canvas
too should work. You can also use a custom QQuickPaintedItem derived class which will update on model changes. Just use signal-slot mechanism. Check this example for how to create, register and use it from QML.See this ugly 0x0100+1?
This is because data() want's role as integer and there is enum in my model:
So second question is how to resolve role name to int in QML?
My model has roleNames() func, but it's not callable from QML.Check this post. Model is the same
QAbstractItemModel
. -
You can also use a custom QQuickPaintedItem derived class which will update on model changes
Thank you, this is exactly what i want!
Check this post. Model is the same QAbstractItemModel.
Ok, additional Q_INVOKABLE method was added to the model, this should work.
But interesting fact: somehow ListView doing it without additional method. -
@sigmaN AFAIK there is no ready-made method for it. You can try digging up the source and particularly the delegate part of it only in which these roles are available.
Apart from that there is another way to access the data. Iterating through the children ofListView
'scontentItem
as all the items (delegate too) declared insideListView
are parented to it. But IMO it is not a recommended way.