I was working with a GridView in QML. When I click on an element, I want to following highlight to happen:
However, my problem is that I want the blue color to appear below the delegate (not in the white area but still visible on the transparent side part) while the checkmark appears above (so it is visible). I have tried playing around with the z values so that the lowest z should be the blue rectangle, the middle should be the white rectangle part of the delegate, and the highest should be the check mark but i can't seem to make it work. Either the highlight or the delegate has to be on top. Does anyone know any way I can fix this so that it works correctly?
Code for highlight:
highlight:
Rectangle {
z:5
color: "steelblue"; radius: 5; opacity: 0.5
Image{
z:8
id: checkMark
visible: found;
x: parent.width-8-width
y: 8
width: 40;
height: 40;
source: "file:///Users/arjun/Documents/CompetitiveBall/images/checkMark.png"
}
}
Code for delegate:
Component {
id: contactsDelegate
Rectangle{
width: grid.cellWidth
height: grid.cellHeight
color: "transparent"
Rectangle {
z:7
width: grid.cellWidth-20
height: grid.cellHeight-20
id: wrapper
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
border.width: 3
border.color: "black"
radius: 5;
Image{
id: mImage
x:parent.x
width: 65
height:65;
source: picSource
}
Text{
width: grid.cellWidth-15
y: mImage.y+mImage.height+4
anchors.horizontalCenter: parent.horizontalCenter
id: nameText
text: name
font.family: "Palatino Linotype"
font.bold: (grid.isCurrentItem===true)?"true":"false"
horizontalAlignment: Text.AlignHCenter
color:"#050027"
}
MouseArea{
anchors.fill: parent
onClicked:{
console.log("Clicked on :" + name)
//what happens when u click
grid.currentIndex=index;
}
}
}
}
}
Since you want part of the highlight to be underneath the delegate and part of it to be on top, you need to break it up into different pieces. I tested the code below with Qt 5.15.0. I made the normal highlight object draw underneath the delegate. Then I added another Rectangle that follows the highlight that draws on top of the delegate.
GridView
{
id: lv
anchors.fill: parent
anchors.margins: 50
cellWidth: 50
cellHeight: 50
model: 30
// By default, highlight draws behind delegates
// (You can specify a positive z-value to make it draw on top)
highlight: Item
{
Rectangle
{
anchors.centerIn: parent
width: 50
height: 50
color: "green"
}
}
delegate: Rectangle
{
width: 30
height: 30
color: "red"
MouseArea
{
anchors.fill: parent
onClicked: lv.currentIndex = index;
}
}
// This will draw on top of the delegates
// (You can change that by specifying a negative z-value.)
Rectangle
{
id: checkbox
x: lv.highlightItem.x - lv.contentX
y: lv.highlightItem.y - lv.contentY
width: 10
height: 10
color: "blue"
}
}
Related
In the below sample code, I set z property for the highlight item and depending on the value, it shows up to the user. The z property can also be configured with real value.
It means z value can have fractional values such as 0.1 or 1.2, like that.
Can anyone explain the purpose of z value should be fractional or real value in QML ListView?
import QtQuick 2.8
import QtQuick.Window 2.2
Window {
visible: true
width: 640
height: 480
title: qsTr("Sample List View")
property var delHeight: 50
ListView {
id: listView
anchors.fill: parent
cacheBuffer: 100
footer: Rectangle {
width: (listView.orientation === ListView.Horizontal) ? 200 : parent.width
height: delHeight
color: "lightyellow"
Text {
anchors.centerIn: parent
font.pointSize: 20
text: "Footer"
}
}
header: Rectangle {
width: (listView.orientation === ListView.Horizontal) ? 200 : parent.width
height: delHeight
color: "lightblue"
Text {
anchors.centerIn: parent
font.pointSize: 20
text: "Header"
}
z: 2
}
headerPositioning: ListView.OverlayHeader
highlight: Rectangle {
color: "white"
opacity: 0.5
border.color: "blue"
border.width: 5
z: 1.2
Component.onCompleted: {
console.log ("Created hightlight component with z factor: " + z)
}
}
// highlightMoveDuration: 10000
// highlightRangeMode: ListView.ApplyRange
keyNavigationEnabled: true
model: 20
delegate: componentId
layoutDirection: Qt.RightToLeft
orientation: ListView.Vertical
snapMode: ListView.SnapOneItem
Component.onCompleted: {
currentIndex = 5
}
focus: true
onFocusChanged: {
console.log ("Focus: " + focus)
}
}
Component {
id: componentId
Rectangle {
width: (listView.orientation === ListView.Horizontal) ? 200 : parent.width
height: delHeight
color: "lightgreen"
border.color: "black"
border.width: (listView.currentIndex === index) ? 5 : 1
Text {
anchors.centerIn: parent
font.pointSize: 20
text: "Element: " + index
}
MouseArea {
anchors.fill: parent
onClicked: {
listView.currentIndex = index
}
}
Component.onCompleted: {
console.log ("Created component: " + index)
}
Component.onDestruction: {
console.log ("Destroyed component: " + index)
}
}
}
}
The z property of an item gives the stacking order to that item.
Meaning, if you are constructing two Rectangles one after the other than recently constructed rectangle will be stacked on top the previously constructed one.
Ex code:
Item {
Rectangle {
color: "red"
width: 100; height: 100
}
Rectangle {
color: "blue"
x: 50; y: 50; width: 100; height: 100
}
}
Here red rectangle stacked below blue rectangle.
Now QML gives you chance to change the stacking order through z property of the item.
in the above example if I assign z property of the red rectangle to have a value of anything above 0, I would see it on top of blue rectangle. So z property has changed the stacking order for the sibling item.
The purpose of the z property stays the same in case of ListView highlight. When you want to see the highlight item then you have to give it a value which is greater than the items which will be constructed. You can check this by just setting z property for the componentIds rectangle to some higher value than highlights z value.
NOTE: it only works for sibling items.
More explanation can be found here
Read about the real type here
I'm trying to make my horizontal rectangle to drop a shadow. When I do it with the code below, the rectangle duplicates, so that there are two horizontal rectangles in two rows. It's shown in the image (the duplicated one is white). How can I get rid of the duplicated rectangle so that just the shadow and the original rectangle remain?
Window {
visible: true
width: 640
height: 480
color: "white"
Item {
anchors.fill: parent
ColumnLayout {
id: layout
anchors.fill: parent
spacing: 0
Rectangle {
id: bar
color: "blue"
height: 40
Layout.fillWidth: true
}
DropShadow {
anchors.fill: bar
horizontalOffset: 0
verticalOffset: 3
radius: 8.0
samples: 12
source: bar
color: "blue"
}
Rectangle {
Layout.fillHeight: true
Layout.preferredWidth: parent.width
color: "grey"
}
}
}
}
There is no duplicate rectangle, there is just a gap. You are using a layout, which will lay its containing items out based on their size. You do anchor the shadow to fill the rectangle, so that's where it is, but the layout is not supposed to be used in such a format, therefore it leaves an empty space where the shadow is supposed to go before placing the grey rectangle.
And the shadow doesn't show if you get rid of the gap because the grey rectangle is on top of it. Tinkering with the z value doesn't seem to help either. It might have to do with using a layout.
You can get the desired result if you get rid of the layout and use anchoring, which allows you to put the grey rectangle first, so it can be under the shadow.
Item {
anchors.fill: parent
Rectangle {
anchors.bottom: parent.bottom
anchors.top: bar.bottom
width: parent.width
color: "grey"
}
Column { // or you can put the layout here if you want
id: bar
anchors.top: parent.top
width: parent.width
Rectangle {
color: "blue"
height: 40
width: parent.width
}
// other stuff
}
DropShadow {
anchors.fill: bar
horizontalOffset: 0
verticalOffset: 3
radius: 8.0
samples: 12
source: bar
color: "blue"
}
}
Create DropShadow as Rectangle child:
Item {
ColumnLayout {
id: layout
anchors.fill: parent
spacing: 0
Rectangle {
id: bar
color: "blue"
height: 40
Layout.fillWidth: true
...
... // some buttons, images etc.
DropShadow {
anchors.fill: parent
horizontalOffset: 0
verticalOffset: 3
radius: 8.0
samples: 12
source: bar
color: "blue"
}
}
...
... // some other components to the layout ...
}
}
Also you can assign DropShadow object to layer.effect Property:
Item {
ColumnLayout {
id: layout
anchors.fill: parent
spacing: 0
Rectangle {
id: bar
color: "blue"
height: 40
Layout.fillWidth: true
...
... // some buttons, images etc.
layer.enabled: true // Set Layer for Enable
layer.effect: DropShadow {
horizontalOffset: 0
verticalOffset: 3
radius: 8.0
samples: 12
source: bar
color: "blue"
}
}
...
... // some other components to the layout ...
}
}
I want to create an animated accordion-like element that expands on click. Here's how it should work.
When the user clicks one of the red rectangles, the green rectangle which is the actual content, should expand. I want this expansion to be animated. The height of the contents of the green rectangles could be different for each red header.
I have been able to implement the click-to-expand behavior, but there's no animation. Here is the code I currently have.
AccordionElement.qml
import QtQuick 2.5
import QtQuick.Layouts 1.1
ColumnLayout {
id: rootElement
property string title: ""
property bool isOpen: false
default property alias accordionContent: contentPlaceholder.data
anchors.left: parent.left; anchors.right: parent.right
// Header element
Rectangle {
id: accordionHeader
color: "red"
anchors.left: parent.left; anchors.right: parent.right
height: 50
MouseArea {
anchors.fill: parent
Text {
text: rootElement.title
anchors.centerIn: parent
}
cursorShape: Qt.PointingHandCursor
onClicked: {
rootElement.isOpen = !rootElement.isOpen
}
}
}
// This will get filled with the content
ColumnLayout {
id: contentPlaceholder
visible: rootElement.isOpen
anchors.left: parent.left; anchors.right: parent.right
}
}
And this is how it is used from the parent element:
Accordion.qml
ColumnLayout {
Layout.margins: 5
visible: true
AccordionElement {
title: "Title1"
accordionContent: Rectangle {
anchors.left: parent.left; anchors.right: parent.right
height: 20
color: "green"
}
}
AccordionElement {
title: "Title2"
accordionContent: Rectangle {
anchors.left: parent.left; anchors.right: parent.right
height: 50
color: "green"
}
}
AccordionElement {
title: "Title3"
accordionContent: Rectangle {
anchors.left: parent.left; anchors.right: parent.right
height: 30
color: "green"
}
}
// Vertical spacer to keep the rectangles in upper part of column
Item {
Layout.fillHeight: true
}
}
This produces the following result (when all rectangles are expanded):
Ideally I would like the green rectangles to roll out of the red rectangles (like paper out of a printer). But I am stuck on how to do this. I have tried several approaches using the height property, and I got the green rectangle to disappear but the white space remains under the red rectangle.
Any help would be appreciated. Is there an approach I'm missing?
Here is a quick and simple example:
// AccItem.qml
Column {
default property alias item: ld.sourceComponent
Rectangle {
width: 200
height: 50
color: "red"
MouseArea {
anchors.fill: parent
onClicked: info.show = !info.show
}
}
Rectangle {
id: info
width: 200
height: show ? ld.height : 0
property bool show : false
color: "green"
clip: true
Loader {
id: ld
y: info.height - height
anchors.horizontalCenter: info.horizontalCenter
}
Behavior on height {
NumberAnimation { duration: 200; easing.type: Easing.InOutQuad }
}
}
}
// Acc.qml
Column {
spacing: 5
AccItem {
Rectangle {
width: 50
height: 50
radius: 50
color: "blue"
anchors.centerIn: parent
}
}
AccItem {
Rectangle {
width: 100
height: 100
radius: 50
color: "yellow"
anchors.centerIn: parent
}
}
AccItem {
Rectangle {
width: 75
height: 75
radius: 50
color: "cyan"
anchors.centerIn: parent
}
}
}
You are needlessly over-complicating it with the anchors and the layouts. It doesn't seem the problem calls for any of those.
Update: I slightly refined the implementation, compared to the initial one the content would actually slide out of the header as paper out of printer rather than simply being unveiled, and also removed the source of a false positive binding loop warning.
I want to create an animated accordion-like element that expands on click. Here's how it should work.
When the user clicks one of the red rectangles, the green rectangle which is the actual content, should expand. I want this expansion to be animated. The height of the contents of the green rectangles could be different for each red header.
I have been able to implement the click-to-expand behavior, but there's no animation. Here is the code I currently have.
AccordionElement.qml
import QtQuick 2.5
import QtQuick.Layouts 1.1
ColumnLayout {
id: rootElement
property string title: ""
property bool isOpen: false
default property alias accordionContent: contentPlaceholder.data
anchors.left: parent.left; anchors.right: parent.right
// Header element
Rectangle {
id: accordionHeader
color: "red"
anchors.left: parent.left; anchors.right: parent.right
height: 50
MouseArea {
anchors.fill: parent
Text {
text: rootElement.title
anchors.centerIn: parent
}
cursorShape: Qt.PointingHandCursor
onClicked: {
rootElement.isOpen = !rootElement.isOpen
}
}
}
// This will get filled with the content
ColumnLayout {
id: contentPlaceholder
visible: rootElement.isOpen
anchors.left: parent.left; anchors.right: parent.right
}
}
And this is how it is used from the parent element:
Accordion.qml
ColumnLayout {
Layout.margins: 5
visible: true
AccordionElement {
title: "Title1"
accordionContent: Rectangle {
anchors.left: parent.left; anchors.right: parent.right
height: 20
color: "green"
}
}
AccordionElement {
title: "Title2"
accordionContent: Rectangle {
anchors.left: parent.left; anchors.right: parent.right
height: 50
color: "green"
}
}
AccordionElement {
title: "Title3"
accordionContent: Rectangle {
anchors.left: parent.left; anchors.right: parent.right
height: 30
color: "green"
}
}
// Vertical spacer to keep the rectangles in upper part of column
Item {
Layout.fillHeight: true
}
}
This produces the following result (when all rectangles are expanded):
Ideally I would like the green rectangles to roll out of the red rectangles (like paper out of a printer). But I am stuck on how to do this. I have tried several approaches using the height property, and I got the green rectangle to disappear but the white space remains under the red rectangle.
Any help would be appreciated. Is there an approach I'm missing?
Here is a quick and simple example:
// AccItem.qml
Column {
default property alias item: ld.sourceComponent
Rectangle {
width: 200
height: 50
color: "red"
MouseArea {
anchors.fill: parent
onClicked: info.show = !info.show
}
}
Rectangle {
id: info
width: 200
height: show ? ld.height : 0
property bool show : false
color: "green"
clip: true
Loader {
id: ld
y: info.height - height
anchors.horizontalCenter: info.horizontalCenter
}
Behavior on height {
NumberAnimation { duration: 200; easing.type: Easing.InOutQuad }
}
}
}
// Acc.qml
Column {
spacing: 5
AccItem {
Rectangle {
width: 50
height: 50
radius: 50
color: "blue"
anchors.centerIn: parent
}
}
AccItem {
Rectangle {
width: 100
height: 100
radius: 50
color: "yellow"
anchors.centerIn: parent
}
}
AccItem {
Rectangle {
width: 75
height: 75
radius: 50
color: "cyan"
anchors.centerIn: parent
}
}
}
You are needlessly over-complicating it with the anchors and the layouts. It doesn't seem the problem calls for any of those.
Update: I slightly refined the implementation, compared to the initial one the content would actually slide out of the header as paper out of printer rather than simply being unveiled, and also removed the source of a false positive binding loop warning.
I'm new of qml.
I'm starting to develop a little application with a custom item.
when I try to use in application anchor.top: first_item.bottom, to position the rectangles of the custom component, one below the other doesn't work.
content file main.qml:
import QtQuick 2.5
Item
{
id:main_screen
Rectangle
{
width: 300
height: 60
id: text_content
color: "DarkGray"
opacity: 0.9
border.color: "blue"
border.width: 3
radius: 5
z:6
Text {
id: titleText
width: parent.width
height: parent.height
font.pointSize: 20
font.family: "Arial"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text: "Test - title"
color: "White"; style: Text.Raised;
}
}
//..................This rectangle is shown below main_screen... so is OK
Custom_item
{
id:first_item
anchors.top: main_screen.bottom
}
//..................This rectangle is not shown below first_item... but it shown on absolute top, in overlap of retangle title
Custom_item
{
id:second_item
anchors.top: first_item.bottom
}
//..................This rectangle is not shown below second_item... but it shown on absolute top, in overlap of retangle title
Custom_item
{
id:third_item
anchors.top: second_item.bottom
}
}
content file Custom_item.qml
import QtQuick 2.5
Item
{
id:testComponent
Rectangle
{
width: 300
height: 60
id: text_content
color: "DarkGray"
opacity: 0.9
border.color: "blue"
border.width: 3
radius: 5
z:6
}
}
what am I doing wrong ?
Thanks
The problem lies within the dimensions of the objects your are anchoring to.
Though the Rectangles have a width and a height, the enclosing Item has none, so it is basically 0 pixels in height and width, while the Rectangle protrudes it.
If you don't have any reason for enclosing the Rectangle within the Item, I'd reccomend you, to take the Rectangle itself as the toplevel element of the file.
Reasons for having the Item might be those:
Hiding the Rectangles properties
Having multiple children for the Item that are logically siblings to the Rectangle
... other reasons might exist ;-)
Nevertheless, you need to make sure, that the toplevel item has always the right dimensions. So you should set the width and height, better the implicitWidth and implicitHeight in component declarations.
Example 1: Without an Item
import QtQuick 2.5
Rectangle {
id: root
width: 300
height: 60
color: "DarkGray"
opacity: 0.9
border.color: "blue"
border.width: 3
radius: 5
z:6
}
Example 2: With Item
import QtQuick 2.5
Item {
id:testComponent
implicitHeight: 60 // < This
implicitWidth: 300 // < and that are important to have the dimensions
Rectangle {
id: text_content
anchors.fill: parent
color: "DarkGray"
opacity: 0.9
border.color: "blue"
border.width: 3
radius: 5
z:6
}
}
You are anchoring all the Rectangle's to the Item hence you are not getting the desired result. Simple change the id of the top Rectangle as follows
Item
{
id: root
Rectangle
{
id:main_screen
...
}
}