make QML TextField to blinking - qt

I want TextField to blink when button is clicked. It easy to do with QTimer:
void MyLineEdit::buttonClickedSlot{
for(int i=1;i<15;i+=2){
QTimer::singleShot(100*i, this, SLOT(changeBackgroundColor("QLineEdit{background: red;}")));
QTimer::singleShot(100*(i+1), this, SLOT((changeBackgroundColor("QLineEdit{background: white;}")));
}
}
void MyLineEdit::changeBackgroundColor(QString str){
this->setStyleSheet(str)
}
However, I did not find anything like QTimer in QML so I decided to do it via animation. Here QML is code:
Rectangle{
ColumnLayout{
anchors.fill: parent
TextField{
id: txt
text: "hello"
style: TextFieldStyle{
background:Rectangle {
id: rect
radius: 2
implicitWidth: 100
implicitHeight: 24
border.color: "#333"
border.width: 1
color: "white"
}
}
}
ColorAnimation{
id: whiteToRed
target: rect //reference error: rect is not defined
properties: "color"
from: "white"
to: "red"
duration: 300
}
ColorAnimation{
id: redToWhite
target: rect //reference error: rect is not defined
properties: "color"
from: "red"
to: "white"
duration: 300
}
Button{
text: "blink"
onClicked: {
for(var i=0;i<3;i++){
whiteToRed.start()
redToWhite.start()
}
}
}
}
}
The problem here is that there are compile error: rect is not defined. How should I solve that problem?

Try this:
Column{
anchors.fill: parent
TextField{
id: txt
text: "hello"
property string color: "white"
style: TextFieldStyle{
background: Rectangle {
id: rect
radius: 2
implicitWidth: 100
implicitHeight: 24
border.color: "#333"
border.width: 1
color: txt.color
Behavior on color {
SequentialAnimation {
loops: 3
ColorAnimation { from: "white"; to: "red"; duration: 300 }
ColorAnimation { from: "red"; to: "white"; duration: 300 }
}
}
}
}
}
Button{
text: "blink"
onClicked: {
txt.color = "red";
txt.color = "white";
}
}
}

Related

Combobox popup is opened transparent

I have a Combobox (Control 2.0). I write my own combobox like
Rectangle
{
border.width: 1
border.color: "lightsteelblue"
height:dp(40)
width: parent.width
ComboBox {
id:tmCombo
model:combotm.datalist
textRole: "value"
anchors.fill: parent
currentIndex:-1;
contentItem: Text {
leftPadding: 0
rightPadding: tmCombo.indicator.width + tmCombo.spacing
text:tmCombo.currentIndex==-1 ? "":tmCombo.model[tmCombo.currentIndex].value
font: tmCombo.font
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
onCurrentIndexChanged: {
if(currentIndex!=-1) {
var sqlid=model[currentIndex].sqlid;
combotm.getsqlid(sqlid,1,Query.SelectSubParam,Query.Subq,"TMC",1);
TaskResult.taskresult.HatBilgisi_TM=sqlid;
tmsCombo.enabled=true;
}
else {
tmsCombo.enabled=false;
}
tmsCombo.currentIndex=-1;
}
}
}
My problem is that when Combobox first open, half of popup is transparent. Then I close and open combobox again. Everthing is OK. I am working in android platform.
SOLUTION:
I have added import QtQuick.Templates 2.0 as T and chance Popup with T.Popup . That's work
Rigth code is : Combobox with filter input :) I have binded model from C++ side with Q_Property . dp function is my global function in main.qml which is fixed pixel for any device.
ComboBox {
id:trCombo
model:combotr.datalist
textRole: "value"
anchors.fill: parent
currentIndex:-1;
contentItem: Text {
leftPadding: 0
rightPadding: trCombo.indicator.width + trCombo.spacing
text:trCombo.currentIndex==-1 ? "":trCombo.model[trCombo.currentIndex].value
font: trCombo.font
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
popup: T.Popup {
id:mpopup
y: trCombo.height - (trCombo.visualFocus ? 0 : 1)
width: trCombo.width
implicitHeight: listview.contentHeight
topMargin: 6
bottomMargin: 6
// focus: true
closePolicy: Popup.NoAutoClose
contentItem: Item {
Column
{
anchors.fill: parent
spacing: 5
TextField
{
placeholderText: "arama yapın"
width: trCombo.width
height: dp(35)
// color: "red"
focus:true
inputMethodHints: Qt.ImhNoPredictiveText;
onTextChanged:{
//console.log("degisiyor");
process.filtertr(text);
}
onAccepted:{
// console.log("Tasarım Bitti");
isfinished(true);
// text="";
}
}
ListView {
id: listview
clip: true
model: trCombo.popup.visible ? trCombo.delegateModel : null
currentIndex: trCombo.highlightedIndex
width: trCombo.width
height:dp(500)
Rectangle {
z: 10
parent: listview
width: listview.width
height: listview.height
color: "transparent"
border.color: "#bdbebf"
layer.smooth: true
}
ScrollIndicator.vertical: ScrollIndicator { }
}
}
}
background: Rectangle { }
onClosed: {
if(!flag)
{
mpopup.open();
}
else
flag=false;
}
}
delegate: ItemDelegate {
width: trCombo.width
text: trCombo.textRole ? (Array.isArray(trCombo.model) ? modelData[trCombo.textRole] : model[trCombo.textRole]) : modelData
font.weight: trCombo.currentIndex === index ? Font.DemiBold : Font.Normal
highlighted: trCombo.highlightedIndex == index
onClicked: {
isfinished(true);
}
}
onCurrentIndexChanged: {
if(currentIndex!=-1)
{
var sqlid=model[currentIndex].sqlid;
combotr.getsqlid(sqlid,1,Query.SelectSubParam,Query.Subq,"TRC",1);
TaskResult.taskresult.HatBilgisi_TR=sqlid ;
trsCombo.enabled=true;
}
else
trsCombo.enabled=false;
trsCombo.currentIndex=-1;
}
}

How to slide items in a ListView

I would like to create a slideshow showing 3 items with a picture and a label for each, the item in the middle being highlighted (picture is bigger and a description text appears below the label).
When a corresponding arrow is clicked, I would like the items to "slide" instead of just appearing where they should. Unfortunately, the Behavior on x {
NumberAnimation{...}} code in the delegate does not do this.
Here is my code:
import QtQuick 2.7
import QtQuick.Window 2.0
Window {
id: display
width: 500
height: 300
visible: true
Item {
id: conteneur
anchors.leftMargin: 50
height: display.height / 1.2
width: display.width / 1.2
anchors.horizontalCenter: parent.horizontalCenter
Rectangle {
id: boutonAvant
height: conteneur.height
anchors.verticalCenter: parent.verticalCenter
width: 68
x: -50
color: "transparent"
z: 1
Text {
id: pictureAv
anchors.centerIn: parent
text: "<"
font.pixelSize: 90
}
MouseArea {
id: buttonAvMouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: listview.decrementCurrentIndex()
}
}
ListView {
id: listview
clip: true
orientation: ListView.Horizontal
width: conteneur.width
height: conteneur.height / 1.2
anchors.centerIn: conteneur
model: myListModel
delegate: myDelegate
maximumFlickVelocity: 700
snapMode: ListView.SnapToItem
highlightFollowsCurrentItem: true
highlightRangeMode: ListView.StrictlyEnforceRange
preferredHighlightBegin: conteneur.width * 0.3
preferredHighlightEnd: conteneur.width * 0.3 + conteneur.width * 0.4
onCurrentIndexChanged: {
positionViewAtIndex(currentIndex, ListView.SnapPosition)
}
Component.onCompleted: {
currentIndex = 1
}
}
Rectangle {
id: boutonApres
height: conteneur.height
anchors.verticalCenter: parent.verticalCenter
x: conteneur.width - 10
width: 68
color: "transparent"
Text {
id: pictureAp
anchors.centerIn: parent
text: ">"
font.pixelSize: 90
}
MouseArea {
id: buttonApMouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: listview.incrementCurrentIndex()
}
}
}
ListModel {
id: myListModel
ListElement {
name: "rectangle 0"
desc: "blabla"
mycolor: "green"
}
ListElement {
name: "rectangle 1"
desc: "blabla"
mycolor: "blue"
}
ListElement {
name: "rectangle 2"
desc: "blabla"
mycolor: "lightblue"
}
ListElement {
name: "rectangle 3"
desc: "blabla, \n with several lines for test \n and more lines \n and more lines"
mycolor: "gold"
}
}
Component {
id: myDelegate
Rectangle {
id: cadre
opacity: listview.currentIndex === index ? 1 : 0.5
anchors.top: parent.top
anchors.topMargin: listview.currentIndex === index ? 0 : 35
width: listview.currentIndex === index ? listview.width * 0.4 : listview.width * 0.3
height: conteneur.height
border.color: mycolor
color: "transparent"
Behavior on x {
NumberAnimation {
duration: 800
}
}
}
}
}
ListView inherits Flickable which uses contentX and contentY to govern what's visible. The model Rectangles don't actually move.
I would try a Behavior on ListView's contentX. Note that the documentation for positionViewAtIndex says not manipulate those directly because the math on them is not predictable – but a behavior on them may work.
I finally had some result using this :
//In bouton Avant :
MouseArea{
id: boutonAvant
anchors.fill: parent
hoverEnabled: true
onClicked: {
pictureAp.visible = true;
var oldPos = listview.contentX;
listview.decrementCurrentIndex();
var newPos = oldPos - listview.width*0.3; // listview.width*0.3 is the width of one item that is not the current one
if(listview.currentIndex == 0){
pictureAv.visible = false;
}
anim.running = false
anim.from = oldPos;
anim.to = newPos;
anim.running = true;
}
}
}
The ListView becomes :
ListView{
id: listview
clip: true
orientation: ListView.Horizontal
width: conteneur.width
height: conteneur.height/1.2
anchors.centerIn: conteneur
model: myListModel
delegate: myDelegate
Component.onCompleted: {
currentIndex = 1;
}
}
NumberAnimation { id: anim; target: listview; property: "contentX"; duration: 800 }
And boutonApres is similar to boutonAvant with :
MouseArea{
id: buttonApMouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: {
pictureAv.visible = true;
var oldPos = listview.contentX;
listview.incrementCurrentIndex();
var newPos = oldPos + listview.width*0.3;
if(listview.currentIndex == listview.count-1){
pictureAp.visible = false;
}
anim.running = false
anim.from = oldPos;
anim.to = newPos;
anim.running = true;
}
}
It works fines when items being 'slided' are in the middle of the listview but when I get to the first item (on the last click on the left arrow), or to the last item (on the last click on the right arrow), I get a disturbing 'flick' as if the listview was trying to move at two places at the same time, following 2 different orders. But I can't see where this could come from...

How to add animation onPressed and onReleased in QML Slider?

http://doc.qt.io/qt-5/qml-qtquick-controls-styles-sliderstyle.html
Slider {
anchors.centerIn: parent
style: SliderStyle {
groove: Rectangle {
implicitWidth: 200
implicitHeight: 8
color: "gray"
radius: 8
}
handle: Rectangle {
anchors.centerIn: parent
color: control.pressed ? "white" : "lightgray"
border.color: "gray"
border.width: 2
implicitWidth: 34
implicitHeight: 34
radius: 12
}
}
How to access the onReleased and onPressed of the slider in order to start and stop some animation?
Here is what I tried:
import QtQuick 2.4
import QtQuick.Window 2.2
import QtQuick.Controls.Styles 1.4
import QtQuick.Controls 1.4
Window {
visible: true
Slider
{
id: head
property Rectangle thumb: thumb
anchors.centerIn: parent
style: SliderStyle {
groove: Rectangle {
implicitWidth: 200
implicitHeight: 8
color: "gray"
radius: 8
}
handle: Rectangle {
id: thumb
anchors.centerIn: parent
color: control.pressed ? "white" : "lightgray"
border.color: "gray"
border.width: 2
implicitWidth: 34
implicitHeight: 34
radius: 12
}
}
onPressedChanged:
{
if(pressed)
{
console.log("pressed")
returnAnimation.stop()
}
else
{
console.log("released")
returnAnimation.start()
}
}
ParallelAnimation {
id: returnAnimation
NumberAnimation { target: thumb.anchors; property: "horizontalCenterOffset";
to: 0; duration: 200; easing.type: Easing.OutSine }
NumberAnimation { target: thumb.anchors; property: "verticalCenterOffset";
to: 0; duration: 200; easing.type: Easing.OutSine }
}
}
}
Error:
ReferenceError: thumb is not defined
Here is a fully working example. You will have to create your own images referenced here since I can't attach them.
I have found scoping is tricky in QML with component objects. The ":style:handle" component in Slider can "see out" to the higher levels but the higher levels cannot "see in" to the ":style:handle" component.
General Strategy
Create a property in the Top Level Slider scope
Use the property inside the ":style:handle" component since it can "see out"
Use the higher level onPressedChanged handler and the pressed property to adjust the high level property which will be "seen" by the low level component.
Slider {
id: portVoltageSlider
width: 100; height: 27
maximumValue: 150; minimumValue: -150
value: 0.00
stepSize: 10
anchors { centerIn: parent }
// style:handle component will be able to see/access this property
// opacity value of style: SliderStyle:handle.sliderHover
property real hoverOpacity: 0
// adjust property on slider pressed
onPressedChanged: {
// show slider Hover when pressed, hide otherwise
if( pressed ) {
console.log("slider pressed. show hover.")
hoverShowAnimation.start()
}
else {
console.log("slider released. hide hover.")
hoverHideAnimation.start()
}
}
// gratuitous animation using opacity
PropertyAnimation {
id: hoverShowAnimation
target: portVoltageSlider; properties: "hoverOpacity"; from: portVoltageSlider.hoverOpacity; to: 1; duration: 500
}
PropertyAnimation {
id: hoverHideAnimation
target: portVoltageSlider; properties: "hoverOpacity"; from: portVoltageSlider.hoverOpacity; to: 0; duration: 500
}
style: SliderStyle {
id: sliderStyle
property bool hoverVisible: false
groove: Rectangle {
// x: slider1.leftPadding
y: portVoltageSlider.topPadding + portVoltageSlider.availableHeight / 2 - height / 2
implicitWidth: 200; implicitHeight: 4
width: portVoltageSlider.availableWidth; height: implicitHeight
radius: 2
color: "#bdbebf"
Rectangle {
width: portVoltageSlider.visualPosition * parent.width; height: parent.height
color: "yellow"
radius: 2
}
}
handle: Image {
id: sliderHandle
width: 22; height: 24
source: "sliderThumb.svg"
anchors { centerIn: parent }
Image {
id: sliderHover
width: 22; height: 24
source: "sliderValue.svg"
anchors { bottom: sliderHandle.top }
opacity: portVoltageSlider.hoverOpacity
Label {
id: check
anchors {centerIn: parent; verticalCenterOffset: -4 }
text: portVoltageSlider.value
font.pointSize: 6
font.bold: true
}
}
}
}
}
That what I meant in the comment above:
Slider {
...
onPressedChanged: {
if(pressed)
console.log("pressed")
else
console.log("released")
}
}
Would this work?
import QtQuick 2.4
import QtQuick.Window 2.2
import QtQuick.Controls.Styles 1.4
import QtQuick.Controls 1.4
Window {
visible: true
Slider
{
id: head
property Rectangle thumb: thumb
//Added these signals:
signal startAnim
signal stopAnim
anchors.centerIn: parent
style: SliderStyle {
groove: Rectangle {
implicitWidth: 200
implicitHeight: 8
color: "gray"
radius: 8
}
handle: Rectangle {
id: thumb
anchors.centerIn: parent
color: control.pressed ? "white" : "lightgray"
border.color: "gray"
border.width: 2
implicitWidth: 34
implicitHeight: 34
radius: 12
//Moved animation within the confines of the object that it actually pertains to
ParallelAnimation {
id: returnAnimation
NumberAnimation { target: thumb.anchors; property: "horizontalCenterOffset";
to: 0; duration: 200; easing.type: Easing.OutSine }
NumberAnimation { target: thumb.anchors; property: "verticalCenterOffset";
to: 0; duration: 200; easing.type: Easing.OutSine }
}
//Signal connections done here:
Component.onCompleted: {
head.startAnim.connect(returnAnimation.start)
head.stopAnim.connect(returnAnimation.stop)
}
}
}
onPressedChanged:
{
if(pressed)
{
console.log("pressed")
startAnim()
}
else
{
console.log("released")
stopAnim()
}
}
}
}

How to move/animate components created by repeater in QML?

I have a component named Tile in Tile.qml, which I want to create by a Repeater. Tile.qml is as follows:
import QtQuick 2.0
Rectangle {
id: tile
property string tileLabel: label.text
property int tileSize: height
width: 50
height: tileSize
color: "green"
border.color: Qt.lighter(color)
anchors.bottom: parent.bottom
Text {
id: label
color: "white";
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.bottom
text: tileLabel
}
}
And my main.qml is as follows:
import QtQuick 2.0
Rectangle {
id: root
width: 552; height: 300
color: "#3C3C3C"
border.color: Qt.lighter(color)
Row {
id: tilesRow
anchors.margins: 8
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
spacing: 4
Repeater {
id: repeater
model: 10
delegate: Tile {
tileSize: Math.random() * 100 + 1
tileLabel: tileSize
}
}
}
Rectangle {
id: button
width: 100
height: 30
color: "gray"
focus: true
Text {
anchors.centerIn: parent
color: "white"
text: "Button"
}
MouseArea {
hoverEnabled: true
anchors.fill: parent
onEntered: { button.color = Qt.lighter("blue")}
onExited: { button.color = "gray" }
onPressed: { button.color = "blue" }
onReleased: { button.color = Qt.lighter("blue") }
onClicked: func()
}
}
}
I need to sort the tiles when the button is clicked so that the tiles are in ascending order by their labels. I can access the labels of the tiles using repeater.itemAt(i).tileSize. How can I animate the movement of tiles as they are moved/swapped?
Small example:
import QtQuick 2.3
import QtQuick.Window 2.2
Window {
visible: true
width: 800
height: 600
Row {
anchors.centerIn: parent
property var word: ['H','e','l','l','o','!']
id: row
Repeater {
id: repeater
model: row.word.length
delegate: Rectangle {
id: delegate;
width: 100
height: 100
property int pos
color: Qt.rgba(Math.random(),Math.random(),Math.random(),1);
Text {
anchors.centerIn: parent
font.pixelSize: 36
color: "white"
text: row.word[index]
}
Behavior on x {
ParallelAnimation {
PropertyAnimation {
duration: 500
easing.type: Easing.InOutBack
}
SequentialAnimation {
PropertyAnimation {
target: delegate
property: "y"
from: 0
to: delegate.pos == 1 ? 20 : -20
duration: 250
}
PropertyAnimation {
target: delegate
property: "y"
from: delegate.pos == 1 ? 20 : -20
to: 0
duration: 250
}
}
}
}
Behavior on rotation {
RotationAnimation {
direction: RotationAnimation.Clockwise
duration: 300
}
}
}
}
}
Timer {
interval: 1000
running: true
repeat: true
onTriggered: {
var element1 = repeater.itemAt(Math.round(Math.random() * (repeater.count - 1)));
var element2 = repeater.itemAt(Math.round(Math.random() * (repeater.count - 1)));
if(element1 === element2) {
element1.rotation = element1.rotation + 90;
} else {
element1.pos = 1;
element2.pos = 2;
var temp = element1.x;
element1.x = element2.x;
element2.x = temp;
}
}
}
}

Need responsive height for DropDown List in QML for ComboBox?

I am creating a custom combobox model in which i need to assign a height of a dropDown list in responsive value. It is on length of items at present so unable to reduce or increase its height as per screen resolution. Here is my code :
Rectangle {
width:150;
height: 60;
Rectangle {
id:comboBox
property variant items: ["Item 1", "Item 2", "Item 3"]
property alias selectedItem: chosenItemText.text;
property alias selectedIndex: listView.currentIndex;
signal comboClicked;
width: 100;
height: 30;
z: 100;
smooth:true;
Rectangle {
id:chosenItem
radius:4;
width:parent.width;
height:comboBox.height;
color: "lightsteelblue"
smooth:true;
Text {
anchors.top: parent.top;
anchors.left: parent.left;
anchors.margins: 8;
id:chosenItemText
text:comboBox.items[0];
font.family: "Arial"
font.pointSize: 14;
smooth:true
}
MouseArea {
anchors.fill: parent;
onClicked: {
comboBox.state = comboBox.state==="dropDown"?"":"dropDown"
}
}
}
Rectangle {
id:dropDown
width:comboBox.width;
height:0;
clip:true;
radius:4;
anchors.top: chosenItem.bottom;
anchors.margins: 2;
color: "lightgray"
ListView {
id:listView
height:500;
model: comboBox.items
currentIndex: 0
delegate: Item{
width:comboBox.width;
height: comboBox.height;
Text {
text: modelData
anchors.top: parent.top;
anchors.left: parent.left;
anchors.margins: 5;
}
MouseArea {
anchors.fill: parent;
onClicked: {
comboBox.state = ""
var prevSelection = chosenItemText.text
chosenItemText.text = modelData
if(chosenItemText.text != prevSelection){
comboBox.comboClicked();
}
listView.currentIndex = index;
}
}
}
}
}
Component {
id: highlight
Rectangle {
width:comboBox.width;
height:comboBox.height;
color: "red";
radius: 4
}
}
states: State {
name: "dropDown";
PropertyChanges { target: dropDown; height:30*comboBox.items.length }
}
transitions: Transition {
NumberAnimation { target: dropDown; properties: "height"; easing.type: Easing.OutExpo; duration: 1000 }
}
}
}
Please suggest me some solution.

Resources