1

I would like to have QML GridView with at the end of it a special element to add new items. So when the grid reflows that special element at the end reflows exactly like normal elements. I had it coded with a Flow, with inside a Repeater and after it, that special element and it worked great, but I can't get scrollbars with a Flow, so I moved to a GridView.

I tried the footer property of the GridView, but the footer appears under the grid, while I want it on the last row of the grid besides the other items.

To make it clear here is what I want:

[item1] [item2] [item3]
[item4] [ ADD ]

Also, the special element must have a different display an different action on click.

I would like the C++ side not to be aware of that special behaviour. If I must add an item at the end of the model, I would like it add it within the QML so that I don't taint the C++ with that implementation detail.

I tried this:

model: projects.push({name: '+'})

and also various types of append, but that didn't work.

Emmanuel Touzery
  • 9,008
  • 3
  • 65
  • 81
  • 1
    "but I can't get scrollbars with a Flow" --> Exploiting `ScrollView` or a `Flickable` as a container for the `Flow`should provide the scrollbars. Is it not a feasible option? – BaCaRoZzo Dec 20 '14 at 19:31
  • I think `ScrollView` works only on `Flickable` which as far as I understand are only `GridView` and `ListView`? I started looking a bit more into it now. Failed previously. – Emmanuel Touzery Dec 20 '14 at 19:42
  • The first effect I get when I add the `Flow` in add `ScrollView` is that the `Flow` flows only vertically. I remember previously I managed to get it to flow horizontally after some tweaking. But not to flow in two dimensions as it does without the `ScrollView`. – Emmanuel Touzery Dec 20 '14 at 19:46

2 Answers2

1

Glad to read that you solved the issue. After testing your code, I think you can achieve the same result in an easier way.

If you bind the Flow to the Item which contains the ScrollView, the Flow can grow horizontally and you got the vertical scrollbar as required. The working code:

import QtQuick 2.3
import QtQuick.Window 2.0
import QtQuick.Controls 1.2
// import QtQuick.Controls 1.3      // <--- requires Qt >= 5.4

Window {
    id: container
    width: 300
    height: 150
    visible: true

    ScrollView {
        anchors.fill: parent
        //horizontalScrollBarPolicy:  Qt.ScrollBarAlwaysOff  // <--- requires .Controls 1.3

        Flow {
            width: container.width       // width of ScrollView parent
            spacing: 10
            Text { text: "Text"; font.pixelSize: 40 }
            Text { text: "items"; font.pixelSize: 40 }
            Text { text: "flowing"; font.pixelSize: 40 }
            Text { text: "inside"; font.pixelSize: 40 }
            Text { text: "a"; font.pixelSize: 40 }
            Text { text: "Flow"; font.pixelSize: 40 }
            Text { text: "item"; font.pixelSize: 40 }
            Text { text: "yeah"; font.pixelSize: 40 }
            Text { text: "alright"; font.pixelSize: 40 }
            Text { text: "cool"; font.pixelSize: 40 }
            Text { text: "almost"; font.pixelSize: 40 }
            Text { text: "not"; font.pixelSize: 40 }
            Text { text: "epic"; font.pixelSize: 40 }
        }
    }
}

Here, with Qt < 5.4, you got the horizontal scrollbar since the vertical one covers part of the content space. Using controls 1.3 from Qt 5.4 (and the related commented code) solves the issue.


Another way to solve the problem is by using Flickable with custom scrollbars (see here). In this case the code would be:

import QtQuick 2.3
import QtQuick.Window 2.0
import QtQuick.Controls 1.2

Window {
    id: container
    width: 300
    height: 150
    visible: true

    Flickable {
        id: flick
        anchors.fill: parent
        contentHeight: flow.height    // grows according to the size of the Flow

        Flow {
            id: flow
            width: container.width
            spacing: 10
            Text { text: "Text"; font.pixelSize: 40 }
            Text { text: "items"; font.pixelSize: 40 }
            Text { text: "flowing"; font.pixelSize: 40 }
            Text { text: "inside"; font.pixelSize: 40 }
            Text { text: "a"; font.pixelSize: 40 }
            Text { text: "Flow"; font.pixelSize: 40 }
            Text { text: "item"; font.pixelSize: 40 }
            Text { text: "yeah"; font.pixelSize: 40 }
            Text { text: "alright"; font.pixelSize: 40 }
            Text { text: "cool"; font.pixelSize: 40 }
            Text { text: "almost"; font.pixelSize: 40 }
            Text { text: "not"; font.pixelSize: 40 }
            Text { text: "epic"; font.pixelSize: 40 }
        }
    }

    ScrollBar {                 // one of the scrollbars from the linked question
        flickable: flick
    }
}
Community
  • 1
  • 1
BaCaRoZzo
  • 7,502
  • 6
  • 51
  • 82
0

I managed to get scrollbars working based on a Flow as suggested by BaCaRoZzo.

However it's a bit complex scheme and I get QML warnings on stdout.

Here's how I did it:

ScrollView {
    anchors.fill: parent
    Flickable {
        contentWidth: parent.width
        contentHeight: flow.implicitHeight
        Flow {
            id: flow
            anchors.fill: parent
            ...
        }
    }
}

If I simply put the Flow in a ScrollView I get only one column in the flow.

This works as far as I can tell, however I get this warning on stdout:

QML Flickable: Binding loop detected for property "contentWidth"

I hope there's a simpler solution, but that's what I have for now...

EDIT: OK I got rid of the warning. I just set width: parent.width instead of contentWidth in the Flickable and it's ok, behaves well and no warnings. I guess I'll stick with that unless someone comes up with a nicer solution.

Emmanuel Touzery
  • 9,008
  • 3
  • 65
  • 81
  • Yeah, you shouldn't use `anchors.fill: parent` in a container that doesn't have a fixed size but rather tries to fit its content. – Stefan Fabian Oct 07 '20 at 12:50