I'm having an issue with a Qt Quick custom button. The planned behaviour is the button background, border, and text changes color on hover and pressed actions. The color change aspect is working, but when the button is pressed, it appears to lose it's radius setting (image of button states). I thought this might be related to the highlighted setting, but setting that to false, doesn't fix it. Any ideas what might be causing this behaviour?
import QtQuick 2.15
import QtQuick.Controls 2.15
Button {
id: customButton
text: qsTr("Custom Button")
highlighted: false
flat: true
implicitWidth: 200
implicitHeight: 40
// Custom Properties
// Button Colors
property color defaultButtonColor: "#DB8000"
property color hoverButtonColor: "#784491"
property color pressedButtonColor: "#315718"
// Text Colors
property color defaultTextColor: "#ffffff"
property color hoverTextColor: "#ffffff"
property color pressedTextColor: "#000000"
QtObject {
id: internal
property var dynamicColor: if (customButton.down) {
customButton.down ? pressedButtonColor : defaultButtonColor
} else {
customButton.hovered ? hoverButtonColor : defaultButtonColor
}
property var dynamicText: if (customButton.down) {
customButton.down ? pressedTextColor : defaultTextColor
} else {
customButton.hovered ? hoverTextColor : defaultTextColor
}
}
background: Rectangle {
id:bg_customButton
radius: 15
color: internal.dynamicColor
border.color: "#000000"
}
contentItem: Item {
id: item1_customButton
Text {
id: text_customButton
text: customButton.text
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
color: internal.dynamicText
}
}
}
Edit: Don't think it's the radius changing, something is being displayed over the baackground during the pressed event as the border is partial visible if more contrasting colors are used pressed button edges
Edit#2: Same behaviour when trying to use States, as suggested by #TOHO, but there could be errors in this given it's a first attempt as using them.
import QtQuick 2.15
import QtQuick.Controls 2.15
Button {
id: customButton
// Button Colors
property color defaultButtonColor: "#DB8000"
property color hoverButtonColor: "#784491"
property color pressedButtonColor: "#315718"
// Border Colors
property color defaultBorderColor: "#ffffff"
property color hoverBorderColor: "#ffffff"
property color pressedBorderColor: "#FF0800"
// Text Colors
property color defaultTextColor: "#ffffff"
property color hoverTextColor: "#ffffff"
property color pressedTextColor: "#000000"
text: qsTr("Custom Button")
clip: false
highlighted: false
flat: true
hoverEnabled: true
implicitWidth: 200
implicitHeight: 40
onHoveredChanged: if (hovered) {bg_customButton.state = "HOVER"} else {bg_customButton.state = "DEFAULT"}
onReleased: bg_customButton.state = "DEFAULT"
onPressed: bg_customButton.state = "PRESS"
background: Rectangle {
id: bg_customButton
radius: 15
border.color: defaultBorderColor
state: "DEFAULT"
states: [
State {
name: "DEFAULT"
PropertyChanges { target: bg_customButton; color: defaultButtonColor; border.color: defaultBorderColor}
PropertyChanges { target: text_customButton; color: defaultTextColor}
},
State {
name: "HOVER"
PropertyChanges { target: bg_customButton; color: hoverButtonColor; border.color: hoverBorderColor}
PropertyChanges { target: text_customButton; color: hoverTextColor}
},
State {
name: "PRESS"
PropertyChanges { target: bg_customButton; color: pressedButtonColor; border.color: pressedBorderColor}
PropertyChanges { target: text_customButton; color: pressedTextColor}
}
]
}
contentItem: Item {
id: item1_customButton
clip: true
Text {
id: text_customButton
text: customButton.text
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
state: "DEFAULT"
}
}
}
your problem was that hoverEnabled was false (by default),
and as I said in comments this is not best practice but here is a working example:
import QtQuick 2.15
import QtQuick.Controls 2.15
Rectangle {
id: root
anchors.fill: parent;
color: "grey"
Button {
anchors.centerIn: parent;
id: customButton
text: qsTr("Custom Button")
highlighted: false
flat: true
implicitWidth: 200
implicitHeight: 40
hoverEnabled: true
// Custom Properties
// Button Colors
property color defaultButtonColor: "#DB8000"
property color hoverButtonColor: "#784491"
property color pressedButtonColor: "#315718"
// Text Colors
property color defaultTextColor: "#ffffff"
property color hoverTextColor: "#ffffff"
property color pressedTextColor: "#000000"
readonly property color currentColor: down? pressedButtonColor: hovered ? hoverButtonColor : defaultButtonColor;
readonly property color currentTextColor: down? pressedTextColor: hovered ? hoverTextColor : defaultTextColor;
background: Rectangle {
id:bg_customButton
radius: 15
color: customButton.currentColor
border.color: "#000000"
}
contentItem: Item {
id: item1_customButton
Text {
id: text_customButton
text: customButton.text
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
color: customButton.currentTextColor
}
}
}
}
Related
i have created a custom button in qml, which i want to focus on pressing 'tab', i mean "jump to it on pressing tab if its on top of queue" by default qml has this functionality on button itself and some of other controls too but what about new components which does not exist,i saw a "FocusScope" control of qml but there is no documentation of using it and i am not sure how can i implement it, here is my control :
import QtQuick 2.4
Item {
id: button
width: innerText.width + 10
height: 30
property alias text: innerText.text;
property alias font: innerText.font;
property color color: "#00171f"
property color hoverColor: "#00395f"
property color pressColor: "#3E65FF"
property int fontSize: 12
property int borderWidth: 0
property int borderRadius: 2
property bool highlighted : true
onEnabledChanged: state = ""
signal clicked
property var background
Rectangle {
id: rectangleButton
anchors.fill: button
radius: borderRadius
color: button.enabled ? button.color : "grey"
border.width: borderWidth
border.color: "black"
Text {
id: innerText
font.pointSize: fontSize
font.family: "B Nazanin"
color: "white"
anchors.centerIn: rectangleButton
}
}
//change the color of the button in differen button states
states: [
State {
name: "Hovering"
PropertyChanges {
target: rectangleButton
color: hoverColor
}
},
State {
name: "Pressed"
PropertyChanges {
target: rectangleButton
color: pressColor
}
}
]
//define transmission for the states
transitions: [
Transition {
from: ""; to: "Hovering"
ColorAnimation { duration: 200 }
},
Transition {
from: "*"; to: "Pressed"
ColorAnimation { duration: 10 }
},
Transition {
from: "*"
to: ""
ColorAnimation { duration: 200 }
}
]
//Mouse area to react on click events
MouseArea {
hoverEnabled: true
anchors.fill: button
onEntered: { button.state='Hovering'}
onExited: { button.state=''}
onClicked: { button.clicked();}
onPressed: { button.state="Pressed" }
onReleased: {
if (containsMouse)
button.state="Hovering";
else
button.state="";
}
}
}
It looks like you are simply looking for the activeFocusOnTab property:
Item {
id: button
activeFocusOnTab: true
// ...
}
I developing qml project in that i want to add functionality of changing background color ..
for that i create one combo box with items {red,blue,white} and create one update button to update color when user select red item and click on update background color change as red so how can i do ??
Button {
id: button1
x: 284
y: 95
width: 114
height: 34
text: qsTr("Update")
contentItem: Text {
font: control.font
opacity: enabled ? 1.0 : 0.3
text: "Update"
//Font.pixelSize:15
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
background: Rectangle {
id: myRectId1
color: Colorchange.Rectange_Color
radius: 8
}
onHoveredChanged: hovered ? myRectId1.opacity = 1 :
myRectId1.opacity = .80;
MouseArea {
id: mouseAreaScanbtn
anchors.fill: parent
hoverEnabled: true;
onEntered: { myRectId1.border.width = 2 }
onExited: { myRectId1.border.width = 1 }
onClicked: {
//i want to add some code here to change background color
// i tried
//window.color:combobox.currantindex()
}
}
}
hi just use ComboBox Qml type like this:
ComboBox {
currentIndex: -1
width: 200
model: [ "white", "blue" , "red" ]
onCurrentIndexChanged:{
background.color=model[currentIndex]
}
}
or if you want to update the background color after user click the button you should save the color that user selected in a property then use this in onClicked of your button:
Item {
id:root
property var SelectedColor
ComboBox {
currentIndex: -1
width: 200
model: [ "white", "blue" , "red" ]
onCurrentIndexChanged:{
SelectedColor=model[currentIndex]
}
}
in Qml there is auto key navigation for already known components like checkbox,textfield,button and etc , i have my custom component which is a item or rectangle and i want same functionality for it,without writing
KeyNavigation.tab: componentid
here is one of my custom controls :
Rectangle {
signal clicked
property alias font : icoText.font.family
property alias icon : icoText.text
property alias size : icoText.font.pixelSize
property alias toolTip : tooltipText.text
property string colorEnter :"#0481ff"
property string colorExit :"#00171f"
id: root
implicitWidth: 50
implicitHeight: 50
//width: childrenRect.width
radius: 0
//height: childrenRect.height
color: colorExit
state: "default"
Text {
id: icoText
text: ""
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
font.pixelSize: 25
font.family: "fontawesome"
visible: text!= ""
color: "white"
}
ToolTip {
id:tooltipText
text: ""
delay: 500
timeout: 2000
visible: mouseArea.containsMouse && text!=""
font.family: "B Nazanin"
contentItem: Text {
text: tooltipText.text
font: tooltipText.font
color: "white"
}
background: Rectangle {
color: "#cc000000"
border.color: "black"
}
}
InnerShadow {
id:shadow
anchors.fill: icoText
radius: 1.0
samples: 17
horizontalOffset: 1
color: colorExit
source: icoText
visible: false
}
MouseArea{
id: mouseArea
anchors.fill: parent
hoverEnabled: true
onEntered: root.color = colorEnter
onExited: root.color = root.state == "transparent"? "transparent" : root.colorExit
onPressed: {
shadow.visible = true
}
onReleased: {
shadow.visible = false
}
onClicked: {
root.clicked()
}
}
states: [
State {
name: "transparent"
PropertyChanges {
target: root
color:"transparent"
}
PropertyChanges {
target: icoText
color:colorExit
}
},
State{
name: "default"
PropertyChanges {
target: root
color:colorExit
}
PropertyChanges {
target: icoText
color:"white"
}
}
]
}
which will be inside a page like this :
Item{
myControl{
}
myControl{
}
}
this component by default does not loop through pressing tab what should i do?
i already tried this without success, i think this should be inside FocusScope but cause of poor documentation i did not get a simple example for this
set activeFocusOnTab on parent and focus:true in child you want to get focus
Rectangle{
activeFocusOnTab: true
Control{
focus: true
}
}
Focusable Qml Components (Focus My Control On Tab)
For my experience key navigation only works with native components like checkbox, textfield, button, etc.
To work arround this problem I used a fake native component hided with the same size of my custom component like the next example:
Rectangle {
id: myCustomComponent1
width: 100
height: 100
color: red
Button {
id: buttonFake1
text: "My Accessible text Component 1"
width: parent.width
height: parent.height
opacity: 0 // hide the fake component
Accessible.role: Accessible.defaultButton
Accessible.name: text
KeyNavigation.tab: buttonFake2
onClicked: {
console.log(index)
}
onFocusChanged: {
if(focus === true){
// Here do what you want with your custom component
// For example, change color, size, ...
Do_what_you_Want()
// And then set back the focus at the fake native component
// to key navigation keeps working from the same component
buttonFake1.focus = true
}
}
}
}
Rectangle {
id: myCustomComponent2
width: 100
height: 100
color: green
Button {
id: buttonFake2
text: "My Accessible text Component 2"
width: parent.width
height: parent.height
opacity: 0 // hide the fake component
Accessible.role: Accessible.defaultButton
Accessible.name: text
KeyNavigation.tab: buttonFake1
onClicked: {
console.log(index)
}
onFocusChanged: {
if(focus === true){
// Here do what you want with your custom component
// For example, change color, size, ...
Do_what_you_Want()
// And then set back the focus at the fake native component
// to key navigation keeps working from the same component
buttonFake2.focus = true
}
}
}
}
I have a ListModal as follows:
ListModel {
ListElement { icon: "qrc:/icons/gallery/20x20/profile.png"; icon.color: "transparent"; title: "Profile"; source: "qrc:/src/qml/pages/Profile.qml" }
ListElement { icon: "qrc:/icons/gallery/20x20/lock.png"; icon.color: "transparent"; title: "Connect"; source: "qrc:/src/qml/pages/Connect.qml" }
}
When my application uses the dark theme of a style (i.e Universal), my icons are hard to see. I would like them to have a transparent color so the color is inverted upon theme change, similar to this code:
ListView {
id: listView
focus: true
currentIndex: -1
anchors.fill: parent
delegate: ItemDelegate {
width: parent.width
text: model.title
icon.source: model.icon
icon.height: 20
icon.width: 20
icon.color: "transparent"
highlighted: ListView.isCurrentItem
onClicked: {
listView.currentIndex = index
stackView.push(model.source)
drawer.close()
}
}
Is there a way I can do this easily?
I haven't used themes or styles much, but I believe you can specify the icon's color depending on what theme is currently in use with a ternary operator:
icon.color: (Material.theme === Material.Dark) ? "white" : "black"
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)
}
}