need ideas on styling a ListView
-
Hi all -
The customer wants a bunch of displays that will look like this:
Note the rounded corners to the first and last rectangle - the right corner would be rounded too.
At first glance, it seemed easy enough to do, but that was before I realized you couldn't set individual corner radiuses (radii) on Rectangles.
Is there some easy way to do this that I'm overlooking?
Thanks...
-
@jeremy_k interesting idea. I was thinking along similar lines (though kind of backwards) -- put a rectangle behind the list, and color the Rectangle the desired color of the list entries. Then each list entry would be a transparent rectangle (with all the stuff I need to put into it). The only problem here is -- can I change the color of the spacing between the items?
Thanks...
-
I had presumed that this was an item view, for no apparent reason.
If there's no scrolling, putting the Rectangle behind sounds fine. Transparent items with Rectangles to draw the dividers could work. A LineShape is another option. It might be easier to use an Image background for everything but the text.
-
@jeremy_k said in need ideas on styling a ListView:
I had presumed that this was an item view, for no apparent reason.
That's correct. The idea was to put the ListView within the Rectangle.
I'm still new to using ListView, so this idea may be untenable.
-
@mzimmers said in need ideas on styling a ListView:
@jeremy_k said in need ideas on styling a ListView:
I had presumed that this was an item view, for no apparent reason.
That's correct. The idea was to put the ListView within the Rectangle.
I'm still new to using ListView, so this idea may be untenable.
I don't think so, but it may be overkill. Will there always be the same 4 fields, and does adding the compexity of an item model make sense? I have encountered deployed products that had list views for data which all fit in on screen. How did I know? Someone forgot to set Flickable.boundsBehavior or the equivalent in other frameworks to Flickable.StopAtBounds.
Another idea is to draw the rounded corned via an Image or Canvas in the delegate that is hidden if index !== 0 and index !== count -1.
-
@jeremy_k no, it won't always be the same number of items in the list, nor will all lists be composed of the same component. I think a standard ListModel/ListView is in order here; I just need a way to put a rectangle behind the rendered area.
-
@JoeCFD that's not quite what I want. What I think I need is:
- a Rectangle with the color I would normally use in my delegate. This would have the rounded corners. (z: 1)
- another Rectangle with height = (first rectangle - (firstRectangleRadius * 2), vertically centered. This Rectangle would be colored to represent the dividers. (z: 2)
- my ListView elements, with the same color as the first Rectangle. (z: 3)
But I don't know how to code this. When I try to introduce the first Rectangle, it hides my list, even if I use the z values.
-
@mzimmers I do not think that is a good idea. Delegates are made for rows. Your round corners are global settings.
Normally you use alternative colors in listview(just like in tables) to display different rows. Pretty much standard practice. Therefore, no dividers are needed. -
import QtQuick 2.15 import QtQuick.Window 2.15 Window { width: 640 height: 480 visible: true Rectangle { id: background anchors.fill: parent color: "blue" } ListView { model: 10 anchors.centerIn: parent height: parent.height / 2 width: parent.width / 2 spacing: 2 boundsBehavior: Flickable.StopAtBounds delegate: Rectangle { height: 10 width: ListView.view.width Text { text: index anchors.centerIn: parent } } Rectangle { anchors.centerIn: parent.contentItem border.width: 15 border.color: background.color width: parent.contentItem.width + border.width * 2 height: parent.contentItem.height + border.width * 2 radius: border.width * 2 color: "transparent" } } }
-
ListView { id: listView model: 10 anchors.centerIn: parent height: parent.height / 2 width: parent.width / 2 spacing: 2 boundsBehavior: Flickable.StopAtBounds delegate: Rectangle { height: 10 width: ListView.view.width } Rectangle { anchors.fill: overlay color: "blue" z: -1 } Rectangle { id: overlay anchors.centerIn: parent.contentItem border.width: 15 border.color: "blue" width: parent.contentItem.width + border.width * 2 height: parent.contentItem.height + border.width * 2 radius: border.width * 2 color: "transparent" } }
-
@JoeCFD said in need ideas on styling a ListView:
@mzimmers I do not think that is a good idea. Delegates are made for rows. Your round corners are global settings.
DelegateChooser, explicit use of a Loader, or hiding/showing items that are always present are all viable techniques.
Going this route, I might do something like:
ListView { delegate: Rectangle { id: d Image { source: d.index == 0 ? topCorner : d.index == (d.ListView.view.count - 1) ? bottomCorner : undefined } }
Normally you use alternative colors in listview(just like in tables) to display different rows. Pretty much standard practice. Therefore, no dividers are needed.
That's a common design choice, but certainly not universal. Wanting a different appearance isn't unreasonable.
-
I think I got it (sorry for the lengthy code include, but I wanted to show everything):
// Roundlist.qml import QtQuick import QtQuick.Controls import QtQuick.Layouts Item { height: parent.height width: parent.width Rectangle { id: rect1 property real rectRadius: 5.0 property real rowHeight: 60.0 property real rowSpacing: 3.0 height: activityView.height + (rectRadius * 2) width: parent.width radius: rect1.rectRadius anchors { horizontalCenter: parent.horizontalCenter verticalCenter: parent.verticalCenter } color: 'white' Rectangle { id: rect2 height: activityView.height width: rect1.width anchors.verticalCenter: rect1.verticalCenter color: mainWindow.color ListModel { id: activityModel ListElement { text: "aaa" } ListElement { text: "bbb" } ListElement { text: "ccc" } ListElement { text: "ddd" } ListElement { text: "eee" } } Component { id: activityDelegate Rectangle { height: rect1.rowHeight width: rect1.width color: rect1.color Text { text: model.text anchors { horizontalCenter: parent.horizontalCenter verticalCenter: parent.verticalCenter } } } } ListView { id: activityView implicitHeight: contentItem.childrenRect.height width: rect1.width spacing: rect1.rowSpacing clip: true model: activityModel delegate: activityDelegate } } } }
It works by itself, though I'm having problem embedding it in a ColumnLayout - instead of appearing inline, it overlays the other items. It should look something like this:
But it comes out like this (please ignore the different text in the rows):
Here's how I'm trying to use it (heavily edited):Flickable { id: flickable Layout.fillHeight: true Layout.fillWidth: true clip: true contentHeight: pumpStuff.height ColumnLayout { id: pumpStuff height: parent.height width: flickable.width - (scroller.width * 2) RowLayout { id: actions } Text { id: parameters } Roundlist {} RowLayout { id: activities } } ScrollBar.vertical: ScrollBar { id: scroller policy: ScrollBar.AlwaysOn//AsNeeded } }
Any idea why this is happening?
Thanks...
-
@mzimmers said in need ideas on styling a ListView:
I think I got it (sorry for the lengthy code include, but I wanted to show everything):
// Roundlist.qml import QtQuick import QtQuick.Controls import QtQuick.Layouts Item { height: parent.height width: parent.width
As a style guide, never reference parent or anything outside of the component. Let the instantiator impose its constraints. Use implicitWidth and implicitHeight to specify reasonable defaults.
-
Apologies if this is answered, I only read the first 2 posts of this long topic.
I worked on something very similar just last month and the QML is really simple. (full).
delegate: Item { height: 80 clip: true Rectangle { // we always have the rounded circles, but if we should not see them, // we move them out of the clipped area. height: { var h = 80; if (index == 0) h += 20 if (index == MAX) // donno, bottom check. h += 20 return h; } radius: 20 y: index == 0 ? 0 : -20 } }
-
@jeremy_k said in need ideas on styling a ListView:
As a style guide, never reference parent or anything outside of the component. Let the instantiator impose its constraints. Use implicitWidth and implicitHeight to specify reasonable defaults.
Understood. How do you handle a case where the instantiator doesn't know the height, because (for example) there might be a variable number of rows? I'm hoping to make this reusable.