By default SwipeDelegate allows for swiping multi items like below image:
As you can see, multi swipe items are open at a time and i want only one open item at a time, means if you open item #1, by opening item #2, item #1 should close. how can i achieve this?
Sample code for a ListView with SwipeDelegate:
ListView {
id: listView
anchors.fill: parent
delegate: SwipeDelegate {
id: delegate
text: modelData
width: parent.width
swipe.right: Rectangle {
width: parent.width
height: parent.height
Label {
text: qsTr("SOME ACTION BUTTON")
padding: 20
anchors.fill: parent
}
}
}
model: ListModel {
id: listModel
ListElement { text: "Lorem ipsum dolor sit amet" }
ListElement { text: "Curabitur sit amet risus" }
ListElement { text: "Suspendisse vehicula nisi" }
ListElement { text: "Mauris imperdiet libero" }
ListElement { text: "Sed vitae dui aliquet augue" }
ListElement { text: "Praesent in elit eu nulla" }
ListElement { text: "Etiam vitae magna" }
ListElement { text: "Pellentesque eget elit euismod" }
ListElement { text: "Nulla at enim porta" }
ListElement { text: "Fusce tincidunt odio" }
ListElement { text: "Ut non ex a ligula molestie" }
ListElement { text: "Nam vitae justo scelerisque" }
ListElement { text: "Vestibulum pulvinar tellus" }
ListElement { text: "Quisque dignissim leo sed gravida" }
}
ScrollIndicator.vertical: ScrollIndicator { }
}
Here's how I would do this:
import QtQuick 2.9
import QtQuick.Controls 2.3
import QtGraphicalEffects 1.0
ApplicationWindow {
id: window
width: 800
height: 600
visible: true
ListView {
id: listView
anchors.fill: parent
ButtonGroup {
buttons: listView.contentItem.children
}
delegate: SwipeDelegate {
id: delegate
checkable: true
text: modelData
width: parent.width
checked: swipe.complete
onCheckedChanged: if (!checked) swipe.close()
swipe.right: Rectangle {
width: parent.width
height: parent.height
color: "#666"
Label {
text: qsTr("SOME ACTION BUTTON")
color: "white"
leftPadding: 20
anchors.verticalCenter: parent.verticalCenter
}
}
}
model: ListModel {
id: listModel
ListElement { text: "Lorem ipsum dolor sit amet" }
ListElement { text: "Curabitur sit amet risus" }
ListElement { text: "Suspendisse vehicula nisi" }
ListElement { text: "Mauris imperdiet libero" }
ListElement { text: "Sed vitae dui aliquet augue" }
ListElement { text: "Praesent in elit eu nulla" }
ListElement { text: "Etiam vitae magna" }
ListElement { text: "Pellentesque eget elit euismod" }
ListElement { text: "Nulla at enim porta" }
ListElement { text: "Fusce tincidunt odio" }
ListElement { text: "Ut non ex a ligula molestie" }
ListElement { text: "Nam vitae justo scelerisque" }
ListElement { text: "Vestibulum pulvinar tellus" }
ListElement { text: "Quisque dignissim leo sed gravida" }
}
ScrollIndicator.vertical: ScrollIndicator { }
}
}
ButtonGroup ensures that only one "button" (SwipeDelegate is derived from AbstractButton) can be checked at a time. SwipeDelegate has no visual effects to represent the checked state, so we can safely use it to keep track of which one should be open. We still need to close the previously open delegate though, so that's where the
onCheckedChanged: if (!checked) swipe.close()
comes in.
Inspired by the answer with the ButtonGroup, here's my solution which does not require to modify the delegates:
SwipeDelegateGroup.qml
import QtQuick 2.9
import QtQuick.Controls 2.2
Item {
id: swipeGroup
property ListView listView: parent
QtObject {
id: d
property var delegates: swipeGroup.listView.contentItem.children
property var delegateCache: []
onDelegatesChanged: {
for (var i = 0; i < d.delegates.length; i++) {
var thisItem = d.delegates[i];
if (!thisItem.hasOwnProperty("swipe")) {
continue;
}
if (d.delegateCache.indexOf(thisItem) < 0) {
d.delegateCache.push(thisItem);
thisItem.Component.destruction.connect(function() {
d.delegateCache.splice(d.delegateCache.indexOf(thisItem), 1)
})
thisItem.swipe.opened.connect(function() {
for (var j = 0; j < d.delegates.length; j++) {
var otherItem = d.delegates[j];
if (thisItem === otherItem) {
continue;
}
if (!otherItem.hasOwnProperty("swipe")) {
continue;
}
otherItem.swipe.close();
}
})
}
}
}
}
}
Then just put this into the ListView like this:
ListView {
SwipeDelegateGroup {}
delegate: SwipeDelegate {
...
}
}
Related
I am having trouble getting the scrollview to work properly. I'm most likely missing something or I'm doing something totally wrong. This isn't my first time dealing with this issue either. The page contains a scrollview which has a stacklayout inside of it. My goal is to scroll through the stacklayout content using the scrollview. I tried setting the contentWidth and the contentHeight of the scrollview but that did not fix the issue.
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import QtGraphicalEffects 1.12 // ColorOverlay
import "../../components" as NeroshopComponents
Page {
id: sellerHub
background: Rectangle {
color: "transparent"
}
NeroshopComponents.TabBar {
id: tabBar
anchors.top: parent.top
anchors.topMargin: tabBar.buttonHeight
anchors.horizontalCenter: parent.horizontalCenter
model: ["Overview", "Inventory", "Customers"]
Component.onCompleted: {
buttonAt(1).checked = true
}
}
ScrollView {
id: scrollView
width: parent.width; height: 2000//anchors.fill: parent
anchors.top: tabBar.bottom; anchors.topMargin: tabBar.buttonHeight + 10
//anchors.margins: 20
//contentHeight: height; contentWidth: width
ScrollBar.vertical.policy: ScrollBar.AlwaysOn////AsNeeded
clip: true
StackLayout {
id: dashboard
anchors.fill: parent
currentIndex: tabBar.checkedButtonIndex
Item {
id: overviewTab
// StackLayout child Items' Layout.fillWidth and Layout.fillHeight properties default to true
RowLayout {
id: stats
anchors.horizontalCenter: parent.horizontalCenter//Layout.alignment: Qt.AlignHCenter | Qt.AlignTop// <- this is not working :/
property real numberTextFontSize: 24
property string textColor: "#384364"////(NeroshopComponents.Style.darkTheme) ? "#ffffff" : "#384364"
property real boxWidth: 250//(scrollView.width / 3) - 20//scrollView.width / statsRepeater.count
property real boxHeight: 110
property real boxRadius: 6
spacing: 15
property bool useDefaultBoxColor: true//false
property string boxColor: "#ffffff"////(NeroshopComponents.Style.darkTheme) ? "#384364" : "#ffffff"
// Products (listed)
Rectangle {
Layout.preferredWidth: stats.boxWidth
Layout.preferredHeight: stats.boxHeight
color: stats.useDefaultBoxColor ? stats.boxColor : "#e9eefc"
radius: stats.boxRadius
Item {
anchors.fill: parent
anchors.centerIn: parent
Rectangle {
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left; anchors.leftMargin: width / 2
width: 64; height: 64
color: "#e9eefc"
radius: 50
Image {
id: productIcon
source: "qrc:/images/open_parcel.png"
width: 32; height: 32
anchors.centerIn: parent
}
ColorOverlay {
anchors.fill: productIcon
source: productIcon
color: "#4169e1"
visible: productIcon.visible
}
}
Item {
anchors.right: parent.children[0].right; anchors.rightMargin: -(contentWidth + 20)
anchors.top: parent.children[0].top
Text {
text: "0"//"5430"
font.bold: true
font.pointSize: stats.numberTextFontSize
color: stats.textColor
}
Text {
text: "Products"
//font.bold: true
color: stats.textColor
anchors.left: parent.children[0].left
anchors.top: parent.children[0].bottom; anchors.topMargin: 10
}
}
}
}
// Sales (the total number of completed orders)
Rectangle {
Layout.preferredWidth: stats.boxWidth
Layout.preferredHeight: stats.boxHeight
color: stats.useDefaultBoxColor ? stats.boxColor : "#eff5ef"
radius: stats.boxRadius
Item {
anchors.fill: parent
anchors.centerIn: parent
Rectangle {
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left; anchors.leftMargin: width / 2
width: 64; height: 64
color: "#eff5ef"
radius: 50
Image {
id: salesIcon
source: "qrc:/images/increase.png"
width: 32; height: 32
anchors.centerIn: parent
}
ColorOverlay {
anchors.fill: salesIcon
source: salesIcon
color: "#8fbc8f"
visible: salesIcon.visible
}
}
Item {
anchors.right: parent.children[0].right; anchors.rightMargin: -(contentWidth + 20)
anchors.top: parent.children[0].top
Text {
text: "0"//"17440"
font.bold: true
font.pointSize: stats.numberTextFontSize
color: stats.textColor
}
Text {
text: "Sales"
//font.bold: true
color: stats.textColor
anchors.left: parent.children[0].left
anchors.top: parent.children[0].bottom; anchors.topMargin: 10
}
}
}
}
// Ratings/Feedback/Reputation
Rectangle {
Layout.preferredWidth: stats.boxWidth
Layout.preferredHeight: stats.boxHeight
color: stats.useDefaultBoxColor ? stats.boxColor : "#fffbe5"
radius: stats.boxRadius
Item {
anchors.fill: parent
anchors.centerIn: parent
Rectangle {
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left; anchors.leftMargin: width / 2
width: 64; height: 64
color: "#fffbe5"
radius: 50
Image {
id: ratingIcon
source: "qrc:/images/rating.png"
width: 32; height: 32
anchors.centerIn: parent
}
ColorOverlay {
anchors.fill: ratingIcon
source: ratingIcon
color: "#ffd700"//"#e6c200"
visible: ratingIcon.visible
}
}
Item {
anchors.right: parent.children[0].right; anchors.rightMargin: -(contentWidth + 20)
anchors.top: parent.children[0].top
Text {
text: qsTr("%1%2").arg("0").arg("%")
font.bold: true
font.pointSize: stats.numberTextFontSize
color: stats.textColor
}
Text {
text: "Reputation"
//font.bold: true
color: stats.textColor
anchors.left: parent.children[0].left
anchors.top: parent.children[0].bottom; anchors.topMargin: 10
}
}
}
}
}
// TODO: show recent orders from customers, show seller's top-selling products, show customer reviews on seller products
//ColumnLayout {}
} // overview tab
Item {
id: inventoryTab
// StackLayout child Items' Layout.fillWidth and Layout.fillHeight properties default to true
Component.onCompleted: { console.log("InventoryTab width",this.width) }
ColumnLayout {//GridLayout {//
id: productDetails
width: parent.width; height: childrenRect.height////anchors.fill: parent
Component.onCompleted: { console.log("ProductDetails width",this.width) }
spacing: 30////rowSpacing: 5
property string titleTextColor: (NeroshopComponents.Style.darkTheme) ? "#ffffff" : "#000000"
property real radius: 3
property real marginFromTitle: 7
property string textColor: (NeroshopComponents.Style.darkTheme) ? "#ffffff" : "#000000"
property string baseColor: (NeroshopComponents.Style.darkTheme) ? "#101010" : "#ffffff"
property string borderColor: (NeroshopComponents.Style.darkTheme) ? "#a9a9a9" : "#000000"
// RegisterItem to "products" table
//Product title (TODO: place both text and textfield in an item)
// If item fields are related then place them side-by-side in separate columns
Item {
//Layout.row: 0
Layout.alignment: Qt.AlignHCenter// | Qt.AlignTop
//Layout.topMargin: 0
Layout.preferredWidth: childrenRect.width////productNameField.width
Layout.preferredHeight: childrenRect.height // 72 (child margins included)
Text {
text: "Product name" // height=17
color: productDetails.titleTextColor
font.bold: true
}
TextField {
id: productNameField
width: 500; height: 50
anchors.top: parent.children[0].bottom
anchors.topMargin: productDetails.marginFromTitle
placeholderText: qsTr("Product title")
color: productDetails.textColor
selectByMouse: true
background: Rectangle {
color: productDetails.baseColor
border.color: productDetails.borderColor
radius: productDetails.radius
}
}
}
// Product price (sales price)
Item {
//Layout.row: 1
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: childrenRect.width
Layout.preferredHeight: childrenRect.height
Text {
text: "Price"
color: productDetails.titleTextColor
font.bold: true
}
TextField {
id: productPriceField
width: 500; height: 50
anchors.top: parent.children[0].bottom
anchors.topMargin: productDetails.marginFromTitle
placeholderText: qsTr("Enter price")
color: productDetails.textColor
selectByMouse: true
background: Rectangle {
color: productDetails.baseColor
border.color: productDetails.borderColor
radius: productDetails.radius
}
}
}
// Product quantity
Item {
//Layout.row:
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: childrenRect.width
Layout.preferredHeight: childrenRect.height
Text {
text: "Quantity"
color: productDetails.titleTextColor
font.bold: true
//visible: false
}
TextField {
id: productQuantityField
width: 500; height: 50
anchors.top: parent.children[0].bottom
anchors.topMargin: productDetails.marginFromTitle
placeholderText: qsTr("Enter quantity")
color: productDetails.textColor
selectByMouse: true
background: Rectangle {
color: productDetails.baseColor
border.color: productDetails.borderColor
radius: productDetails.radius
}
}
}
// Product condition
Item {
//Layout.row:
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: childrenRect.width
Layout.preferredHeight: childrenRect.height
Text {
text: "Condition"
color: productDetails.titleTextColor
font.bold: true
//visible: false
}
ComboBox {
anchors.top: parent.children[0].bottom
anchors.topMargin: productDetails.marginFromTitle
width: 500
model: ["new", "used", "renewed (refurbished)"]
}
}
// Product code UPC, EAN, JAN, SKU, ISBN (for books) // https://www.simplybarcodes.com/barcode_types.html
Item {
//Layout.row:
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: childrenRect.width
Layout.preferredHeight: childrenRect.height
Text {
text: "Product code"
color: productDetails.titleTextColor
font.bold: true
//visible: false
}
TextField {
id: productCodeField
width: 500; height: 50
anchors.top: parent.children[0].bottom
anchors.topMargin: productDetails.marginFromTitle
placeholderText: qsTr("Enter product code (optional)")
color: productDetails.textColor
selectByMouse: true
background: Rectangle {
color: productDetails.baseColor
border.color: productDetails.borderColor
radius: productDetails.radius
}
}
}
// Product categories
// Subcategories (will be determined based on selected categories)
// Weight
Item {
//Layout.row:
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: childrenRect.width
Layout.preferredHeight: childrenRect.height
Text {
text: ""
color: productDetails.titleTextColor
font.bold: true
//visible: false
}
TextField {
id: productWeightField
width: 500; height: 50
anchors.top: parent.children[0].bottom
anchors.topMargin: productDetails.marginFromTitle
placeholderText: qsTr("Enter weight (e.g. 12 lbs.)")
color: productDetails.textColor
selectByMouse: true
background: Rectangle {
color: productDetails.baseColor
border.color: productDetails.borderColor
radius: productDetails.radius
}
}
//ComboBox {
// id: weightMeasurementUnit (default is kg)
//}
}
// Size
Item {
//Layout.row:
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: childrenRect.width
Layout.preferredHeight: childrenRect.height
Text {
text: ""
color: productDetails.titleTextColor
font.bold: true
//visible: false
}
TextField {
id: productSizeField
width: 500; height: 50
anchors.top: parent.children[0].bottom
anchors.topMargin: productDetails.marginFromTitle
placeholderText: qsTr("Enter size")
color: productDetails.textColor
selectByMouse: true
background: Rectangle {
color: productDetails.baseColor
border.color: productDetails.borderColor
radius: productDetails.radius
}
}
//ComboBox
}
// Variations (i.e. Color, Size options to choose from - optional)
// Product location (ship to and ship from)
//Product description and bullet points
Item {
//Layout.row:
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: childrenRect.width
Layout.preferredHeight: childrenRect.height
Text {
text: "Description"
color: productDetails.titleTextColor
font.bold: true
//visible: false
}
TextArea {
id: productDescArea
anchors.top: parent.children[0].bottom
anchors.topMargin: productDetails.marginFromTitle
width: 500; height: 250
}
}
//Product images
//Search terms and relevant keywords (tags)
// tags must be separated with a colon
Item {
//Layout.row:
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: childrenRect.width
Layout.preferredHeight: childrenRect.height
Text {
text: ""
color: productDetails.titleTextColor
font.bold: true
//visible: false
}
TextField {
id: productKeywordsField
width: 500; height: 50
anchors.top: parent.children[0].bottom
anchors.topMargin: productDetails.marginFromTitle
placeholderText: qsTr("Enter keywords or search term")
color: productDetails.textColor
selectByMouse: true
background: Rectangle {
color: productDetails.baseColor
border.color: productDetails.borderColor
radius: productDetails.radius
}
}
}
// ListItem to "listings" table
//Button {
// id: listProductButton
//}
}
//ColumnLayout {
// id: inventoryManager // inventory can be managed here and sorted too
//}
}
Item {
id: customerOrdersTab
}
}
}
}
I suspect the reason why the ScrollView is not working for you is because your child StackLayout has anchors.fill: parent. This means the size of your child is already constrained, so it will never have a meaningful ScrollBar. Please review your anchoring / sizing.
Here's an example usage of ScrollView. Note that the ScrollView contains exactly one child. Note that I have not set the height of the child and allowed it to grow. Note that I modified the default policy making the ScrollBar always visible. Also note that I resize the ScrollBar to 20 pixels and that I shrunk the content within by 20 pixels:
import QtQuick
import QtQuick.Controls
Page {
ScrollView {
id: scrollView
anchors.fill: parent
ScrollBar.vertical.policy: ScrollBar.AlwaysOn
ScrollBar.vertical.width: 20
TextEdit {
id: textEdit
width: scrollView.width - 20
text: `
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus vel sagittis tellus. Aliquam rhoncus laoreet mi at varius. Phasellus et nisl quam. Duis luctus porta quam, a vehicula erat aliquet sed. Quisque viverra erat risus, vitae congue libero vestibulum vel. Mauris vel interdum purus. Aliquam mauris justo, pellentesque vel sagittis ac, placerat nec enim. Nulla gravida non libero non mollis. Donec sodales ornare tincidunt. Vivamus mattis augue quis justo convallis, molestie tempus velit sollicitudin. Suspendisse potenti. Fusce ut nibh et odio mattis semper at sit amet elit. Nullam pharetra augue nisi, at vestibulum magna dignissim sit amet. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nunc mattis congue magna at laoreet. Vestibulum tincidunt ante ligula, sit amet lacinia orci suscipit ac.
`.repeat(5)
wrapMode: Text.WordWrap
}
}
}
You can Try it Online!
Here's an example usage of Flickable. Note that the Flickable must set:
contentWidth and contentHeight correctly else you will not get a flickable action
note the optional setting of a ScrollBar of 20 pixels and that I shrink the content by the same amount
also note the optional setting of clip: true
again I've only constrained the width of the child but not the height, allowing it to grow
import QtQuick
import QtQuick.Controls
Page {
Flickable {
id: flickable
anchors.fill: parent
contentWidth: textEdit.width
contentHeight: textEdit.height
clip: true
ScrollBar.vertical: ScrollBar {
width: 20
policy: ScrollBar.AlwaysOn
}
TextEdit {
id: textEdit
width: flickable.width - 20
text: `
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus vel sagittis tellus. Aliquam rhoncus laoreet mi at varius. Phasellus et nisl quam. Duis luctus porta quam, a vehicula erat aliquet sed. Quisque viverra erat risus, vitae congue libero vestibulum vel. Mauris vel interdum purus. Aliquam mauris justo, pellentesque vel sagittis ac, placerat nec enim. Nulla gravida non libero non mollis. Donec sodales ornare tincidunt. Vivamus mattis augue quis justo convallis, molestie tempus velit sollicitudin. Suspendisse potenti. Fusce ut nibh et odio mattis semper at sit amet elit. Nullam pharetra augue nisi, at vestibulum magna dignissim sit amet. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nunc mattis congue magna at laoreet. Vestibulum tincidunt ante ligula, sit amet lacinia orci suscipit ac.
`.repeat(5)
wrapMode: Text.WordWrap
}
}
}
You can Try it Online!
You figured it out yourself already. I just add here what I've come up with. Because I didn't fully understand what you were trying to do I made different version of ScrollViews. As Stephen already said you anchor filled the StackLayout in the ScrollView which essentially makes it non scroll able as the StackLayout gets the same size as the ScrollView.
I came up with 4 solutions.
Scroll through a StackLayout via a ScrollBar.
Use a ScrollView with content.
Use a ScrollView around a StackLayout. In order to keep the height of the StackLayout correct it needs to be bound to the current item shown in the StackView. Otherwise it is as big as the biggest item in the layout.
The proper way which you came up with already to have ScrollView
per item in the StackLayout.
These are all the solutions in one application.
import QtQuick
import QtQuick.Controls.Basic
import QtQuick.Layouts
Window {
width: 800
height: 600
visible: true
title: qsTr("Hello StackLayout")
component Content : Rectangle {
color: "gray"
border { width: 1; color: "black" }
Text { text: index; font.pixelSize: 80; anchors.centerIn: parent}
}
// --- Solution 1 ---
Item {
id: frame
width: 400; height: 300
StackLayout {
id: stackLayout
anchors.fill: parent
Repeater {
id: repeater1
model: 5
delegate: Content {}
}
}
ScrollBar {
id: hbar
policy: ScrollBar.AlwaysOn
orientation: Qt.Vertical
size: 1.0 / repeater1.count
anchors.top: parent.top
anchors.right: parent.right
anchors.bottom: parent.bottom
onPositionChanged: {
let i = Math.floor((hbar.position / hbar.size) + 0.5)
if (i !== stackLayout.currentIndex)
stackLayout.currentIndex = i
}
}
}
// --- Solution 2 ---
ScrollView {
id: scrollView
anchors.left: frame.right
width: 400; height: 300
ColumnLayout {
spacing: 0
Repeater {
model: 5
delegate: Content { width: 400; height: 300 }
}
}
}
// --- Solution 3 ---
Item {
id: frame3
anchors.top: frame.bottom
width: 400; height: 300
TabBar {
id: bar
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
Repeater {
model: 5
TabButton { text: index }
}
}
ScrollView {
anchors.left: parent.left
anchors.right: parent.right
anchors.top: bar.bottom
anchors.bottom: parent.bottom
StackLayout {
currentIndex: bar.currentIndex
implicitHeight: repeater3.itemAt(bar.currentIndex).implicitHeight
Repeater {
id: repeater3
model: 5
delegate: Content { width: 400; implicitHeight: 200 * (index + 1) }
}
}
}
}
// --- Solution 4 ---
Item {
anchors.top: scrollView.bottom
anchors.left: frame3.right
width: 400; height: 300
TabBar {
id: bar2
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
Repeater {
model: 5
TabButton { text: index }
}
}
StackLayout {
anchors.left: parent.left
anchors.right: parent.right
anchors.top: bar2.bottom
anchors.bottom: parent.bottom
currentIndex: bar2.currentIndex
Repeater {
model: 5
delegate: ScrollView {
Content { width: 400; implicitHeight: 200 * (index + 1) }
}
}
}
}
}
I want to make Dialog with only 1 button ("OK"). But when I use "standardButtons: Dialog.Ok" it positions it to the right. How it may be positioned in the middle? I would like to keep current button dimensions.
I've tried to use DialogButtonBox, and also Rectangle and Buttons in footer, but every time it not worked, or look like a mess
Code:
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
Window {
id: window
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Button {
id: button
text: qsTr("Button")
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
onClicked: dialog.open()
}
Dialog {
id: dialog
modal: true
font.bold: true
title: "WARNING!!!"
Text {
id: dialogMessage
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, \nsed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
horizontalAlignment: Text.AlignHCenter
}
parent: Overlay.overlay
x: parent.width/2 - width/2
y: parent.height/2 - height/2
standardButtons: Dialog.Ok
}
}
There are a few options:
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
Window {
id: window
width: 640
height: 480
visible: true
Dialog {
id: dialog
x: parent.width/2 - width/2
y: parent.height/2 - height/2
parent: Overlay.overlay
modal: true
font.bold: true
title: "WARNING!!!"
standardButtons: Dialog.Ok
visible: true
Text {
id: dialogMessage
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, \nsed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
horizontalAlignment: Text.AlignHCenter
}
// Declare your own DialogButtonBox.
footer: DialogButtonBox {
alignment: Qt.AlignHCenter
}
// Assign it declaratively.
// Binding {
// target: dialog.footer
// property: "alignment"
// value: Qt.AlignHCenter
// }
// Assign it imperatively.
// Component.onCompleted: dialog.footer.alignment = Qt.AlignHCenter
}
}
I've left the other ones commented out to illustrate that you only need one of these approaches.
Note that you can't just do:
footer.alignment: Qt.AlignHCenter
because the type of the footer property is Item, not DialogButtonBox, and Item doesn't have an alignment property.
Consider using Column Layout, it will keep the dialog in shape. Also use both Layout.alignment and alignment property in the DialogButtonBox - the dialog will look just as You wish:
Dialog {
id: dialog
modal: true
font.bold: true
visible: true
title: "WARNING!!!"
ColumnLayout {
Text {
id: dialogMessage
Layout.alignment: Qt.AlignHCenter
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, \nsed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
}
DialogButtonBox{
standardButtons: DialogButtonBox.Ok
Layout.alignment: Qt.AlignHCenter
alignment: Qt.AlignHCenter
onAccepted: dialog.close()
}
}
}
The problem is the following:
If the length of the text is longer than the width of the cell, the text is wrapped, but the height of the row is not increased. which displays the rest of the text chopped. My other question is, how to adapt the height of each cell to the text contained in it?
Here's the QML part:
Window {
id: window
visible: true
width: 440
height: 400
title: qsTr("Table test")
ListModel {
id: stringsModel
ListElement {
ID: 0
String: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam'
}
ListElement {
ID: 1
String: 'This is a test string'
}ListElement {
ID: 1
String: 'This is another test string'
}
}
TableView {
anchors.fill: parent
frameVisible: false
model: stringsModel
TableViewColumn { role: "ID"; title: "ID"; width: window.width / 2 }
TableViewColumn { role: "String"; title: "String"; width: window.width / 2; delegate: stringDelegate;}
Component {
id: stringDelegate
Item {
id: stringItem
Text {
id: stringTxt
width: parent.width
text: styleData.value
wrapMode: TextEdit.WordWrap
}
}
}
}
}
Your delegate's root item should define its implicitHeight property.
Something like this:
Component {
id: stringDelegate
Item {
id: stringItem
implicitHeight: stringTxt.paintedHeight
Text {
id: stringTxt
width: parent.width
text: styleData.value
wrapMode: TextEdit.WordWrap
}
}
}
I need to create nested list view and as shown below, and highlight the main list and sub-list with different color
I have tried with ListView highlight but there are issue like the highlight showing for child as well as parent as shown
below image.
I am using the code from here with some minor modification.
Here is the full code
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick 2.2
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.1
ApplicationWindow {
id: loginWindow
//visibility: "Maximized"
visible: true
width: 720
height: 720
Item {
width: 200
height: 720
ListView {
id: list
anchors.fill: parent
model: nestedModel
delegate: categoryDelegate
highlight: Rectangle {
color: "#FF00AAFF" //"#FF59ACFF";
radius: 2
}
}
ListModel {
id: nestedModel
ListElement {
categoryName: "Veggies"
collapsed: true
// A ListElement can't contain child elements, but it can contain
// a list of elements. A list of ListElements can be used as a model
// just like any other model type.
subItems: [
ListElement {
itemName: "Tomato"
},
ListElement {
itemName: "Cucumber"
},
ListElement {
itemName: "Onion"
},
ListElement {
itemName: "Brains"
}
]
}
ListElement {
categoryName: "Fruits"
collapsed: true
subItems: [
ListElement {
itemName: "Orange"
},
ListElement {
itemName: "Apple"
},
ListElement {
itemName: "Pear"
},
ListElement {
itemName: "Lemon"
}
]
}
ListElement {
categoryName: "Cars"
collapsed: true
subItems: [
ListElement {
itemName: "Nissan"
},
ListElement {
itemName: "Toyota"
},
ListElement {
itemName: "Chevy"
},
ListElement {
itemName: "Audi"
}
]
}
}
Component {
id: categoryDelegate
Column {
width: 200
Rectangle {
id: categoryItem
border.color: "black"
border.width: 5
color: "#33FF5225"
height: 50
width: 200
Text {
anchors.verticalCenter: parent.verticalCenter
x: 15
font.pixelSize: 24
text: categoryName
}
Rectangle {
color: "red"
width: 30
height: 30
anchors.right: parent.right
anchors.rightMargin: 15
anchors.verticalCenter: parent.verticalCenter
MouseArea {
anchors.fill: parent
// Toggle the 'collapsed' property
onClicked: {
list.currentIndex = index
nestedModel.setProperty(index, "collapsed",
!collapsed)
}
}
}
}
Loader {
id: subItemLoader
// This is a workaround for a bug/feature in the Loader element. If sourceComponent is set to null
// the Loader element retains the same height it had when sourceComponent was set. Setting visible
// to false makes the parent Column treat it as if it's height was 0.
visible: !collapsed
property variant subItemModel: subItems
sourceComponent: collapsed ? null : subItemColumnDelegate
onStatusChanged: if (status == Loader.Ready) item.model = subItemModel
}
}
}
Component {
id: subItemColumnDelegate
Column {
property alias model: subItemRepeater.model
width: 200
Repeater {
id: subItemRepeater
delegate: Rectangle {
x: 10
color: "#33FF5225"
height: 40
width: 190
border.color: "black"
border.width: 2
Text {
anchors.verticalCenter: parent.verticalCenter
x: 30
font.pixelSize: 18
text: itemName
}
}
}
}
}
}
}
How can I overcome this issue. Basically I need to highlight Parent and child Item with different color.
Edit:
I can highlight parent list using the code
color:categoryDelegate.ListView.isCurrentItem ? "#FF00AAFF" : "#CCBBBBBB"
but coud'nt a find similar way to change the color of child list (sub list) on click.
Change the color property of the delegate in subItemRepeater to your choice.
Example
Component {
id: subItemColumnDelegate
Column {
...
Repeater {
id: subItemRepeater
delegate: Rectangle {
...
color: "purple"
...
}
}
}
}
Similarly change the color property categoryItem in the categoryDelegate.
Example
Component {
id: categoryDelegate
Column {
...
Rectangle {
id: categoryItem
...
color: "blue"
...
}
}
}
EDIT:
In that case the the overall concept is wrong. In the comment of the original code the author has written A ListElement can't contain child elements, but it can contain a list of elements. So we can't highlight the child item. But the following approach will give good result to you.
import QtQuick 2.0
Rectangle {
width: 360
height: 360
ListModel {
id: model1
ListElement {
name: "name"
}
ListElement {
name: "name"
}
ListElement {
name: "name"
}
}
ListModel {
id: model2
ListElement {
name: "inside"
}
ListElement {
name: "inside"
}
ListElement {
name: "inside"
}
}
ListView {
id: outer
model: model1
delegate: listdelegate
anchors.fill: parent
}
Component {
id: listdelegate
Item {
width: 100
height: col.childrenRect.height
Column {
id: col
anchors.left: parent.left
anchors.right: parent.right
Text {
id: t1
text: name
}
ListView {
id: insidelist
model: model2
property int collapseHeightFlag: childrenRect.height
delegate: Component {
id: delegate2
Item {
width: 100
height: col2.childrenRect.height
Column {
id: col2
anchors.left: parent.left
anchors.right: parent.right
Text {
id: name1
text: name
}
}
MouseArea {
anchors.fill: parent
onClicked: {
insidelist.currentIndex = index;
}
}
}
}
contentHeight: contentItem.childrenRect.height
height: 0
anchors.left: parent.left
anchors.right: parent.right
clip: true
highlight: Rectangle {
color: "pink"
radius: 2
}
focus: true
}
}
Rectangle {
color: "red"
width: 10
height: 10
anchors.right: parent.right
anchors.rightMargin: 5
anchors.top: parent.top
anchors.topMargin: 5
MouseArea {
anchors.fill: parent
onClicked: {
if(insidelist.height === insidelist.collapseHeightFlag) {
insidelist.height = 0;
}
else
insidelist.height = insidelist.collapseHeightFlag;
}
}
}
}
}
}
I'm trying to develop an application which has multi-layered navigation in drop-downs.
Below is the snapshot of the requirement. On clicking QSR only the subitems of QSR should pop out with proper alignment.
But with my implementation, I'm getting following result. The pop out window is not aligned, but extending itself to the list.
Below is the my code snippet
import QtQuick 1.1
Item {
width: 500
height: 300
ListView {
anchors.fill: parent
model: nestedModel
delegate: categoryDelegate
}
ListModel {
id: nestedModel
ListElement {
categoryName: "QSR"
collapsed: true
subItems: [
ListElement { itemName: "KFC" },
ListElement { itemName: "Mc Donalds" },
ListElement { itemName: "Pizza Hut" },
ListElement { itemName: "Brain's" }
]
}
ListElement {
categoryName: "Drinks"
collapsed: true
subItems: [
ListElement { itemName: "Pepsi" },
ListElement { itemName: "Coke" },
ListElement { itemName: "7up" },
ListElement { itemName: "Bacardi" }
]
}
}
Component {
id: categoryDelegate
Column {
width: 200
Rectangle {
id: categoryItem
border.color: "black"
border.width: 5
color: "white"
height: 50
width: 200
anchors.left: parent.right
Text {
anchors.right: parent.right
x: 15
font.pixelSize: 24
text: categoryName
}
MouseArea {
anchors.fill: parent
onClicked: nestedModel.setProperty(index, "collapsed", !collapsed)
}
}
Loader {
id: subItemLoader
visible: !collapsed
property variant subItemModel : subItems
sourceComponent: collapsed ? null : subItemColumnDelegate
onStatusChanged: if (status == Loader.Ready) item.model = subItemModel
}
}
}
Component {
id: subItemColumnDelegate
Column {
property alias model : subItemRepeater.model
width: 200
Repeater {
id: subItemRepeater
delegate: Rectangle {
color: "#cccccc"
height: 40
width: 200
border.color: "black"
border.width: 2
Text {
anchors.verticalCenter: parent.verticalCenter
x: 30
font.pixelSize: 18
text: itemName
}
}
}
}
}
}
Any help to achieve original requirement will be appreciable.
Have a close look at the delegate for your main list view: It's Column (put items on top of each over) of the main menu item and Loader for the popup menu. Obviously as soon as you load a popup menu it's displayed under its corresponding menu item in the list.
To get the behavior you intended you have to move the Loader for the popup menu out of the ListView:
import QtQuick 1.1
Item {
width: 400
height: 300
Row {
anchors.fill: parent
Loader {
id: subItemLoader
width: 200
height: parent.height
property variant subItemModel: null
sourceComponent: subItemModel == null? null: subItemColumnDelegate
function setModel() {
if (status == Loader.Ready) item.model = subItemModel
}
onStatusChanged: setModel()
onSubItemModelChanged: setModel()
}
ListView {
width: 200
height: parent.height
model: nestedModel
delegate: categoryDelegate
}
}
ListModel {
id: nestedModel
ListElement {
categoryName: "QSR"
subItems: [
ListElement { itemName: "KFC" },
ListElement { itemName: "Mc Donalds" },
ListElement { itemName: "Pizza Hut" },
ListElement { itemName: "Brain's" }
]
}
ListElement {
categoryName: "Drinks"
subItems: [
ListElement { itemName: "Pepsi" },
ListElement { itemName: "Coke" },
ListElement { itemName: "7up" },
ListElement { itemName: "Bacardi" }
]
}
}
Component {
id: categoryDelegate
Rectangle {
id: categoryItem
border.color: "black"
border.width: 5
color: "white"
height: 50
width: 200
Text {
anchors.centerIn: parent
x: 15
font.pixelSize: 24
text: categoryName
}
MouseArea {
anchors.fill: parent
onClicked: {
if (subItemLoader.subItemModel != subItems)
subItemLoader.subItemModel = subItems
else
subItemLoader.subItemModel = null
}
}
}
}
Component {
id: subItemColumnDelegate
Column {
property alias model : subItemRepeater.model
width: 200
height: 500
Repeater {
id: subItemRepeater
delegate: Rectangle {
color: "#cccccc"
height: 40
width: 200
border.color: "black"
border.width: 2
Text {
anchors.verticalCenter: parent.verticalCenter
x: 30
font.pixelSize: 18
text: itemName
}
}
}
}
}
}