Trying to center items programmatically in a ListView - qt

I would like to have centered items in QML ListView and therefore I've added following code of my ListView:
import QtQuick 2.0
import QtMultimedia 5.5
import QtQuick.Controls 1.3
import QtQuick.Extras 1.4
import QtQuick.Layouts 1.2
import QtQuick.Window 2.2
import QtTest 1.1
Rectangle {
id: ueKeypad
width: ueMainColumnLayout.implicitWidth+2*radius
height: ueMainColumnLayout.implicitHeight+2*radius
color: "grey"
radius: 8
border.color: "#99c6f0"
border.width: 4
ColumnLayout {
id: ueMainColumnLayout
anchors.fill: parent
anchors.margins: radius
spacing: 4
RowLayout {
id: ueTextLayout
Text {
id: ueStaffLoginText
text: qsTr("Staff Login")
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
font.family: "Padauk"
textFormat: Text.RichText
font.pointSize: 16
font.bold: true
color: ueKeypad.border.color
Layout.fillWidth: true
} // ueStaffLoginText
} // ueTextLayout
RowLayout {
id: uePeopleViewLayout
ListView {
id: uePeopleView
keyNavigationWraps: true
spacing: 4
antialiasing: true
model: uePeopleModel
Layout.fillWidth: true
Layout.fillHeight: false
//Layout.minimumWidth: 64
Layout.minimumHeight: 64
//Layout.preferredWidth: 96
Layout.preferredHeight: 96
//Layout.maximumWidth: 128
Layout.maximumHeight: 128
orientation: ListView.Horizontal
layoutDirection: Qt.LeftToRight
snapMode: ListView.SnapToItem
highlightRangeMode: ListView.ApplyRange
Component.onCompleted: {
var newIndex=(count%2==0)?(count/2):(Math.round(count/2));
positionViewAtIndex(newIndex, ListView.Center);
currentIndex=newIndex;
print(newIndex)
} // onCompleted - center items
delegate: Rectangle {
id: uePersonDelegate
width: 32
height: 32
ColumnLayout {
id: uePersonDelegateMainLayout
anchors.fill: parent
anchors.margins: radius
RowLayout {
id: uePersonDelegateImageLayout
Image {
id: uePersonImage
antialiasing: true
fillMode: Image.PreserveAspectFit
source: "image://uePeopleModel/"+model.ueRoleImage
} // uePersonImage
} // uePersonDelegateImageLayout
RowLayout {
id: uePersonDelegateNameLayout
Text {
id: ueTextPersonName
color: "#ffffff"
text: model.ueRoleName
font.bold: true
font.pixelSize: 16
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
} // ueTextPersonName
} // uePersonDelegateNameLayout
} // uePersonDelegateMainLayout
} // uePersonDelegate
add: Transition {
NumberAnimation {
property: "opacity";
from: 0;
to: 1.0;
duration: 100
} // NumberAnimation
NumberAnimation {
property: "scale";
from: 0;
to: 1.0;
duration: 100
} // NumberAnimation
} // Transition
displaced: Transition {
NumberAnimation {
properties: "x,y";
duration: 100;
easing.type: Easing.OutBounce
} // NumberAnimation
} // Transition
} // uePeopleView
} // uePeopleViewLayout
RowLayout {
id: ueTumblerLayout
Tumbler {
id: ueLoginKeypadTumbler
Layout.fillWidth: true
Layout.fillHeight: false
height: 100
antialiasing: true
TumblerColumn {
id: ueNumericTumblerColumnDigit1000
model: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
} // ueNumericTumblerColumnDigit1000
TumblerColumn {
id: ueNumericTumblerColumnDigit100
model: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
} // ueNumericTumblerColumnDigit100
TumblerColumn {
id: ueNumericTumblerColumnDigit10
model: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
} // ueNumericTumblerColumnDigit10
TumblerColumn {
id: ueNumericTumblerColumnDigit1
model: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
} // ueNumericTumblerColumnDigit1
} // ueLoginKeypadTumbler
} // ueTumblerLayout
RowLayout {
id: ueButtonsLayout
Button {
id: ueButtonLogin
Layout.fillWidth: true
text: qsTr("Login")
} // ueButtonLogin
Button {
id: ueButtonClear
Layout.fillWidth: true
text: qsTr("Clear")
} // ueButtonClear
Button {
id: ueButtonQuitApp
Layout.fillWidth: true
text: qsTr("Quit")
} // ueButtonQuitApp
} // ueButtonsLayout
} // ueMainColumnLayout
states: [
State {
name: "ueStateLoginOk"
PropertyChanges {
target: ueKeypad
border.color: "#00ff00"
}
PropertyChanges {
target: ueLoginText
color: "#00ff00"
}
}, // ueStateLoginOk
State {
name: "ueStateLoginOkFailed"
PropertyChanges {
target: ueKeypad
border.color: "#ff0000"
}
PropertyChanges {
target: ueLoginText
color: "#ff0000"
}
} // ueStateLoginOkFailed
] // states
} // ueKeypad
Now, print(newIndex) statement prints out correct value 3 (in my case, since at the moment I have 5 items), and I would like the 3rd item to be in the center of ListView and other two items on the left side and the right side. Is this possible? And out of scope of this question, why Transitions also does not work, taken from example?
I've also set highlightRangeMode: ListView.ApplyRange taken from comment hint .
Here is a screenshot of the problem:

The problem here is that you are trying to place ListView delegates according to your needs. That's plain wrong since the ListView (much like all the other views) is meant to do that for you, according to the ListView size. The ListView will always use all the available space, resulting in the delegates all positioned to the left, as you experienced.
Instead of forcing the behaviour on the delegates, you should constrain the ListView size and position it to be in the center. Then, you can exploit highlightRangeMode with preferredHighlightBegin and preferredHighlightEnd from this answer to ensure the currently selected Item is in the center of the list. Also, by using StrictlyEnforceRange, you can force the selected Item to stay always in the center, which would result in an IMO better way to select the desired Item.
Here is an example implementing this approach. Sizes are hard-coded for simplicity but can be easily parametrised. As said, I went a little bit further by setting the highlighting policy. Hope it helps.
import QtQuick 2.4
import QtQuick.Window 2.2
import QtQuick.Layouts 1.1
Window {
id: win
width: 300
height: 300
visible: true
ColumnLayout {
anchors.fill: parent
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
color: "blue"
}
ListView {
Layout.alignment: Qt.AlignCenter
Layout.minimumWidth: 30 * 5 + 40
Layout.preferredHeight: 50
clip: true
spacing: 15
model: 10
orientation: ListView.Horizontal
delegate: Item {
width: 30
height: 50
Rectangle{
anchors.centerIn: parent
color: parent.ListView.isCurrentItem ? "red" : "steelblue"
width: 30
height: 30
Text {
text: index
anchors.centerIn: parent
}
scale: parent.ListView.isCurrentItem ? 1.5 : 1
Behavior on scale { NumberAnimation { duration: 200 } }
}
}
preferredHighlightBegin: width / 2 - 15
preferredHighlightEnd: width / 2 + 15
highlightRangeMode: ListView.StrictlyEnforceRange
Component.onCompleted: currentIndex = count / 2
}
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
color: "yellow"
}
}
}

Related

How to customize ScrollView from qtquick controls 2.3

I'm using using ScrollView control from import QtQuick.Controls 2.3version because it looks better that prior ones.
The problem is that if i try to customize it with ScrollBar.vertical it looses some functionality. I can't press it and drag it up and down like it does by default.
I've searched and i've find a way to do the drag functionality.
The code i've used is:
import QtQuick 2.9
import QtQuick.Controls 1.4
import QtQuick.Controls 2.3
ApplicationWindow {
id: window
title: "Stack"
visible: true
height: 200
width: 400
ListModel {
id: libraryModel
ListElement {
text: "A Masterpiece"
}
ListElement {
text: "Brilliance"
}
ListElement {
text: "Outstanding"
}
}
Item {
id: page
anchors.fill: parent
width:parent.width
height: parent.height
ScrollView {
id:scrollView
anchors.fill:parent
ScrollBar.vertical: ScrollBar {
parent: scrollView
x: scrollView.mirrored ? 0 : scrollView.width - width
y: scrollView.topPadding
height: scrollView.availableHeight
active: scrollView.ScrollBar.horizontal.active
contentItem: Rectangle {
implicitWidth: 6
implicitHeight: 100
radius: width/2
color: scrollView.pressed ? "orange" : "green"
}
}
Column{
width:parent.width
spacing:10
TextField {
id:textField
implicitHeight: 30
font.bold: true
}
ComboBox {
id:comboBox
anchors.topMargin: 10
textRole: "text"
model: libraryModel
}
TextField {
id:textField2
anchors.topMargin: 10
implicitHeight: 30
font.bold: true
}
ComboBox {
id:comboBox2
anchors.topMargin: 10
textRole: "text"
model: libraryModel
}
TextField {
id:textField3
anchors.topMargin: 10
implicitHeight: 30
font.bold: true
}
ComboBox {
id:comboBox3
anchors.topMargin: 10
textRole: "text"
model: libraryModel
}
TextField {
id:textField4
anchors.topMargin: 10
implicitHeight: 30
font.bold: true
}
ComboBox {
id:comboBox4
anchors.topMargin: 10
textRole: "text"
model: libraryModel
}
}
}
}
}
What did i missed on the code? Maybe on ScrollBar?
I've fixed it by setting a different parent for ScrollBar (link). Also, to change the color you need to check ScrollBar property instead of ScrollView:
ScrollBar.vertical: ScrollBar {
id: scrollBar
parent: scrollView.parent
policy: ScrollBar.AlwaysOn
x: scrollView.mirrored ? 0 : scrollView.width - width
y: scrollView.topPadding
height: scrollView.availableHeight
active: scrollView.ScrollBar.horizontal.active
contentItem: Rectangle {
implicitWidth: 6
implicitHeight: 100
radius: width/2
color: scrollBar.pressed ? "orange" : "green"
}
}
If you set z: 1 (or any value > 0) to your ScrollBar the problem should be fixed.
I am not sure about the reason but it looks like it is related to the scrollbar attached by default to the ScrollView, that prevents you to access the custom scrollbar in this 10px zone.
cf Why is there a dead zone on the right side of my flipable?

QtLocation: how to make drag-and-drop on Map?

I have a QML Map widget. I want to drop some objects on it to get the latitude and longitude of the dropping point. How can I do it?
You can do that exactly as all other drag-n-drop applications. There are tons of examples as in Qt documentation as over the Internet.
One of them:
import QtQuick 2.9
import QtQuick.Window 2.0
import QtLocation 5.3
Window {
id: window
width: 600
height: 400
visible: true
MouseArea {
id: mouseArea
anchors.fill: parent
drag.target: item
propagateComposedEvents: true
onReleased: item.Drag.drop()
}
Plugin {
id: mapPlugin
preferred: ["osm", "esri"]
}
Map {
id: map
anchors.fill: parent
anchors.topMargin: 40
anchors.bottomMargin: 30
plugin: mapPlugin
center {
latitude: 40.785091
longitude: -73.968285
}
zoomLevel: 14
DropArea {
anchors.fill: parent
onDropped: {
var coord = map.toCoordinate(Qt.point(drop.x, drop.y));
output.text = "latitude:" + coord.latitude + ", longitude:" + coord.longitude;
anim.running = true;
}
}
}
Rectangle {
id: item
x: parent.width/2 - 20
y: 0
width: 40
height: 40
radius: 20
color: "orange"
opacity: 1
Drag.active: mouseArea.drag.active
Drag.hotSpot.x: 20
Drag.hotSpot.y: 20
Text {
anchors.centerIn: parent
text: "Drop me"
font.pixelSize: 8
}
SequentialAnimation {
id: anim
running: false
NumberAnimation { target: item; property: "opacity"; to: 0; duration: 500 }
PropertyAction { target: item; property: "x"; value: window.width/2 - 20 }
PropertyAction { target: item; property: "y"; value: 0 }
NumberAnimation { target: item; property: "opacity"; to: 1; duration: 500 }
}
}
Text {
id: output
anchors.bottom: parent.bottom
height: 30
width: window.width
text: ""
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
}
}

QML fill width of parent element

I have a problem, which can be seen on the attached screenshot
There is ApplicationWindow, which has header and ListView which is used in horizontal layout. Each item of list should be one page of application. Unfortunatelly, the width of base page is not set correctly to fill width of its parent (white background, not the grey one).
Here is the code of main page, it should load Login page - it is shown on the image.
ApplicationWindow {
id: root_window
title: Style.applicationName
visible: true
color: "white"
width: Style.windowWidth
height: Style.windowHeight
ColumnLayout {
id: root_layout
spacing: 0
width: root_window.width
height: root_window.height
SmonHeader {
id: smon_user_app_header
height: Style.headerHeight
anchors.top: parent.top
Layout.alignment: Qt.AlignLeft
Layout.fillWidth: true
}
Component.onCompleted: {
console.log("Main width: " + width);
}
ListView {
id: navigation
width: parent.width
height: parent.height
orientation: ListView.Horizontal
interactive: true // disable manual pageChange
snapMode: ListView.SnapOneItem // while moving to right, finish move
highlightRangeMode: ListView.StrictlyEnforceRange // mouse gesture make currentIndex change
highlightMoveDuration: 400 // speed up pages change (swap)
model: ObjectModel {
/* First page with login capabilities */
Login {
id: login_module
width: root_layout.width
height: root_layout.height
}
}
}
}
/* Private function definition*/
function init_database()
{
var database = Storage.LocalStorage.openDatabaseSync(Style.databaseName, Style.databaseVersion, Style.databaseDescr, Style.databaseSize);
smonDatabase.startDatabase(Style.databaseName);
}
Component.onCompleted: {
init_database();
}
}
Here is base of Login page
import QtQuick 2.4
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1
import QtQuick.Dialogs 1.2
import "../"
import "./common"
Rectangle {
id: login_page
// why parent.width is not set ?
anchors.fill: parent
//width: parent.width
//Layout.fillWidth: true
property string credentials_title: qsTr("Přístupové údaje")
property string available_devices: qsTr("Dostupné servery")
property string identity_title: qsTr("Identita")
property string password_title: qsTr("Heslo")
property string domain_title: qsTr("Doména")
property string infoLine_title: qsTr("Zapamatovat přihlašovací údaje")
property string username_title: qsTr("Jméno");
Component.onCompleted: {
console.log("Login width: " + login_page.width);
control.cancelEnabled = false
}
ColumnLayout{
id: navigation
spacing: Style.spacing
anchors.left: parent.left
anchors.leftMargin: Style.defaultAnchors
Layout.fillWidth: true
anchors.fill: parent
width: parent.width
Text {
id: title
//anchors.top: parent.top
//anchors.left: parent.left
font.pointSize: Style.fontSizeHeading
text: credentials_title
}
ColumnLayout{
id: navigationLogin
spacing: Style.spacing
anchors.left: parent.left
anchors.leftMargin: Style.defaultAnchors
Layout.fillWidth: true
Layout.bottomMargin: Style.bottomMargin
width: (parent.width - 4*Style.defaultAnchors)
GridLayout {
id: input_login
rowSpacing: Style.denseSpacing
columns: 2
columnSpacing: Style.spacing
anchors.left: parent.left
anchors.leftMargin: Style.defaultAnchors
width: 200
Text {
id: user_name
font.pointSize: Style.fontSizeSubHeading
text: username_title
}
SmonComboBox {
id: user
width: parent.width
value: smonRole.user
object: smonRole
prop: "user"
isEditable: true
dataModel: smonRole.userData
selectedIndex: smonRole.userNameSelected
}
Text {
id: password_name
font.pointSize: Style.fontSizeSubHeading
text: password_title
}
SmonTextField {
id: password
width: parent.width
type: "password"
object: smonRole
prop: "pass"
value: smonRole.pass
onEnterPressed: {
user.enabled = false
password.enabled = false
//control.okEnabled = false
control.okEnabled = false
control.cancelEnabled = true
smonRole.save();
smonCommunication.connect();
}
onValueChanged: {
if(password.value !== "")
{
control.okEnabled = true
}
else
{
control.okEnabled = false
}
}
}
}
ColumnLayout {
id: scanning
spacing: Style.denseSpacing
anchors.left: parent.left
//Layout.fillWidth: true
RowLayout {
id: slider_component
Text {
id: scanningHeader
font.pointSize: Style.fontSizeSubHeading
text: qsTr("Perioda vyhledávání zařízení");
}
Text {
id: value
font.pointSize: Style.fontSizeInfo
anchors.left: scanningHeader.right
anchors.leftMargin: Style.defaultAnchors
width: 30
text: slider.value
}
}
Slider {
id: slider
minimumValue: 2
maximumValue: 30
Layout.fillWidth: true
stepSize: 1
value: smonCommunication.scanPeriod
onValueChanged: {
smonCommunication.scanPeriod = slider.value;
}
}
}
SmonControlPanel {
id: control
width: parent.width
okEnabled: smonRole.user != "" && smonRole.pass != ""
okVisible: true
cancelVisible: true
onSignalOk: {
// hide content
user.enabled = false
password.enabled = false
control.okEnabled = false
control.cancelEnabled = true
smonRole.save();
smonCommunication.connect();
}
onSignalCancel: {
// show content again
password.enabled = true
user.enabled = true
//domain.enabled = true
control.cancelEnabled = false
control.okEnabled = true
//smonConnection.logout();
smonCommunication.disconnect();
smonRole.disconnected();
}
}
}
Text {
id: favourite
font.pointSize: Style.fontSizeHeading
text: available_devices
}
ListView{
id: servers
Layout.fillHeight: true
width: parent.width
model: smonCommunication.devicesList
delegate: Rectangle {
id: serverList
height: 80
width: parent.width
ColumnLayout{
Text {
id: serverName
text: modelData.bluetooth_name
}
Text {
id: rssi
text: modelData.bluetooth_rssi
}
}
MouseArea {
id: bt_device
anchors.fill: parent
onClicked: {
if(smonCommunication.btCanConnect === true)
smonCommunication.connect(index);
}
}
}
}
}
MessageDialog {
id: errorDialog
standardButtons: StandardButton.Cancel | StandardButton.OK
visible: false;
informativeText: smonCommunication.errorMessage
onInformativeTextChanged: {
errorDialog.visible = true;
}
}
}
Is there problem on the main page or on the page which is loaded ? Thanks for help...
Your problem lies with the anchors.fill: parent bit in your ObjectModel.
The parent here, is not the ListView, but the ListView's contentItem, which happens to have an implicit width of 100px.
In your minimal example, something like this should work:
model: ObjectModel {
/* First page with login capabilities */
Rectangle{
id: one
//anchors.fill: parent <- parent is not navigation
width: navigation.width
height: 50
color: "red"
}
}
Generally speaking, you should not use the parent property in your delegates.
So, after answers from ddriver and Kevin Krammer (thanks) I made a minimal working example.
I stopped using ColumnLayout, and set everything as best as I can.
Here is the code
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Layouts 1.1
import QtQml.Models 2.1
ApplicationWindow {
id: root_window
title: "Hello world"
visible: true
color: "white"
width: 480
height: 520
Rectangle {
id: smon_user_app_header
height: 50
color: "blue"
width: parent.width
}
ListView {
id: navigation
orientation: ListView.Horizontal
interactive: true // disable manual pageChange
snapMode: ListView.SnapOneItem // while moving to right, finish move
highlightRangeMode: ListView.StrictlyEnforceRange // mouse gesture make currentIndex change
highlightMoveDuration: 400 // speed up pages change (swap)
anchors.top: smon_user_app_header.bottom
anchors.bottom: root_window.bottom
width: parent.width
height: 400
model: ObjectModel {
/* First page with login capabilities */
Rectangle{
id: one
anchors.fill: parent
color: "red"
}
}
}
}
And here is how it looks

QT 5.3 / QML: Resizable StackView depending on currentItem

I'm working on a QML StackView that starts with a list of items to select from. Once selected I want to transition _.push(...) to a input form which has larger dimensions than the initialItem.
The only way I have trial-and-errored my way into a situation that works is by making the form Item a nested borderless window.
Q1. A nested window can't be the right type of concept to use for this... right ? there must be another way to do it. What is the right way ?
Q2. My goal after this is to have a transition animation that grows or shrinks between stacks of different sizes. Advice that doesn't preclude that would be best.
code
Main.qml :
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1
ApplicationWindow {
property int itemHeight: 30
property int cornerRadius : 5
visible: true
color: "transparent"
flags: Qt.FramelessWindowHint
ListModel {
id: searchFacets
ListElement {
title: "Topics"
page: "content/TopicSearch.qml"
}
// ListElement {
// title: "Domains"
// }
}
StackView {
id: stackView
focus: true
initialItem: SearchFacets {
id: facets
}
delegate: StackViewDelegate {
pushTransition: StackViewTransition {
PropertyAnimation {
target: enterItem
property: "opacity"
from: 0
to: 1
}
}
}
}
}
Initial Item:
import QtQuick 2.3
Item {
height : listView.count * itemHeight
ListView {
id: listView
model: searchFacets
anchors.fill: parent
focus: true
highlightFollowsCurrentItem: false
highlight: Rectangle {
width: parent.width
height: itemHeight
radius : cornerRadius
color: "green"
opacity: 0.5
z:2
x: listView.currentItem.x;
y: listView.currentItem.y
Behavior on y {
SpringAnimation {
spring: 60
damping: 1.0
}
}
}
delegate: Component {
Item {
width: parent.width
height : itemHeight
Rectangle {
anchors.fill: parent
color: "#212126"
radius: cornerRadius
z:0
border.width: 2
border.color : "white"
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: {
console.log("clicked index: " + index)
listView.currentIndex = index
// listView.forceActiveFocus()
stackView.push(Qt.resolvedUrl(page))
}
}
Text {
text: title
font.pixelSize: 24
font.bold: true
z:1
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
color: "white"
antialiasing: true
}
}
}
}
}
Input Form:
import QtQuick 2.3
import QtQuick.Window 2.0
Item {
Window {
width: 400
height: 400
visible: true
flags: Qt.FramelessWindowHint
Rectangle {
anchors.fill: parent
visible: true
color: "red"
}
}
}
One possible solution is to update the size of the dimensions of the StackView in the click handler that causes the transition. I do not know if that causes any problems with animating the transition.
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: {
console.log("clicked index: " + index)
listView.currentIndex = index
var component = Qt.createComponent(page)
var res = component.createObject(stackView)
stackView.height = res.height
stackView.width = res.width
stackView.push(res)
}
}

QML: How to make nice transition effect between image sources (one fades into the other)?

I wonder how to make smooth transitions betwen image sources in QML, I try
import QtQuick 1.1
Image {
id: rect
source: "quit.png"
smooth: true
MouseArea {
id: mouseArea
anchors.fill: parent
anchors.margins: -10
hoverEnabled: true //this line will enable mouseArea.containsMouse
onClicked: Qt.quit()
}
states: State {
name: "mouse-over"; when: mouseArea.containsMouse
PropertyChanges { target: rect; scale: 0.8; source :"quit2.png" }
}
transitions: Transition {
NumberAnimation { properties: "scale, source"; easing.type: Easing.InOutQuad; duration: 1000 }
}
}
But It does not work on source as a transition just as final state change.. so I wonder how to make one image source fade into andothe and back?
You want the first image to fade out into the other? How about if you place two Image objects on top of each other, then animate the opacity property?
EDIT: This worked for me (I'm using QtQuick 1.0 because my Qt Creator installation is a bit outdated):
import QtQuick 1.0
Rectangle {
Image {
id: rect
source: "quit.png"
smooth: true
opacity: 1
MouseArea {
id: mouseArea
anchors.fill: parent
anchors.margins: -10
hoverEnabled: true //this line will enable mouseArea.containsMouse
onClicked: Qt.quit()
}
states: State {
name: "mouse-over"; when: mouseArea.containsMouse
PropertyChanges { target: rect; scale: 0.8; opacity: 0}
PropertyChanges { target: rect2; scale: 0.8; opacity: 1}
}
transitions: Transition {
NumberAnimation { properties: "scale, opacity"; easing.type: Easing.InOutQuad; duration: 1000 }
}
}
Image {
id: rect2
source: "quit2.png"
smooth: true
opacity: 0
anchors.fill: rect
}
}
To the question in your comment: you can place the image exactly on top of the other by copying the anchors thru anchors.fill: rect
Here is also a simple scroll transition between images:
import QtQuick 2.6
import QtQuick.Controls 1.4
import QtQuick.Window 2.2
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Rectangle {
id: imageRect
anchors.centerIn: parent
width: 240
height: 320
clip: true
property int currentIndex: 0
property var imageSources: [ "imageLeft.jpg", "imageCenter.jpg" ]
Repeater {
model: imageRect.imageSources
Image {
id: image
width: parent.width
height: parent.height
x: index * parent.width - imageRect.currentIndex * parent.width
fillMode: Image.PreserveAspectFit
source: imageRect.imageSources[index]
Behavior on x { SpringAnimation { spring: 2; damping: 0.2 } }
}
}
}
Button {
id: leftButton
anchors.bottom: parent.bottom
text: "left"
onClicked: if(imageRect.currentIndex > 0) imageRect.currentIndex--
}
Button {
id: rightButton
anchors.bottom: parent.bottom
anchors.left: leftButton.right
text: "right"
onClicked: if(imageRect.currentIndex < imageRect.imageSources.length - 1) imageRect.currentIndex++
}
Button {
id: addButton
anchors.bottom: parent.bottom
anchors.left: rightButton.right
text: "+"
onClicked: imageRect.imageSources = [ "imageLeft.jpg", "imageCenter.jpg" , "imageRight.jpg" ]
}
}

Resources