Invalid property "style" for Button - qt

Why am I getting this error: invalid property "style" every time I use the style property?
Button {
text: "A button"
style: ButtonStyle {
background: Rectangle {
implicitWidth: 100
implicitHeight: 25
border.width: control.activeFocus ? 2 : 1
border.color: "#888"
radius: 4
gradient: Gradient {
GradientStop { position: 0 ; color: control.pressed ? "#ccc" : "#eee" }
GradientStop { position: 1 ; color: control.pressed ? "#aaa" : "#ccc" }
}
}
}
}

Assuming you are using QtQuick.Controls.Button, you can use the following:
Button {
id: control
text: "A button"
background: Rectangle {
implicitWidth: 100
implicitHeight: 25
border.width: control.activeFocus ? 2 : 1
border.color: "#888"
radius: 4
gradient: Gradient {
GradientStop { position: 0 ; color: control.pressed ? "#ccc" : "#eee" }
GradientStop { position: 1 ; color: control.pressed ? "#aaa" : "#ccc" }
}
}
}
If you are using this definition repeatedly, you can put it (with text: "A button") in a separate file, which you can call MyButton.qml, then you can use MyButton { text: "A Button" }

Gray is the default color of a button in qml. If you would like to style it this is an option I use frequently. Create a rectangle child component of button, set anchors.fill, and then set a color on the rectangle. This will be the color of your button now.

You can use Rectangle, Text and MouseArea Components to create button. By this way, there is no need style. You can do it like,
Rectangle{
implicitWidth: 100
implicitHeight: 25
border.width: control.activeFocus ? 2 : 1
border.color: "#888"
radius: 4
gradient: Gradient {
GradientStop { position: 0 ; color: control.pressed ? "#ccc" : "#eee" }
GradientStop { position: 1 ; color: control.pressed ? "#aaa" : "#ccc" }
}
Text{
anchors.centerIn: parent
text: qsTr("A button")
}
MouseArea{
id: control
anchors.fill: parent
onClicked: {
//Your Button Function
}
}
}

Related

Animated progress bar in QML

I need to create a Progress bar as below using QML Controls 2 :
ProgressBar{
id:progressBar
width : parent.width * 0.80
height:parent.height * 0.05
anchors.bottom:parent.bottom
anchors.bottomMargin: (parent.height * 0.03)
anchors.left:parent.left
anchors.leftMargin: (parent.width * 0.05)
value : 0.5
background: Rectangle {
color: "#e6e6e6"
radius: 3
}
contentItem: Item {
Rectangle {
width: progressBar.visualPosition * parent.width
height: parent.height
radius: 2
color: "#17a81a"
gradient: Gradient {
GradientStop {
position: 0.0
SequentialAnimation on color {
loops: Animation.Infinite
ColorAnimation { from: "#14148c"; to: "#0E1533"; duration: 5000 }
ColorAnimation { from: "#0E1533"; to: "#14148c"; duration: 5000 }
}
}
GradientStop {
position: 1.0
SequentialAnimation on color {
loops: Animation.Infinite
ColorAnimation { from: "#14aaff"; to: "#437284"; duration: 5000 }
ColorAnimation { from: "#437284"; to: "#14aaff"; duration: 5000 }
}
}
}
}
}
}
I have never used animations in QML and I tried with sequential animation as above which animates top to bottom. But i need it to animate left to right.
Can anyone help me to achieve this?
As for me I guess its bad idea to overwrite system behavior of controls.
Anyway, you can play with animated gradient. For example:
ProgressBar {
id: control
anchors.centerIn: parent
value: 0
height: 20
clip: true
background: Rectangle {
implicitWidth: 200
implicitHeight: 6
border.color: "#999999"
radius: 5
}
contentItem: Item {
implicitWidth: 200
implicitHeight: 4
Rectangle {
id: bar
width: control.visualPosition * parent.width
height: parent.height
radius: 5
}
LinearGradient {
anchors.fill: bar
start: Qt.point(0, 0)
end: Qt.point(bar.width, 0)
source: bar
gradient: Gradient {
GradientStop { position: 0.0; color: "#17a81a" }
GradientStop { id: grad; position: 0.5; color: Qt.lighter("#17a81a", 2) }
GradientStop { position: 1.0; color: "#17a81a" }
}
PropertyAnimation {
target: grad
property: "position"
from: 0.1
to: 0.9
duration: 1000
running: true
loops: Animation.Infinite
}
}
LinearGradient {
anchors.fill: bar
start: Qt.point(0, 0)
end: Qt.point(0, bar.height)
source: bar
gradient: Gradient {
GradientStop { position: 0.0; color: Qt.rgba(0,0,0,0) }
GradientStop { position: 0.5; color: Qt.rgba(1,1,1,0.3) }
GradientStop { position: 1.0; color: Qt.rgba(0,0,0,0.05) }
}
}
}
PropertyAnimation {
target: control
property: "value"
from: 0
to: 1
duration: 5000
running: true
loops: Animation.Infinite
}
}

Qml slider style, assigning different groove color before and after the slider's handle

So I wanted to create a slider style, similar to the default one, and also more matching to my applications style, but I found it hard to assign a different color before and after the slider's handle.
Here's a simplified version of my code, without gradients, anchor points and other properties:
Slider{
id: widthSlider
style: SliderStyle {
groove: Rectangle {
height: widthSlider.height*0.17
width: widthSlider.width
color: "black"
radius: 8
}
handle: Rectangle {
color: "grey"
}
}
}
I tried a rough workaround, to put two rectangles in the slider, anchored to the handle position like this:
Slider{
id: widthSlider
Rectangle {
anchors.left: widthSlider.left
anchors.right: widthSlider.__handlePos
color: "black"
}
Rectangle {
anchors.left: widthSlider.__handlePos
anchors.right: widthSlider.right
color: "white"
}
...
}
but I cannot anchor to the handle's position since it's just a double(I get the error: Unable to assign double to QQuickAnchorLine).
Does anyone have an idea of how I could do this in Qml?
Something like this?
Slider {
anchors.centerIn: parent
value: 0.5
width: 400
style: SliderStyle {
groove: Item {
implicitHeight: 10
LinearGradient {
anchors.fill: parent
start: Qt.point(0, control.height / 2)
end: Qt.point(control.width, control.height / 2)
gradient: Gradient {
GradientStop { position: 0.0; color: "orange" }
GradientStop { position: control.value; color: "brown" }
GradientStop { position: 1.0; color: "orange" }
}
}
}
}
}
Or:
Slider {
anchors.centerIn: parent
value: 0.5
width: 400
style: SliderStyle {
groove: Rectangle {
implicitHeight: 10
color: "lightgrey"
border {
color: "#999"
width: 1
}
Rectangle {
implicitHeight: 10
color: "orange"
implicitWidth: control.value * parent.width
border {
color: "#999"
width: 1
}
}
}
}
}
I realize this is an old question. However for future reference the Rectangle that represents the colour before the handle should have a width of styleData.handlePosition. The below code is from folibis second solution with this change.
Slider {
anchors.centerIn: parent
value: 0.5
width: 400
style: SliderStyle {
groove: Rectangle {
implicitHeight: 10
color: "lightgrey"
border {
color: "#999"
width: 1
}
Rectangle {
implicitHeight: 10
color: "orange"
implicitWidth: styleData.handlePosition
border {
color: "#999"
width: 1
}
}
}
}
}

Slider Style: Gradient along the width of the groove

I am trying to create a custom QML Slider style as follows:
SliderStyle {
groove: Item {
anchors.verticalCenter: parent.verticalCenter
implicitWidth: 500
implicitHeight: 10
Rectangle {
radius: height/2
anchors.fill: parent
border.width: 1
border.color: "#888"
gradient: Gradient {
GradientStop { color: "#0A406E" ; position: 0 }
GradientStop { color: "#FFA800" ; position: 1 }
}
}
}
}
However, the gradient on the groove here is going from top to bottom rather than left to right. I tried swapping the width and height values and rotating the Rectangle by -90 degrees but then the slider was unresponsive. Also, I could never get the rotation to be done along the centre of the slider control, which made placement a bit problematic.
I was wondering if there is a way to achieve this left->right gradient flow.
Rectangle's property gradient allows for the construction of simple vertical gradients. For more complex gradients there are LinearGradient, RadialGradient and ConicalGradient types.
For example, horizontal gradient:
import QtGraphicalEffects 1.0
SliderStyle {
groove: Item {
anchors.verticalCenter: parent.verticalCenter
implicitWidth: 500
implicitHeight: 10
Rectangle {
radius: height/2
anchors.fill: parent
border.width: 1
border.color: "#888"
layer.enabled: true
layer.effect: LinearGradient {
start: Qt.point(0, 0)
end: Qt.point(500, 0)
gradient: Gradient {
GradientStop { position: 0.0; color: "#0A406E" }
GradientStop { position: 1.0; color: "#FFA800" }
}
}
}
}
}

Setting radio button as group box title

Is it possible to place radio button as group box header in qml. If yest can you give me some hint how can be done. I saw option to change title to check box but it doesn't feet my solution.
It's not currently possible to do this with GroupBox, as it doesn't offer a styling API. You have these options:
Use the checkable property, which gives you a CheckBox, not a RadioButton, as you know.
Use the private GroupBoxStyle type and then define your own checkbox component that is a RadioButton. This is private API though, which means it can change at any point.
Somehow place a non-interactive but visual item over the top of the CheckBox that is produced with the checkable property, and filter the events that would go to that checkbox. This is quite difficult, and I'm not sure if it would work.
Write your own GroupBox, using the code I linked to above as a starting point.
Ok so what I have done based on previous (i hope:)) things is:
style: GroupBoxStyle {
padding {
top: (control.title.length > 0 || control.checkable ? TextSingleton.implicitHeight : 0) + 5
left: 8
right: 8
bottom: 6
}
checkbox:Item {
implicitWidth: 18
implicitHeight: 18
BorderImage {
anchors.fill: parent
border.top: 6
border.bottom: 6
border.left: 6
border.right: 6
}
Rectangle {
width: Math.round(TextSingleton.implicitHeight)
height: width
gradient: Gradient {
GradientStop {color: "#eee" ; position: 0}
GradientStop {color: control.pressed ? "#eee" : "#fff" ; position: 0.4}
GradientStop {color: "#fff" ; position: 1}
}
border.color: control.activeFocus ? "#16c" : "gray"
antialiasing: true
radius: height/2
anchors.left: parent.left
anchors.leftMargin: 5
anchors.top: parent.top
anchors.topMargin: 2
Rectangle {
anchors.centerIn: parent
width: Math.round(parent.width * 0.5)
height: width
gradient: Gradient {
GradientStop {color: "#999" ; position: 0}
GradientStop {color: "#555" ; position: 1}
}
border.color: "#222"
antialiasing: true
radius: height/2
Behavior on opacity {NumberAnimation {duration: 80}}
opacity: control.checked ? control.enabled ? 1 : 0.5 : 0
}
}
BorderImage {
anchors.fill: parent
anchors.margins: -1
visible: control.activeFocus
border.left: 4
border.right: 4
border.top: 4
border.bottom: 4
opacity: 0
}
}
What I get is:
And I have one more question is there an options to be set to disable opacity on radio button and text
Maybe someone may review this solution and tell me if it is ok.
Update:
Additionaly if your add:
panel:Item{
anchors.fill: parent
Loader {
id: checkboxloader
anchors.left: parent.left
sourceComponent: control.checkable ? checkbox : null
anchors.verticalCenter: label.verticalCenter
width: item ? item.implicitWidth : 0
}
Rectangle {
anchors.fill: parent
anchors.topMargin: padding.top - 7
border.color: "gray";
radius: 7;
color: "transparent"
visible: !control.flat
z: -2
}
Rectangle {
anchors.top: parent.top
anchors.left: checkboxloader.right
anchors.margins: 4
width: label.width
height: label.height
color: parent.color
z: -1
}
Text {
id: label
anchors.top: parent.top
anchors.left: checkboxloader.right
anchors.margins: 4
text: control.title
color: textColor
renderType: Settings.isMobile ? Text.QtRendering : Text.NativeRendering
opacity: 1
z: 0
}
}
Group box looks like:
This solution was done based on Mitch post

Creating a custom QML Button with native look and feel

I would like to create a custom Button by defining my own QML type. This Button type should contain two text fields, one with a single character of a symbol font and the other one the actual button text.
That's simple, but how could I use the native colors, gradients, fonts and borders defined for the target system?
Is it possible to extend Button itself? And how would I disable the possibility to set an image when extending Button?
import QtQuick 2.5
Rectangle {
id:anyButton
property string image:"\ue43f"
property string text:"Button"
border.color : "black"
border.width: 1
radius: 5
Gradient {
id: lightGradient
GradientStop { position: 0.0; color: anyButton.color }
GradientStop { position: 1.0; color: Qt.darker(anyButton.color,1.5) }
}
Gradient {
id: darkGradient
GradientStop { position: 0.0; color: Qt.darker(anyButton.color,1.7) }
GradientStop { position: 1.0; color: Qt.darker(anyButton.color,1.7) }
}
Rectangle{
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
Text{
id:buttonImage
}
Text{
id: buttonLabel
font.pixelSize:20
text: anyButton.text
}
}
signal buttonClick()
MouseArea{
id: buttonMouseArea
anchors.fill: parent
onClicked: parent.buttonClick()
hoverEnabled: true
onEntered:{
parent.border.width= 2
}
onCanceled:{
parent.border.width= 1
}
onExited: {
parent.border.width= 1
}
}
gradient: buttonMouseArea.pressed ? darkGradient : lightGradient
}
It's quite simple in QML to create a button with custom style, text etc.
With ButtonStyle you can define custom background and label as you want. To get system colors use SystemPalette. Here you can find its application for real controls.
For example:
Button {
anchors.centerIn: parent
property string firstfield: "a"
property string secondfield: "sometext"
iconSource: "data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7"
text: firstfield + " " + secondfield
style: ButtonStyle {
background: Rectangle {
id: bg
border.width: 1
border.color: palette.mid
radius: 3
gradient: Gradient {
GradientStop { position: 0.0; color: control.pressed ? palette.button : palette.light }
GradientStop { position: 0.5; color: palette.midlight }
GradientStop { position: 1.0; color: control.pressed ? palette.light : palette.button }
}
}
label: RowLayout {
id: row
spacing: 5
Image { source: control.iconSource }
Label {text: control.firstfield; font.family: "Symbol"; font.pixelSize: 18; color: palette.buttonText}
Label {text: control.secondfield; color: palette.buttonText}
}
}
}
SystemPalette { id: palette; colorGroup: SystemPalette.Active }
Sure, you can add a shadow etc. If you will drop the ButtonStyle it should look like a regular button

Resources