I have QML element consisting of transparent Rectangle and Image inside of it. The purpose of this element is to show some operation success - if some operation was executed successfully, checkmark icons pops up and then slowly dissapears in time of 1000ms.
Here is the simplified code that should done this job:
import QtQuick 2.5
import QtQuick.Layouts 1.1
Rectangle
{
id: ueActionResultIndicator
property bool ueParamConnectionOk: false
width: 128
height: 128
color: "transparent"
ColumnLayout
{
anchors.fill: parent
Image
{
Layout.fillWidth: true
Layout.fillHeight: true
horizontalAlignment: Qt.AlignHCenter
verticalAlignment: Qt.AlignVCenter
smooth: true
fillMode: Image.PreserveAspectFit
// source: ueParamConnectionOk===true?"qrc:///ueIcons/icons/ueActionOk.png"
// :"qrc:///ueIcons/icons/ueActionCancel.png"
source: "http://www.clker.com/cliparts/0/f/7/0/11954234311954389563ok_mark_h_kon_l_vdal_02.svg.hi.png"
} // Image
} // ColumnLayout
states:
[
State
{
name: "ueStateHidden"
PropertyChanges
{
target: ueActionResultIndicator
opacity: 0.00
} // PropertyChanges
}, // State
State
{
name: "ueStateShown"
PropertyChanges
{
target: ueActionResultIndicator
opacity: 1.00
} // PropertyChanges
} // State
] // states
transitions:
[
Transition
{
from: "ueStateShown"
to: "ueStateHidden"
PropertyAnimation
{
properties: "opacity"
duration: 1000
loops: 3
easing.type: Easing.InOutSine
onStarted:
{
visible=true;
enabled=true;
} // onStarted
onStopped:
{
visible=false;
enabled=false;
} // onStopped
} // PropertyAnimation
} // Transition
] // transitions
Component.onCompleted:
{
state="ueStateHidden";
} // Component.onCompleted
} // Rectangle
and here is parent .QML file triggering it:
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.1
import QtQuick.Window 2.2
import QtQuick.Controls.Styles 1.4
Window
{
width: 512
height: 512
flags: Qt.FramelessWindowHint
visible: true
ColumnLayout
{
anchors.fill: parent
spacing: 8
Rectangle
{
Layout.fillWidth: true
Layout.fillHeight: true
Layout.margins: 8
radius: 16
border.color: "#4682b4"
border.width: 1
antialiasing: true
gradient: Gradient
{
GradientStop
{
position: 0
color: "#636363"
} // GradientStop
GradientStop
{
position: 1
color: "#303030"
} // GradientStop
} // Gradient
ColumnLayout
{
anchors.fill: parent
RowLayout
{
spacing: 8
Layout.fillWidth: true
Layout.fillHeight: true
Layout.margins: 8
Layout.alignment: Qt.AlignHCenter|Qt.AlignTop
antialiasing: true
Text
{
text: qsTr("APPLICATION SETTINGS")
clip: true
font.bold: true
font.pointSize: 24
textFormat: Text.RichText
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
} // Text
} // RowLayout
ColumnLayout
{
Layout.fillWidth: true
Layout.fillHeight: true
Layout.margins: 8
Layout.alignment: Qt.AlignHCenter|Qt.AlignBottom
TabView
{
Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignHCenter|Qt.AlignVCenter
frameVisible: true
Tab
{
asynchronous: true
title: qsTr("Database")
Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignHCenter|Qt.AlignVCenter
ColumnLayout
{
spacing: 8
Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignHCenter|Qt.AlignVCenter
TextField
{
id: textFieldServerAddress
antialiasing: true
Layout.fillWidth: true
Layout.fillHeight: false
placeholderText: qsTr("database server address")
} // TextField
TextField
{
id: textFieldServerPort
Layout.fillWidth: true
Layout.fillHeight: false
placeholderText: qsTr("database server port")
} // TextField
TextField
{
id: textFieldDatabaseName
Layout.fillWidth: true
Layout.fillHeight: false
placeholderText: qsTr("database name")
} // TextField
TextField
{
id: textFieldDatabaseUsername
Layout.fillWidth: true
Layout.fillHeight: false
placeholderText: qsTr("database access username")
} // TextField
TextField
{
id: textFieldDatabasePassword
Layout.fillWidth: true
Layout.fillHeight: false
placeholderText: qsTr("database access password")
echoMode: TextInput.PasswordEchoOnEdit
} // TextField
RowLayout
{
Layout.fillWidth: true
Layout.fillHeight: false
Layout.alignment: Qt.AlignLeft|Qt.AlignVCenter
spacing: 8
Button
{
Layout.fillWidth: false
Layout.fillHeight: true
Layout.alignment: Qt.AlignLeft|Qt.AlignVCenter
text: qsTr("Test Connection")
onClicked:
{
ueActionResultIndicator.state="ueStateShown";
} // onClicked
} // Button
} // RowLayout
} // ColumnLayout
} // Tab
} // TabView
} // ColumnLayout
} // ColumnLayout
} // Rectangle
} // ColumnLayout
UeActionResultIndicator
{
id: ueActionResultIndicator
} // UeActionResultIndicator
} // Window
Why the checkmark once shown does not slowly dissapear, i.e., why does PropertyAnimation not get started?
You only shown Image.
ueActionResultIndicator.state = "ueStateShown";
For disappear you must add
ueActionResultIndicator.state = "ueStateHidden"
But, anyway, i think, you must refactor this code and run animation from function without states:
Rectangle {
id: rect
width: 100
height: 62
color: "green"
PropertyAnimation
{
id: opacityAnimation
properties: "opacity"
target: rect
from: 0.0
to: 1.0
duration: 1000
loops: 3
easing.type: Easing.InOutSine
onStarted:
{
visible=true;
enabled=true;
} // onStarted
onStopped:
{
visible=false;
enabled=false;
} // onStopped
} // PropertyAnimation
function runAnimation() {
opacityAnimation.running = true
}
}
Related
I have a QML Window with ListView inside TabView's Tab, which
delegates are instances of TextField:
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.1
import QtQuick.Window 2.2
import QtQuick.Controls.Styles 1.4
Window
{
width: Screen.width/2
height: Screen.height/2
x: Screen.width/2-width/2
y: Screen.height/2-height/2
flags: Qt.FramelessWindowHint
visible: true
color: "transparent"
property string uePropertyServerAddress:""
property string uePropertyServerPort:""
property string uePropertyDatabaseName:""
property string uePropertyDatabaseUsername:""
property string uePropertyDatabasePassword:""
property string uePropertyHostname:""
ColumnLayout
{
anchors.fill: parent
spacing: 8
Rectangle
{
Layout.fillWidth: true
Layout.fillHeight: true
Layout.margins: 8
radius: 16
border.color: "#4682b4"
border.width: 1
antialiasing: true
gradient: Gradient
{
GradientStop
{
position: 0
color: "#636363"
} // GradientStop
GradientStop
{
position: 1
color: "#303030"
} // GradientStop
} // Gradient
ColumnLayout
{
anchors.fill: parent
RowLayout
{
spacing: 8
Layout.fillWidth: true
Layout.fillHeight: true
Layout.margins: 8
Layout.alignment: Qt.AlignHCenter|Qt.AlignTop
antialiasing: true
Text
{
text: qsTr("APPLICATION SETTINGS")
clip: true
font.bold: true
font.pointSize: 24
textFormat: Text.RichText
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
} // Text
} // RowLayout
ColumnLayout
{
Layout.fillWidth: true
Layout.fillHeight: true
Layout.margins: 8
Layout.alignment: Qt.AlignHCenter|Qt.AlignBottom
TabView
{
Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignHCenter|Qt.AlignVCenter
tabPosition: Qt.TopEdge
frameVisible: true
style: TabViewStyle
{
frameOverlap: 1
tab: Rectangle
{
implicitWidth: 128//Math.max(ueTabText.width+4, 120)
implicitHeight: 48//ueTabText.height*2
radius: 8
border.color: "#4682b4"
border.width: 1
gradient: Gradient
{
GradientStop
{
position: 0
color: "#ffffff"
} // GradientStop
GradientStop
{
position: 0.418
color: styleData.selected ? "steelblue" : "#000000"
} // GradientStop
} // gradient
ColumnLayout
{
anchors.fill:parent
Text
{
id: ueTabText
Layout.fillWidth: true
Layout.fillHeight: true
Layout.margins: 8
text: styleData.title
color: styleData.selected?"black":"white"
} // Text
} // ColumnLayout
} // tab
frame: Rectangle
{
radius: 8
border.color: "#4682b4"
border.width: 1
color: "black"
} // frame
} // TabViewStyle
Tab
{
asynchronous: true
title: qsTr("Database")
Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignHCenter|Qt.AlignVCenter
ColumnLayout
{
spacing: 8
Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignHCenter|Qt.AlignVCenter
ListModel
{
id: ueDatabaseSettingsModel
ListElement
{
feature: qsTr("database server address")
} // ListElement
ListElement
{
feature: qsTr("database server port")
} // ListElement
ListElement
{
feature: qsTr("database name")
} // ListElement
ListElement
{
feature: qsTr("database access username")
} // ListElement
ListElement
{
feature: qsTr("database access password")
} // ListElement
} // ListModel
ListView
{
id: ueDatabaseSettingListView
Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignHCenter|Qt.AlignVCenter
Layout.margins: 8
spacing: 16
delegate: TextField
{
width: ueDatabaseSettingListView.width
antialiasing: true
placeholderText: model.feature
style: TextFieldStyle
{
textColor: "#C1C1C1"
placeholderTextColor: "steelblue"
background: Rectangle
{
color: "#323232"
border.color: "#4682b4"
border.width: 1
}
} // TextFieldStyle
} // delegate
Component.onCompleted:
{
model=ueDatabaseSettingsModel;
} // Component.OnCompleted
} // ListView
} // ColumnLayout
} // Tab
} // TabView
RowLayout
{
Layout.fillWidth: true
Layout.fillHeight: false
Layout.alignment: Qt.AlignLeft|Qt.AlignVCenter
spacing: 8
Button
{
Layout.fillWidth: false
Layout.fillHeight: true
Layout.alignment: Qt.AlignLeft|Qt.AlignVCenter
text: qsTr("Apply")
onClicked:
{
} // onClicked
} // Button
Button
{
Layout.fillWidth: false
Layout.fillHeight: true
Layout.alignment: Qt.AlignLeft|Qt.AlignVCenter
text: qsTr("Clear")
onClicked:
{
} // onUeSignalButtonClicked
} // Button
} // RowLayout
} // ColumnLayout
} // ColumnLayout
} // Rectangle
} // ColumnLayout
} // Window
This works just fine, but I've stumbled across problem of saving TextField's values into GUI item properties:
TextField database server address must save value into property string uePropertyServerAddress
TextField database server port must save value into property string uePropertyServerPort
etc ... for all other TextFields.
The question is, how do I "link" delegates of ListView (TextField instances) to belonging property?
I think you need to refactor as BaCaRoZzo commented, but I think the problem could be solved with minimum change.
First, append target property name into each ListElement
ListModel
{
id: ueDatabaseSettingsModel
ListElement
{
feature: qsTr("database server address")
target: "uePropertyServerAddress"
} // ListElement
ListElement
{
feature: qsTr("database server port")
target: "uePropertyServerPort"
} // ListElement
ListElement
{
feature: qsTr("database name")
target: "uePropertyDatabaseName"
} // ListElement
ListElement
{
feature: qsTr("database access username")
target: "uePropertyDatabaseUsername"
} // ListElement
ListElement
{
feature: qsTr("database access password")
target: "uePropertyDatabasePassword"
} // ListElement
} // ListModel
Second, add onEditingFinished handler like the following
delegate: TextField
{
...
onEditingFinished: {
window[model.target] = text;
}
}
Third, add id to Window to access its properties
Window
{
id: window
Then you can see each TextField's text is assigned to the property.
I am working on some Application Settings QML Window and here is minimalistic working code:
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.1
import QtQuick.Window 2.2
import QtQuick.Controls.Styles 1.4
Window
{
width: 512
height: 512
flags: Qt.FramelessWindowHint
visible: true
ColumnLayout
{
anchors.fill: parent
spacing: 8
Rectangle
{
Layout.fillWidth: true
Layout.fillHeight: true
Layout.margins: 8
radius: 16
border.color: "#4682b4"
border.width: 1
antialiasing: true
gradient: Gradient
{
GradientStop
{
position: 0
color: "#636363"
} // GradientStop
GradientStop
{
position: 1
color: "#303030"
} // GradientStop
} // Gradient
ColumnLayout
{
anchors.fill: parent
RowLayout
{
spacing: 8
Layout.fillWidth: true
Layout.fillHeight: true
Layout.margins: 8
Layout.alignment: Qt.AlignHCenter|Qt.AlignTop
antialiasing: true
Text
{
text: qsTr("APPLICATION SETTINGS")
clip: true
font.bold: true
font.pointSize: 24
textFormat: Text.RichText
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
} // Text
} // RowLayout
ColumnLayout
{
Layout.fillWidth: true
Layout.fillHeight: true
Layout.margins: 8
Layout.alignment: Qt.AlignHCenter|Qt.AlignBottom
TabView
{
Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignHCenter|Qt.AlignVCenter
frameVisible: true
Tab
{
asynchronous: true
title: qsTr("Database")
Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignHCenter|Qt.AlignVCenter
ColumnLayout
{
spacing: 8
Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignHCenter|Qt.AlignVCenter
TextField
{
id: textFieldServerAddress
antialiasing: true
Layout.fillWidth: true
Layout.fillHeight: false
placeholderText: qsTr("database server address")
} // TextField
TextField
{
id: textFieldServerPort
Layout.fillWidth: true
Layout.fillHeight: false
placeholderText: qsTr("database server port")
} // TextField
TextField
{
id: textFieldDatabaseName
Layout.fillWidth: true
Layout.fillHeight: false
placeholderText: qsTr("database name")
} // TextField
TextField
{
id: textFieldDatabaseUsername
Layout.fillWidth: true
Layout.fillHeight: false
placeholderText: qsTr("database access username")
} // TextField
TextField
{
id: textFieldDatabasePassword
Layout.fillWidth: true
Layout.fillHeight: false
placeholderText: qsTr("database access password")
echoMode: TextInput.PasswordEchoOnEdit
} // TextField
RowLayout
{
Layout.fillWidth: true
Layout.fillHeight: false
Layout.alignment: Qt.AlignLeft|Qt.AlignVCenter
spacing: 8
Button
{
Layout.fillWidth: false
Layout.fillHeight: true
Layout.alignment: Qt.AlignLeft|Qt.AlignVCenter
text: qsTr("Test Connection")
onClicked:
{
print(textFieldServerAddress.text+
textFieldServerPort.text+
textFieldDatabaseName.text+
textFieldDatabaseUsername.text+
textFieldDatabasePassword.text);
} // onClicked
} // Button
} // RowLayout
} // ColumnLayout
} // Tab
Tab
{
asynchronous: true
title: qsTr("General")
Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignHCenter|Qt.AlignVCenter
} // Tab
} // TabView
RowLayout
{
Layout.fillWidth: true
Layout.fillHeight: false
Layout.alignment: Qt.AlignLeft|Qt.AlignVCenter
spacing: 8
Button
{
Layout.fillWidth: false
Layout.fillHeight: true
Layout.alignment: Qt.AlignLeft|Qt.AlignVCenter
text: qsTr("Apply")
onClicked:
{
print(textFieldServerAddress.text+
textFieldServerPort.text+
textFieldDatabaseName.text+
textFieldDatabaseUsername.text+
textFieldDatabasePassword.text);
} // onClicked
} // Button
Button
{
Layout.fillWidth: false
Layout.fillHeight: true
Layout.alignment: Qt.AlignLeft|Qt.AlignVCenter
text: qsTr("Clear")
onClicked:
{
textFieldServerAddress.text="";
textFieldServerPort.text="";
textFieldDatabaseName.text="";
textFieldDatabaseUsername.text="";
textFieldDatabasePassword.text="";
} // onClicked
} // Button
} // RowLayou
} // ColumnLayout
} // ColumnLayout
} // Rectangle
} // ColumnLayout
} // Window
As you can see, I have three Buttons:
Test Connection
Apply
Clear
Now, if I fill values and click on Test Connection Button, the code in handler onClicked() gets executed. However, If I click on Buttons Apply or Clear, I get following error:
ReferenceError: textFieldServerAddress is not defined
Wtf, why do I get this error and how do I get rid of it? As for Buttons names, in Test Connection I test the database connection with entered parameters, in Apply I save database connection parameters into SQLITE database and in Clear I clear all the values in TextField entites.
As from the documentation:
The component scope is the union of the object ids within the component and the component's root object's properties.
Also, we find from here that:
A Tab item inherits from Loader and provides a similar API.
Your item is thus a component scope for itself, with its own rules and visibility. That's because an item loaded by a Loader is not part of the surrounding scope, instead it has a limited access to it (mainly through what is exposed and made available by the Loader itself).
That's why that id is visible from within one button, but it is not from within the others in the tab.
You have to refactor your UI or, at least, to export symbols into an accessible object.
I am working on QML/Qt app and I have following ListView, names ueUserInfoListView:
ListView
{
id: ueUserInfoListView
antialiasing: true
Layout.alignment: Qt.AlignHCenter|Qt.AlignVCenter
Layout.fillWidth: true
Layout.fillHeight: true
Layout.margins: 8
clip: true
spacing: 64
orientation: ListView.Horizontal
highlightFollowsCurrentItem: true
delegate: Image
{
id: ueUserInfoListViewDelegate
source: "image://uePeopleModel/"+model.ueRoleImage
opacity: 0.3
fillMode: Image.PreserveAspectFit
function ueDoOpacity()
{
if(ueUserInfoListViewDelegate===ueUserInfoListView.currentItem)
opacity=1.0
else
opacity=0.3
}
Behavior on opacity
{
NumberAnimation
{
duration: 300
} // NumberAnimation
} // Behavior
Component.onCompleted:
{
ueUserInfoListViewDelegate.focusChanged.connect(ueDoOpacity)
} // Component.onCompleted
} // delegate
Component.onCompleted:
{
model=uePeopleModel
} // Component.onCompleted
preferredHighlightBegin: width/2-70
preferredHighlightEnd: width/2+70
highlightRangeMode: ListView.StrictlyEnforceRange
currentIndex: count/2
} // ListView
I am tryigin to call ueUserInfoListView from another separated (in terms of file) Item, named ueProductSelector:
import QtQuick 2.5
import QtQuick.Layouts 1.2
import si.mikroelektronika 1.0
Item
{
id: ueProductSelector
antialiasing: true
clip: true
Rectangle
{
id: ueProductSelectorWrapper
radius: 16
gradient: Gradient
{
GradientStop
{
position: 0
color: "#ffffff"
} // GradientStop
GradientStop
{
position: 1
color: "#000000"
} // GradientStop
} // Gradient
border.color: "#4682b4"
border.width: 1
antialiasing: true
anchors.centerIn: parent
anchors.fill: parent
ColumnLayout
{
anchors.margins: parent.radius/2
spacing: 0
antialiasing: true
anchors.fill: parent
anchors.centerIn: parent
GridView
{
id: ueProductGridView
antialiasing: true
clip: true
Layout.fillWidth: true
Layout.fillHeight: true
cellWidth: 144
cellHeight: 144
model: ueProductsModel
delegate: Rectangle
{
radius: 16
clip: true
width: ueProductGridView.cellWidth-8
height: ueProductGridView.cellHeight-8
border.color: "#4682b4"
antialiasing: true
gradient: Gradient
{
GradientStop
{
position: 0
color: "#000000"
ParallelAnimation on color
{
id: ueProductSelectorDelegateMouseAreaAnimation
loops: 1
running: false//ueDelegateMouseArea.pressed
ColorAnimation
{
from: "#4682b4"
to: "#000000"
duration: 100
} // ColorAnimation
} // ParallelAnimation
} // GradientStop
GradientStop
{
position: 1
color: "#ffffff"
} // GradientStop
} // Gradient
MouseArea
{
id: ueDelegateMouseArea
anchors.fill: parent
onClicked:
{
var selectedIndex=ueProductGridView.currentIndex=index;
ueProductSelectorDelegateMouseAreaAnimation.running=true;
ueProductGridView.currentIndex=index;
ueOrdersModel.ueSetRecordValues(ueUserInfoListView.model.get(ueUserInfoListView.currentIndex).ueRoleId,
uePlacesListView.model.get(uePlacesListView.currentIndex).ueRoleId,
ueProductGridView.model.get(selectedIndex).ueRoleProductId,
1);
} // onClicked
} // MouseArea
ColumnLayout
{
anchors.centerIn: parent
anchors.fill: parent
antialiasing: true
spacing: 8
Image
{
Layout.fillWidth: true
Layout.fillHeight: false
Layout.alignment: Qt.AlignCenter|Qt.AlignTop
Layout.topMargin: ueProductSelectorWrapper.radius+4
fillMode: Image.PreserveAspectFit
horizontalAlignment: Image.AlignHCenter
verticalAlignment: Image.AlignVCenter
antialiasing: true
source: "image://ueProductsModel/"+model.ueRoleImage
} // Image
Text
{
Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignCenter|Qt.AlignBottom
Layout.bottomMargin: ueProductSelectorWrapper.radius+4
color: "#000000"
text: model.ueRoleProductName
wrapMode: Text.WordWrap
font.family: "Courier"
textFormat: Text.RichText
font.bold: true
font.pointSize: 10
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
} // Text
} // ColumnLayout
} // delegate
Component.onCompleted:
{
ueProductSelectorOpacityAnimator.running=true
}
} // GridView
} // ColumnLayot
} // Rectangle
} // Item
and I get following error:
qrc:/gui/items/UeProductSelector.qml:126: ReferenceError:
ueUserInfoListView is not defined
Why?
Well, you should not do this. Using an ID of another component in a seperate QML component file is evil!
Try to avoid this at all costs. It will couple your QML components and they are not really reuseable.
So, to solve your problem you should pass the ListView component as a property to your ueProductSelector component:
import QtQuick 2.5
import QtQuick.Layouts 1.2
import si.mikroelektronika 1.0
Item
{
id: ueProductSelector
antialiasing: true
clip: true
property ListView ueUserInfoListView
// [...]
}
Then you should be able to call
ueOrdersModel.ueSetRecordValues(ueUserInfoListView.model.get(ueUserInfoListView.currentIndex).ueRoleId,
uePlacesListView.model.get(uePlacesListView.currentIndex).ueRoleId,
ueProductGridView.model.get(selectedIndex).ueRoleProductId,
1);
in your second component.
The ListView component is passed as a reference of (QObject*) and should not be performance critical.
If the MouseArea was declared in UeDelegate.qml, and UeListView.qml (imaginary file names for the sake of the example) contained a ListView that specifies a UeDelegate as its delegate, this would work. With the information you've given us, we can only assume that the ListView is not an ancestor of the MouseArea.
To elaborate on this concept:
The component instance scope hierarchy extends to out-of-line components, too. In the following example, the TitlePage.qml component creates two TitleText instances. Even though the TitleText type is in a separate file, it still has access to the title property when it is used from within the TitlePage. QML is a dynamically scoped language - depending on where it is used, the title property may resolve differently.
// TitlePage.qml
import QtQuick 2.0
Item {
property string title
TitleText {
size: 22
anchors.top: parent.top
}
TitleText {
size: 18
anchors.bottom: parent.bottom
}
}
// TitleText.qml
import QtQuick 2.0
Text {
property int size
text: "<b>" + title + "</b>"
font.pixelSize: size
}
I have following QML Rectangle:
import QtQuick 2.5
import QtQuick.Layouts 1.1
Rectangle
{
id: uePlaceSwitcher
property string ueParamUserImage
property string ueParamUserName
property string ueParamPlaceName
signal ueSignalPlaceSwitcherReleased
signal ueSignalPlaceSwitcherPressed
radius: 16
border.color: "#4682b4"
border.width: 1
antialiasing: true
Layout.fillWidth: true
Layout.fillHeight: true
Layout.minimumWidth: 128
Layout.preferredWidth: 384
Layout.maximumWidth: 384
enabled: false
gradient: Gradient
{
GradientStop
{
id: uePlaceSwitcherGradientPosition0
position: 0
color: "#000000"
ParallelAnimation on color
{
id: uePlaceSwitcherReleasedAnimation
loops: 1
running: false
ColorAnimation
{
from: "#4682b4"
to: "#000000"
duration: 100
} // ColorAnimation
} // ParallelAnimation
ParallelAnimation on color
{
id: uePlaceSwitcherPressedAnimation
loops: 1
running: false
ColorAnimation
{
from: "#000000"
to: "#4682b4"
duration: 100
} // ColorAnimation
} // ParallelAnimation
} // GradientStop
GradientStop
{
id: uePlaceSwitcherGradientPosition1
position: 1
color: "#ffffff"
} // GradientStop
} // Gradient
RowLayout
{
id: ueMainLayout
anchors.fill: parent
anchors.margins: 8
spacing: 8
Image
{
id: ueUserImage
antialiasing: true
clip: true
Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignLeft|Qt.AlignVCenter
source: ueParamUserImage
smooth: true
fillMode: Image.PreserveAspectFit
horizontalAlignment: Image.AlignHCenter
verticalAlignment: Image.AlignVCenter
} // Image
ColumnLayout
{
Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignLeft|Qt.AlignVCenter
Text
{
color: "#ffffff"
Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignLeft|Qt.AlignTop
antialiasing: true
text: ueParamUserName
font.family: "Courier"
font.bold: true
font.pointSize: 16
clip: true
textFormat: Text.RichText
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
} // Text
Text
{
color: "#ffffff"
Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignLeft|Qt.AlignBottom
antialiasing: true
text: ueParamPlaceName
font.family: "Courier"
font.bold: true
font.pointSize: 16
clip: true
textFormat: Text.RichText
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
} // Text
} // ColumnLayout
} // RowLayout
MouseArea
{
anchors.fill: parent
onClicked:
{
print("onClicked state: "+state)
if(state==="uePlaceSwitcherStateReleased")
{
state="uePlaceSwitcherStatePressed"
uePlaceSwitcherPressedAnimation.running=true
ueSignalPlaceSwitcherPressed()
}
else
{
state="uePlaceSwitcherStateReleased"
uePlaceSwitcherReleasedAnimation.running=true
ueSignalPlaceSwitcherReleased()
} // if
} // onClicked
} // MouseArea
states:
[
State
{
name: "uePlaceSwitcherStatePressed"
}, // State
State
{
name: "uePlaceSwitcherStateReleased"
} // State
] // states
Component.onCompleted:
{
state="uePlaceSwitcherStateReleased"
enabled=true
print("Component.onCompleted state: "+state)
}
} // Rectangle
Now, this Rectangle has two states and at the first click Rectangle is not in the neither of two states. Here is debug print after first click:
qml: Component.onCompleted state: uePlaceSwitcherStateReleased
qml: onClicked state:
As you can see, state at onCompleted is ok, but when I first click Rectangle, the state gets emtpy string. Why?!
I think you're changing the state for the MouseArea, not the Rectangle.
According to the documentation,
Every Item based component has a state property and a default state.
The default state is the empty string ("") and contains all of an
item's initial property values.
Without any reference, you're printing the MouseArea state in this line:
print("onClicked state: "+state)
So you should identify the Rectangle state using its id. In your case: uePlaceSwitcher.state.
I've tested the following code and it works fine.
MouseArea
{
anchors.fill: parent
onClicked:
{
print("onClicked state: " + uePlaceSwitcher.state)
if(uePlaceSwitcher.state==="uePlaceSwitcherStateReleased")
{
uePlaceSwitcher.state="uePlaceSwitcherStatePressed"
uePlaceSwitcherPressedAnimation.running=true
ueSignalPlaceSwitcherPressed()
}
else
{
uePlaceSwitcher.state="uePlaceSwitcherStateReleased"
uePlaceSwitcherReleasedAnimation.running=true
ueSignalPlaceSwitcherReleased()
} // if
} // onClicked
} // MouseArea
states:
[
State
{
name: "uePlaceSwitcherStatePressed"
}, // State
State
{
name: "uePlaceSwitcherStateReleased"
} // State
] // states
Component.onCompleted:
{
state="uePlaceSwitcherStateReleased"
enabled=true
print("Component.onCompleted state: "+state)
}
Although in my opinion, we should also use the id in Component.onCompleted because it makes the code easier to follow. It isn't necessary, though.
Component.onCompleted:
{
uePlaceSwitcher.state="uePlaceSwitcherStateReleased"
enabled=true
print("Component.onCompleted state: " + uePlaceSwitcher.state)
}
In my QML/Qt app, I have following Rectangle:
import QtQuick 2.5
import QtQuick.Layouts 1.1
Rectangle
{
id: uePlaceSelector
signal ueSignalPlaceSelected
signal ueSignalPlaceSelectionAborted
property string ueSelectedPlaceName: ""
radius: 16
border.color: "#4682b4"
border.width: 1
antialiasing: true
//FIXME how to set width same as UePlaceSwitcher's width?
anchors.fill: parent
gradient: Gradient
{
GradientStop
{
position: 0
color: "#636363"
} // GradientStop
GradientStop
{
position: 1
color: "#303030"
} // GradientStop
} // Gradient
ColumnLayout
{
antialiasing: true
layoutDirection: Qt.LeftToRight
spacing: 8
anchors.fill: parent
RowLayout
{
Layout.fillWidth: true
Layout.fillHeight: true
Layout.margins: 8
Rectangle
{
id: uePlaceSelectorNavigatorBack
Layout.preferredWidth: 32
Layout.preferredHeight: 32
color: "transparent"
SequentialAnimation
{
id: uePlaceSelectorNavigatorBackPressAnimation
loops: 1
running: false
NumberAnimation
{
target: uePlaceSelectorNavigatorBack
property: "opacity"
to: 0
duration: 150
} // NumberAnimation
NumberAnimation
{
target: uePlaceSelectorNavigatorBack
property: "opacity"
to: 1
duration: 150
} // NumberAnimation
} // SequentialAnimation
Image
{
anchors.fill: parent
asynchronous: true
horizontalAlignment: Image.AlignHCenter
verticalAlignment: Image.AlignVCenter
fillMode: Image.PreserveAspectFit
smooth: true
source: "qrc:///ueIcons/icons/ueArrowLeft.png"
} // Image
MouseArea
{
anchors.fill: parent
onClicked:
{
uePlaceSelectorNavigatorBackPressAnimation.running=true;
ueSignalPlaceSelectionAborted()
} // onClicked
} // MouseAres
} // Rectangle
} // RowLayout
GridView
{
id: uePlacesGridView
antialiasing: true
Layout.fillWidth: true
Layout.fillHeight: true
Layout.margins: 8
Layout.alignment: Qt.AlignHCenter|Qt.AlignBottom
flow: GridView.FlowLeftToRight
layoutDirection: Qt.LeftToRight
clip: true
cellWidth: parent.width
cellHeight: 128
highlightFollowsCurrentItem: true
highlightRangeMode: GridView.StrictlyEnforceRange
snapMode: GridView.SnapToRow
Component.onCompleted:
{
model=uePlacesModel
}
delegate: UeButton
{
id: uePlacesModelDelegate
width: uePlacesGridView.cellWidth-16
height: uePlacesGridView.cellHeight-16
ueText: model.ueRoleName
ueSoundOn: false
onUeSignalButtonClicked:
{
ueSelectedPlaceName=uePlacesGridView.model.get(index).ueRoleName;
ueSignalPlaceSelected()
} // onUeSignalButtonClicked:
} // delegate
} // GridView
} // ColumnLayout
} // Rectangle
Now, this Rectangle is at startup hidden and disabled. But in my ApplicationWindow I have Toolbar with customs Buttons and when the user presses one of them, this Rectangle pops up via OpacityAnimator. However its size is full screen because of anchors.fill: parent. Its parent is ApplicationWindow, becuase it is declared inside it. But, how do I assign its width, because
Component.onCompleted:
{
ueLoggedUserPlaceSelector.width=uePlaceSwitcher.width
} // Component.onCompleted
inside main.qml does not work. Why?
Replace
anchors.fill: parent
with
width: uePlaceSwitcher.width
height: uePlaceSwitcher.height
You should provide height with width or the rectangle will not be visible.