Delegate QML Class Access Model Properties

I have a TableView for which I have defined my own itemDelegate. Now from this delegate, I can access the value for the column using styleData.value, but I will also need to access the other properties in the same element, but I cannot find how to do this.

I need this because the style of the text must change depending on another property of the element model.

Any ideas? thanks!

+6
source share
3 answers

Some documentation is missing. Inside the element delegate, you can access the following (taken from the source code of TreeView.qml ):

  • styleData ( see documentation )
  • model (not currently registered)
  • modelData (not currently registered, not sure about this, but I think it looks like a ListView )

(By the way, what is missing in the documentation, but useful is styleData.role . In addition, the documentation of other delegates also lacks some of the available properties, it is best to look at the source code of the QML file and look at the Loader element that creates the instance of your delegate. As a plus you will learn how this creepy stuff works.))

With model and column / column information, you can go to element data. This code depends on the type of model.

If you use QML ListModel , you can use model.get : model.get(styleData.row)[styleData.role] should work (unchecked since I use it rarely, please report it).

If you use C ++ QAbstractItemModel or friends, it is best to add a slot to the model class, which accepts only the row and role name, since the information the TableView works with (as well as role numbers and columns ...).

However, in both cases, you should not use the expression in a property binding! The notification system will not work, since you are not using the property system to access data. On your question, I think you wanted to use it in a binding expression. I do not know how to listen to changes in the model manually.

An alternative approach is to access other elements of the line and provide their property there. Some tips:

  • From one element, you can access other elements of the same line by double-walking through the tree of objects (first to the loader that creates an instance of your component, and then to the actual line), and then twice down (first, the specific child object that is the loader, and then its instance of the object). You need to know the column number you want to get (not the role name), I assume that you want to access the first column (index 0):

     parent.parent.children[0].item 
  • You can provide model data using the property in each element. Assuming a simple text element, this could be:

     Text { property variant value: styleData.value // <-- Here you make it available // your other stuff } 

Combining them may look as follows. In this example, I assume that the first row contains an integer, and if it is zero, the second column should be red.

 // (within TableView) itemDelegate: Text { property variant value: styleData.value text: styleData.value color: (styleData.column == 1 && parent.parent.children[0].item.value === 0) "red" : "black" } 
+12
source

It seems to me that it is quite easy if you read the source code of TableViewItemDelegateLoader.qml (this is private code in qtquickcontrol )
To access any role you use, use: model[your_role_name] .

For exp: model["comment"]

+3
source

Faced with the same problem today, this is the result of my research (Qt 5.2.x)

If you have a hard limit for TableView, there is only one correct solution - use model.get(styleData.row)["roleForStyling"] , as @leemes wrote. But it will be very slow if you have a large amount of data in the model and use, for example, proxy models for sorting / filtering.

The direct solution from @leemes answer is great, but in the general case it doesn’t work, because in TableView any Item wrapped in Loader and therefore does not depend on parent and other elements:

  • When an element is created (where you want to change the text style) another element (from which to obtain an identity card) cannot be created
  • You may not have a parent when creating the element (i.e. the binding will be broken)

In my case, the best solution for deep customization was to create a simple wrapper for the ListView . In this case, you have access to the full row data in the delegate with no overhead. Highlights for creating a component ("My own ListView as table"):

  • Create a standalone title ( Rectangle or Item ) - do not use the ListView title form. This makes it corrected for any amount of data.
  • Wrap ListView in ScrollView (if you need scrollbars)
  • Use the Clip: true property in the list to make the correct
  • Set highlight style and set highlightFollowsCurrentItem:true in ListView

As a bonus in the future, this can be used to create a "TreeTable" :)

+1
source

All Articles