Multiline text item is not clipped inside QML ListView - qt

I have a QML page that with a GridLayout that contains the page title, ListView and close button:
GridLayout {
columns: 1
rows: 5
anchors.fill: parent
<page title item>....
ListView
{
spacing: 15
model: logModel
delegate: Item {
implicitWidth: parent.width
implicitHeight: grid.height
RowLayout
{
id: grid
spacing: 0
width: parent.width
height: commentLabel.implicitHeight
<icon>....
Label {
id: commentLabel
Layout.fillWidth: true
text: comment
wrapMode: Label.Wrap
}
}
}
ScrollIndicator.vertical: ScrollIndicator { }
}
<close button>...
}
When I scroll the list, the first and the last visible item in the list may go beyond the list bounder and intersect the page title or close button:
How to prevent this and make the items clipped?
EDIT1:
I tried to add
clip: true
to ListView, delegate Item, RowLayout and Label, but with no success. According to docs, ListView with clip property set to true should clip its content, should not it?
I found a similar question where clip property is the answer, but it is not clear why it does not work with my ListView.
My QT version is 5.13.2.

Set clip:true in the ListView component.
ListView
{
clip:true
}

Related

How to setup ListView that hightlight fits always into it

I have a vertical ListView with a lot elements. When an element gets clicked a Rectangle pops up under it as highlight.
This doesnt work for the last elements in the ListView, as can be seen in the image.
How do I setup ListView, that a highlight pushes all elements up.
What I have:
What I want:
I could solve my issue by expanding the selected delegates height for the while it is selected. Furthermore you have to set the hightlight's y explicitly.
ListView{ id:listView
property var someHeight: 100
delegate:Item{
id: delegate
Connections{
target: listView
function onCurrentIndexChanged(){
if(index==listView.currentIndex)
delegate.height=someHeight+listView.highlightItem.childrenRect.height
else
delegate.height=someHeight
}
}
}
}
highlight:Item{
z:10
Rectangle{
id:highlightRect
anchors.left:parent.left
anchors.leftMargin: smallMargin
anchors.right: parent.right
anchors.rightMargin: smallMargin
y: someHeight;
height:someHighlightHeight
}
}
}

Qml Combobox not closing when delegate of the listview goes out of scope

I have made a delegate for listview that contains Combobox. If I open the Combobox and scroll the listview, the Combobox popup is moving with the delegate position, that's ok. But when the delegate goes out of the listview area(Ref the sample image attached), Combobox popup continues to moves even out of the listview area.
How to close the Combobox when the corresponding delegate goes out of the listview area.
Thanks in advance...
Code goes here
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.2
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Column {
spacing: 0
anchors.fill: parent
Item {
width: parent.width
height: parent.height * 0.4
Image {
anchors.fill: parent
anchors.margins: 10
source: "https://lh4.googleusercontent.com/proxy/cITVCAj9KJ5Hfwd5iuNDhzdB2pSrMQv2rzTl-vvg23Ifhe2qdCisZBG-MzV35y_r2zijC9X4QOpda9eHzr_hA"
}
}
ListView {
width: parent.width
height: parent.height * 0.7
model: 10
spacing: 5
clip: true
delegate: Rectangle {
width: parent.width
height: 50
color: index % 2 == 0 ? "lightsteelblue" : "steelblue"
Row {
spacing: 25
anchors.centerIn: parent
Label {
text: qsTr("%1").arg(index)
anchors.verticalCenter: parent.verticalCenter
}
ComboBox {
anchors.verticalCenter: parent.verticalCenter
model: ["a", "b", "c"]
}
}
}
}
}
}
If there is no particular goal to keep ComboBox popup opened when scrolling, then add the following property to your ListView:
highlightRangeMode: ListView.StrictlyEnforceRange
This will close ComboBox popup when ListView is being scrolled.
P.S.
Also, resolves your issue with the ComboBox list getting out of view area.
UPDATE on issue with header element hiding below other list items:
Accordingly to the description ListView.StrictlyEnforceRange - the highlight never moves outside of the range. The current item changes if a keyboard or mouse action would cause the highlight to move outside of the range. when an item goes out of range the list changes next item and that makes ComboBox closing its popup, but since header item is below the other ListView items itself (see this paragraph https://doc.qt.io/qt-5/qml-qtquick-listview.html#stacking-order-in-listview , delegate is always above a header) it makes impossible displaying default header here at the top of the other items. I'd suggest you implement your own header beyond the list. Sorry, I might not have known Qt so good to find the other solution.

Controlling size of QML components from within style property

I'd like to create my own styled RadioButton, but I'm having difficulty controlling the size of the components used in the RadioButtonStyle that I am using. I want to put my RadioButton in a GridLayout and have the RadioButton take up all the available space (as if I were setting Layout.fillWidth and Layout.fillHeight to true)
To start off with, I am using the RadioButtonStyle code from the Qt docs inside a GridLayout:
GridLayout {
columns: 3
anchors.fill: parent
RadioButton {
text: "Radio Button"
style: RadioButtonStyle {
indicator: Rectangle {
implicitWidth: 16
implicitHeight: 16
Rectangle {
anchors.fill: parent
visible: control.checked
color: "#555"
}
}
}
}
}
we can see that implicitWidth and implicitHeight of the indicator Rectangle are set int literals. I want to size the indicator Rectangle to fill the space provided by the layout.
I would like the width and height of the indicator Rectangle to track the width and height of the RadioButton, which in turn tracks the width and height of the GridLayout cell containing it.
== UPDATE ==
I have tried the following - setting Layout.maximumHeight/Width prevents Qml going into some kind of infinite loop
RadioButton {
id: rdbt
Layout.fillHeight: true
Layout.fillWidth: true
Layout.maximumWidth: 200
Layout.maximumHeight: 200
style: RadioButtonStyle {
id: ab
indicator: Rectangle {
color: "blue"
height: control.height
width: control.width //control.width

Building TabBar in QML - Loader doesn't show all the Rectangles

import QtQuick 2.4
import QtQuick.Window 2.2
Window
{
visible: true
height: 500
width: 500
property VisualItemModel contentToBeShownOnTabClick : visualItemModelDemo
property variant tabLabels : ["Navigation", "Payload", "System Control"]
VisualItemModel
{
id: visualItemModelDemo
Rectangle
{
id: navigationTab
color: "green"
height: 200
width: 200
}
Rectangle
{
id: navigationTab1
color: "darkgreen"
height: 200
width: 200
}
Rectangle
{
id: navigationTab2
color: "lightgreen"
height: 200
width: 200
}
}
MainForm
{
Component
{
id: tabsOnBottomComponent
Repeater
{
model: tabLabels
// The Tabs
Rectangle
{
id: tabsOnBottom
// This anchoring places the tabs on the outer top of the parent rectangle.
anchors.top: parent.bottom
anchors.topMargin: 180
color: "lightsteelblue"
border.color: "steelblue"
border.width: 2
implicitWidth: Math.max ((labelTabsBottom.width + 4), 80)
implicitHeight: 20
radius: 2
// Tabs Text/Label
Text
{
id: labelTabsBottom
anchors.centerIn: parent
color: "white"
rotation: 0
// With reference to mode: tabLabels
text: modelData
font.pointSize: 11
}
MouseArea
{
anchors.fill: parent
onClicked: bottomTabClicked (index);
}
}
}
}
Rectangle
{
// The things which get displayed on clicking of a tab will be shown in this rectangle.
id: areaForTabContents
border.color: "black"
border.width: 10
height: parent.height
width : parent.width
color : "pink"
// These are the tabs displayed in one row - horizontally.
Row
{
id: horizontalTabs
Loader
{
anchors.fill: parent
sourceComponent: tabsOnBottomComponent
}
}
}
anchors.fill: parent
}
}
This gets shown as follows:
whereas I want it to see 3 rectangles there side by side.
Loader is not a transparent type w.r.t. the containing type, Row in this case. I think this is an issue related to creation context and the way Repeater works. From the documentation of the latter:
Items instantiated by the Repeater are inserted, in order, as children of the Repeater's parent. The insertion starts immediately after the Repeater's position in its parent stacking list. This allows a Repeater to be used inside a layout.
The Rectangles are indeed added to the parent which is the Loader, they stack up - Loader does not provide a positioning policy - then they are added to the Row resulting in just one Item (the last one) to be visible.
You can tackle the problem with few different approaches, depending on the properties you want to maintain or not. I would get rid of anchoring in the Component and move it to the containing Row. A too specific anchoring inside a Component could be a pain in the neck when it is instanced and used all over a (not so small) project.
As a first approach you can re-parent the Repeater to the Row, i.e. you can rewrite code as:
Row
{
id: horizontalTabs
Loader
{
sourceComponent: tabsOnBottomComponent
onLoaded: item.parent = horizontalTabs
}
}
However this would result in warnings due to the Component anchoring references not working as expected any more.
If you still want to maintain the anchoring, as defined in the Component, and off-load the creation, you can go for the dynamic way (if the semantics fits in your use case), i.e. you can use createObject. This way you totally avoid the Loader and the related issue. For instance, you can create the Repeater once the Row has completed its creation:
Row
{
id: horizontalTabs
Component.onCompleted: tabsOnBottomComponent.createObject(horizontalTabs)
}
Clearly, the creation code can be move anywhere else, depending on your needs.

Scroll QML Grid

I want to make my QML Grid scrollable as soon as the content is too long for it to display.
Grid {
objectName: "sidebarView"
id: sidebarGrid
flow: Grid.TopToBottom
columns: 1
spacing: 10
}
Is that possible with just a few properties added to the Grid?
No, but you can just put a Flickable around the Grid
Flickable {
anchors.fill: parent
contentHeight: sidebarGrid.height
contentWidth: sidebarGrid.width
Grid {
objectName: "sidebarView"
id: sidebarGrid
flow: Grid.TopToBottom
columns: 1
spacing: 10
}
}

Resources