QML Wrap delegate inside Rectangle - qt

How can i wrap a custom delegate i made for my listview, inside of a rectangle in order to customize the background and add corner radius to my listview items? Currently i have what is shown on the left in the image below. My goal is the listview on the right, while maintaining the current TextWrapping and whatnot seen in the current solution.
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3
Frame {
anchors.centerIn: parent
anchors.fill: parent
ListView {
implicitWidth: parent.width
implicitHeight: parent.height
clip: true
spacing: 12
model: ListModel {
ListElement {
description: "Wash the car this could be a really long message with some multiline support we will see how it works."
}
ListElement {
description: "Fix the car"
}
ListElement {
description: "Sell the car"
}
ListElement {
description: "Wash the car this could be a really long message with some multiline support we will see how it works. This should word wrap quite a lot of times."
}
ListElement {
description: "Fix the car"
}
ListElement {
description: "Sell the car"
}
ListElement {
description: "Wash the car"
}
ListElement {
description: "Fix the car"
}
ListElement {
description: "Sell the car"
}
}
delegate: RowLayout {
width: parent.width
Rectangle {
id: newsicon
width: 16
height: 16
color: "steelblue"
Layout.alignment: Qt.AlignTop
}
ColumnLayout {
Layout.fillWidth: true
spacing: 4
TextArea {
selectByMouse: true
Layout.fillWidth: true
Layout.alignment: Qt.AlignTop
id: messageText
text: model.description
wrapMode: TextEdit.WordWrap
readOnly: true
topPadding: 0
bottomPadding: 0
background: null
}
Label {
id: dateText
text: "Dec 20, 2019"
font.italic: true
font.pointSize: 8
color: "grey"
}
}
}
ScrollBar.vertical: ScrollBar {
active: true
}
}
}

Essentially all you need to do is encapsulate your delegate's RowLayout in a Rectangle that acts as the background color:
delegate: Rectangle {
id: delegateBackground
color:"lightgreen"
radius: 10
width: parent.width
height: contentContainer.height + 20
Item {
id: contentContainer
width: parent.width - 20
height: column.height
anchors.centerIn: delegateBackground
RowLayout {
width: parent.width
Rectangle {
id: newsicon
width: 16
height: 16
color: "steelblue"
Layout.alignment: Qt.AlignTop
}
ColumnLayout {
id: column
Layout.fillWidth: true
spacing: 4
TextEdit {
selectByMouse: true
Layout.fillWidth: true
Layout.alignment: Qt.AlignTop
id: messageText
text: model.description
wrapMode: TextEdit.WordWrap
readOnly: true
}
Label {
id: dateText
text: "Dec 20, 2019"
font.italic: true
font.pointSize: 8
color: "grey"
}
}
}
}
}
You'll notice that I also added an invisible Item as a container to hold the RowLayout inside the background so that there are margins around the edges as you have indicated in your graphic.

Related

Transition problem in StackView which is displayed on Dialog

Well, I've run into a problem with my StackView in Dialog. You can see it in this example.
Maybe I need to rewrite the animation?
Here is my code:
Dialog {
id: settingDialog
anchors.centerIn: parent
width: 350
height: parent.height / 1.1
closePolicy: Dialog.NoAutoClose
background: Rectangle {
color: "darkgrey"
border.color: "cyan"
radius: 5
}
ColumnLayout {
anchors.fill: parent
spacing: 5
ToolBar {
Layout.fillWidth: true
Layout.minimumHeight: 60
background: Rectangle { color: "transparent" }
RowLayout {
anchors.fill: parent
ToolButton {
id: tbBack
enabled: true
Layout.alignment: Qt.AlignHCenter
Layout.minimumWidth: 30
Layout.leftMargin: 10
background: Rectangle {
color: tbBack.hovered ? "darkcyan" : "transparent"
radius: parent.width
}
onClicked: stackViewSettings.pop()
}
Item { Layout.fillWidth: true }
ToolButton {
id: tbClose
Layout.alignment: Qt.AlignHCenter
Layout.minimumWidth: 30
Layout.rightMargin: 10
icon.source: "ADD YOUR ICO"
background: Rectangle {
color: tbClose.hovered ? "cyan" : "transparent"
radius: parent.width
}
onClicked: {
settingDialog.close()
stackViewSettings.pop()
}
}
}
}
//
StackView {
id: stackViewSettings
Layout.fillWidth: true
Layout.fillHeight: true
initialItem: Page {
background: Rectangle { color: noColor }
ColumnLayout {
anchors.fill: parent
spacing: 0
ListView {
id: listViewSettings
currentIndex: -1
interactive: false
spacing: 10
Layout.fillWidth: true
Layout.fillHeight: true
delegate: ItemDelegate {
height: 40
anchors {
left: parent.left
right: parent.right
}
highlighted: ListView.isCurrentItem
// Style of button
background: Rectangle {
color: parent.hovered ? "#555e69" : "transparent"
radius: 10
}
RowLayout {
anchors.fill: parent
spacing: 15
// Image
Rectangle {
color: noColor
Layout.minimumHeight: 30
Layout.minimumWidth: 30
Layout.leftMargin: 15
Layout.alignment: Qt.AlignRight
Image {
anchors.fill: parent
source: model.imageSource
}
}
// Text
Rectangle {
color: "transparent"
Layout.fillHeight: true
Layout.minimumWidth: 150
Layout.alignment: Qt.AlignLeft
Text {
anchors.verticalCenter: parent.verticalCenter
text: model.title
color: textColor
font.pixelSize: 16
}
}
}
onClicked: stackViewSettings.push(model.source)
}
model: ListModel {
ListElement { title: "Change profile"; imageSource: "ADD YOUR ICO"; source: "ADD YOUR PAGE" }
ListElement { title: "Language"; imageSource: "ADD YOUR ICO"; source: "ADD YOUR PAGE" }
}
}
}
}
}
}
}
Upd 1: I don't think I should use the stackview on dialog at all.
Upd 2: Just added clip: true in the StackView and It helped me.
Your problem is just a clipping issue. By default all QML objects have clip set to false, but you can turn it on to solve your problem:
StackView {
...
clip: true
}

QML Word wrap and TextArea and Margins

How can i make my TextArea word wrap the text area and auto adjust it's height to show the available text in the TextArea? Secondly how can i remove the odd spacing seen in my image attached.
This is what i have now:
This is what I desire:
QML Code:
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3
Frame {
anchors.centerIn: parent
anchors.fill: parent
ListView {
implicitWidth: parent.width
implicitHeight: parent.height
clip: true
model: ListModel {
ListElement {
description: "Wash the car this could be a really long message with some multiline support we will see how it works."
}
ListElement {
description: "Fix the car"
}
ListElement {
description: "Sell the car"
}
ListElement {
description: "Wash the car this could be a really long message with some multiline support we will see how it works. This should word wrap quite a lot of times."
}
ListElement {
description: "Fix the car"
}
ListElement {
description: "Sell the car"
}
ListElement {
description: "Wash the car"
}
ListElement {
description: "Fix the car"
}
ListElement {
description: "Sell the car"
}
}
delegate: RowLayout {
Layout.fillWidth: true
Rectangle {
id: newsicon
width: 16
height: 16
color: "steelblue"
Layout.alignment: Qt.AlignTop
}
ColumnLayout {
Layout.fillWidth: true
spacing: 0
TextArea {
Layout.fillWidth: true
Layout.alignment: Qt.AlignTop
id: messageText
text: model.description
wrapMode: TextEdit.WordWrap
readOnly: true
textMargin: 0.0
background: null
}
Label {
id: dateText
text: "Dec 20, 2019"
font.italic: true
font.pointSize: 8
color: "grey"
}
}
}
ScrollBar.vertical: ScrollBar {
active: true
}
}
}

How to prevent the contents to appear below the height that is on transition on qml?

To explain better the question, im going to use images, but in summary i'll have a component that will transition the heightfrom 0 to an height that is correspondent to the height of it's childs. that problem is that all the child itemswill appear the moment the transition starts
To illustrate, the height of the child div of Panel 1is 0:
then i click, the transition is supposed to take 5000ms and this happens:
at the end of the 5000ms i have this:
The code i've used for this example is this:
main.qml
import QtQuick 2.7
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.3
import QtQuick.Window 2.3
ApplicationWindow {
visible: true
width: 640
height: 200
title: qsTr("Tabbars")
Item{
id:item
anchors.fill:parent
ScrollView{
anchors.fill:parent
Column {
width:item.width
PanelItem {
id:panel1
title: "Panel 1"
width:parent.width
content: Item {
property string title: "teste"
height: configContent.implicitHeight
width: configContent.implicitWidth
ColumnLayout{
id:configContent
anchors.topMargin: 10
anchors.bottomMargin: 10
anchors.fill:parent
TextField {
id: companyNameText1
placeholderText: qsTr("Company name")
Layout.fillWidth: true
selectByMouse: true
}
ComboBox {
id: languagesComboBox1
textRole: "text"
objectName: "language"
Layout.fillWidth: true
model: ListModel {
ListElement {text: QT_TR_NOOP("English"); oid: 0}
ListElement {text: QT_TR_NOOP("Portuguese"); oid: 1}
ListElement {text: QT_TR_NOOP("Spanish"); oid: 2}
ListElement {text: QT_TR_NOOP("Italian"); oid: 3}
ListElement {text: QT_TR_NOOP("French"); oid: 4}
ListElement {text: QT_TR_NOOP("Portuguese(Brasil)"); oid: 5}
}
}
ComboBox {
id: devSndrModeComboBox1
textRole: "text"
objectName: "test_dev_sndr_mode"
Layout.fillWidth: true
model: ListModel {
Component.onCompleted: {
append({ text: QT_TR_NOOP("None"), oid: 0 })
append({ text: QT_TR_NOOP("Subpanel"), oid: 1 })
append({ text: QT_TR_NOOP("All"), oid: 2 })
}
}
}
}
}
}
PanelItem {
id:panel2
title: "Panel 2"
width:parent.width
content: Item {
property string title: "teste"
height: configContent2.implicitHeight
width: configContent2.implicitWidth
ColumnLayout{
id:configContent2
anchors.fill:parent
ComboBox {
id: sndrModeComboBox1
textRole: "text"
Layout.fillWidth: true
model: ListModel {
Component.onCompleted: {
append({ text: QT_TR_NOOP("Preset"), oid: 0 })
append({ text: QT_TR_NOOP("Programmed"), oid: 1 })
}
}
}
}
}
}
}
}
}
}
and PanelItem.qml
import QtQuick 2.7
import QtQuick.Layouts 1.2
Item {
id: root
property Component content
property string title: "panel"
property bool isSelected: false
height: container.height + bar.height
Rectangle{
id: bar
anchors {
top: parent.top
left: parent.left
right: parent.right
}
height: 30
color: root.isSelected ? "#81BEF7" : "#CEECF5"
Text {
anchors.fill: parent
anchors.margins: 10
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
text: root.title
}
Text {
anchors{
right: parent.right
top: parent.top
bottom: parent.bottom
margins: 10
}
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: "^"
rotation: root.isSelected ? "180" : 0
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: isSelected = !isSelected
}
}
Rectangle{
id: container
anchors.top: bar.bottom
anchors.left: parent.left
anchors.right: parent.right
height: loader.item && isSelected ? loader.item.height : 0
Loader {
id: loader
visible: isSelected
sourceComponent: content
anchors.top: container.top
}
Behavior on height {
PropertyAnimation { duration: 5000 }
}
}
}
I hope i explained well the problem.
What would be the best way to solve this?

Error of 'TypeError: Cannot read property 'name' of undefined', it comes start to end or vice-versa of application window by moving mouse wheel scroll

I am working on qml, found found an error during moving mouse wheel scrolling i.e.
"TypeError: Cannot read property 'name' of undefined".
It only appear when either mouse wheel scrolling or close the application while during execution and beginning of the application didn't show this error.
One more thing, I am getting accurate data/result whatever I want but due to this error the performance of application get affected.
Please let me know how can I get rid of this issue?
also find below example to see error.
My code is..
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Layouts 1.1
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
menuBar: MenuBar {
Menu {
title: qsTr("File")
MenuItem {
text: qsTr("Exit")
onTriggered: Qt.quit();
}
}
}
TableView {
anchors.fill: parent
visible: true
backgroundVisible: false
alternatingRowColors: false
sortIndicatorVisible: true
clip: true
highlightOnFocus: false
width: parent.width
height: parent.height
TableViewColumn{ role: "code" ; title: "cde" ; width: 200;
delegate: Component {
id: codeDelegate
Item{
Text {
color: "lightgray"
elide: styleData.elideMode
text: styleData.value //modelSettingData.get(styleData.row).name
font.family: "Arial"
font.pixelSize: 18
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
Text {
id: metaData
color: "red"
width: parent.width
// height: 20
anchors.bottom: parent.bottom
anchors.bottomMargin: -parent.height/1.5
font.weight: Font.ExtraLight
//elide: Text.ElideMiddle
text: "Time: " + modelSettingData.get(styleData.row).name //Error comes when this part added but I need to use it with the same form
}
}
}
}
}
TableViewColumn{ role: "name" ; title: "nme" ; width: 200
delegate: Component {
id: nameDelegate
Text {
color: "yellow"
elide: styleData.elideMode
text: styleData.value
font.family: "Arial"
font.pixelSize: 18
}
}
}
model: ListModel {
id: modelSettingData
ListElement {
name: "aaaaaaaaaa"
code: "3042666666666"
}
ListElement {
name: "bbbbbb"
code: "32235"
}
ListElement {
name: "ccccccc"
code: "32638"
}
ListElement {
name: "ddddddddddd"
code: "00000000000"
}
ListElement {
name: "eeeeeeeeeeee"
code: "111111111111"
}
ListElement {
name: "ffffffffffff"
code: "222222222222"
}
ListElement {
name: "ggggggggggggg"
code: "3333333333333"
}
ListElement {
name: "hhhhhhhhhhhhh"
code: "4444444444444"
}
ListElement {
name: "iiiiiiiiiiiii"
code: "5555555555555"
}
}
rowDelegate: Rectangle {
property bool selected : styleData.selected
width: parent.width-2
height: 100
color: styleData.selected? "black" : "black"
Rectangle {
width: parent.width
height: 1
anchors.bottom: parent.bottom
visible: parent.selected
color: "yellow"
}
}
}
}

QML ListView, SwipeView etc. - avoid overlapping of other UI components

I'm trying to avoid this annoying overlapping that both SideView and ListView seem to fancy. Here is an example which demonstrates the issue:
Note: Look at the green rectangle on the left when you swipe the SwipeView and also the tabs when you scroll down the ListView
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QLatin1String("qrc:/main.qml")));
return app.exec();
}
main.qml
import QtQuick 2.7
import QtQuick.Window 2.0
import QtQuick.Controls 2.0
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Layouts 1.2
Window {
id: window
visible: true
width: 600
height: 480
title: "Demo"
RowLayout {
id: layoutTopLevel
anchors.fill: parent
spacing: 0
Rectangle {
id: sidebarView
Layout.preferredWidth: layoutTopLevel.width * .3
Layout.fillHeight: true
color: "#453"
border.width: 1
}
ColumnLayout {
id: sideViewLayout
spacing: 0
SwipeView {
id: sideView
currentIndex: sideViewPageIndicator.currentIndex
Layout.fillWidth: true
Layout.preferredHeight: layoutTopLevel.height * .9
Page {
id: page1
header: Text {
text: "Page 1"
horizontalAlignment: Text.AlignHCenter
font.pixelSize: 20
}
}
Page {
id: page2
header: Text {
text: "Page 2"
horizontalAlignment: Text.AlignHCenter
font.pixelSize: 20
}
TabView {
id: page2TabView
width: parent.width
height: parent.height
anchors.margins: 4
tabPosition: Qt.BottomEdge
Tab {
title: qsTr("Tab 1")
}
Tab {
title: qsTr("Tab 2")
ColumnLayout {
Text {
text: "Text 1"
Layout.alignment: Qt.AlignCenter
}
Text {
text: "Text 2"
Layout.alignment: Qt.AlignCenter
}
ListView {
width: parent.width
height: parent.height
model: ListModel {
ListElement {
name: "Element 1"
}
ListElement {
name: "Element 2"
}
ListElement {
name: "Element 3"
}
ListElement {
name: "Element 4"
}
ListElement {
name: "Element 5"
}
ListElement {
name: "Element 6"
}
}
delegate: Text {
text: name
}
}
}
}
style: TabViewStyle {
tabsAlignment: Qt.AlignHCenter
frameOverlap: 1
tab: Rectangle {
border.width: styleData.selected
implicitWidth: Math.max(text.width + 4, 80)
implicitHeight: 20
radius: 10
Text {
id: text
anchors.centerIn: parent
text: styleData.title
color: styleData.selected ? "white" : "black"
}
color: styleData.selected ? "#654" : "white"
}
frame: Rectangle {
color: "white"
}
}
}
}
}
PageIndicator {
id: sideViewPageIndicator
count: sideView.count
interactive: true
anchors.bottom: sideView.bottom
anchors.bottomMargin: -45
anchors.horizontalCenter: parent.horizontalCenter
delegate: Rectangle {
height: 30
width: 30
antialiasing: true
color: "#654"
radius: 10
opacity: index === sideView.currentIndex ? 0.95 : pressed ? 0.7 : 0.45
Behavior on opacity {
OpacityAnimator {
duration: 100
}
}
}
}
}
}
}
Use clip: true
Which clips the content which goes out of its boundaries.
I accidentally came across an example of a ListView while looking into another problem I had and I saw the clip property there. I have completely missed it while looking into the docs of both SideView and ListView. Basically when you set it to true the view no longer covers other components and this is exactly what I want. See comment by #Mitch on why this is not enabled by default.

Resources