Important: Please read the Qt Code of Conduct -

Issue with TextField in ListView delegate

  • I have implemented a 'property table' using ListView, with a TextField in the delegate implementation for value input. The idea is that a value should be committed on pressing enter or on the text field losing focus. To this end, I am using an onEditingFinished handler in the TextField.

    I am relying on the index property in the delegate to tell me which item in the table has been edited. That is needed to allow me to make an appropriate commit to my underlying model.

    The issue I am seeing is that in some circumstances, when the text field loses focus and onEditingFinished is triggered, the index is -1. This means that although I might know that the value has changed and that it needs to be committed, I don't have the information about which item it actually is.

    Whether this happens seems to depend on exactly where in the application focus goes to. For example, the property table is below a tree and if I click on a tree branch the problem does not seem to happen. On the other hand if I click on another list that in a part of the application that is 'further away', it does happen.

    Because this is happening in a relatively complex scenario, it is quite difficult to narrow it down to a simple example. For now, I wondered if anyone recognised the behaviour where the index can be -1 in a ListView delegate or if anyone thought what I am trying to do is fundamentally wrong for some reason.

    I am wondering about using the textEdited signal. I do not want to commit on every single edit as this would be too expensive. However I could use textEdited to store a 'pending' value together with the index (which I assume would be valid in that signal handler). Then I could submit the pending value in onEditingFinished, ignoring the fact that index might be invalid at that point.

  • Moderators

    Add a readonly property in your delegate, like this:

    YourDelegate {
      readonly property int row: index

    And use this in your onEditingFinished handler. It should contain the original value from when the delegate was created.

  • @sierdzio Thanks for the suggestion. I thought that would solve it but unfortunately not. The original index is reported as -1 in onEditingFinished.

    One detail which I unfortunately omitted was that, because I have different types of property in my table and it needs to be initialised dynamically from data, I am using a Loader as a 'delegate factory' . The delegates themselves are defined as Components such as:

        // delegate for integer type property
        Component {
            id: intFieldDelegate
            MyTextField {
                validator: IntValidator{}

    One consequence of this is that I don't have direct access to index etc in my delegate and have to introduce an intermediate property, index_ say, in my Loader (this is described at the end of the Detailed Description for Loader in the Qt documentation).

    I have tried introducing a readonly property, as suggested, at various levels - in the Loader, in the Component instantiation above, in the implementation file for MyTextField but all with the same result.

  • Moderators

    Weird. I had a very similar case recently and this trick with property worked fine.

    There is one other possibility - do not bind the new index property, but assign it. So, do this:

    MyTextField {
      property int row: -1
      Component.onCompleted: row = index

    Since you are adding itermediate property in Loader, you can actually do it there, when sourceComponent is changed.

    This way the row is assigned only once. Even if index changes to -1, row will not be updated - so it should work as you intend it to.

  • @sierdzio Sorry for delayed response to your suggestion - I was pulled onto other things for a while. Now that I have come back to it a bit more fresh I see that there was something specific happening in my application which probably explains why your solution did not work for me. As I mentioned in my first post, the issue depended on where I clicked in the application. I realise now that it was a result of that click (on an item in another ListView) in turn affecting the current selection in the tree. This then reset the model being shown in the property view. What was a bit surprising to me was that the focus out (onEditingFinished) of my text field happens quite late, after all of this other stuff. Anyway I have found a way to deal with it, along the lines that I was originally thinking about, making more use of onTextEdited.

    Having said all that, like you, I have definitely seen a more general issue of losing the index value in the past and I suspect your first suggestion would have worked in that case so thank you for taking the time to suggest it.

Log in to reply