QML Change ScrollBar Handle Color - qml

I want to change the scrollbar handle color, and follow the Qt doc
https://doc.qt.io/qt-5/qtquickcontrols2-customize.html#customizing-scrollbar
here is my code.
ScrollView {
id: view
anchors.top: parent.top
anchors.left: parent.left
contentHeight: 300
contentWidth: view.width
width: 200
height: 200
focus: true
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
Label {
text: "ABC"
font.pixelSize: 224
}
background: Rectangle{
color:"pink"
}
ScrollBar.vertical: ScrollBar {
parent: view
id: control
active: true
contentItem: Rectangle {
implicitWidth: 6
implicitHeight: 100
radius: width / 2
color: control.pressed ? "#81e889" : "#c2f4c6"
}
}
}
enter image description here
this result the handle will fill with scrollbar.
how to changed handle color and do not fill scrollbar?
here is update.
Try to setting implicitHeight to view.contentHeight
ScrollBar.vertical: ScrollBar {
parent: view
id: control
active: true
contentItem: Rectangle {
implicitWidth: 6
implicitHeight: view.contentHeight
radius: width / 2
color: control.pressed ? "#81e889" : "#c2f4c6"
}
}
here is result
It is have same problem,it's change the whole ScrollBar, not handle.

Related

Error when customizing Controls 2 SpinBox

When customizing a QtQuickControls2 SpinBox, I get this error in the console when closing my application :
"There are still \"2\" items in the process of being created at engine destruction."
The number varies depending on how many Spinboxes are in the windows, it goes up for every indicator that was customized (two times per customized SpinBox : one for the up indicator, one for the down indicator). I tried commenting out each part of my custom code, as well as using the example code provided here, so I am positive that this is where the error comes from.
Does anyone know how to get rid of this error ?
Main window code :
import QtQuick 2.7
import QtQuick.Controls 2.3
ApplicationWindow{
width: 1600
height: 900
visible: true
SpinBox_custom{
}
}
Custom SpinBox_custom code :
import QtQuick 2.11
import QtQuick.Controls 2.4
SpinBox {
id: control
value: 50
editable: true
contentItem: TextInput {
anchors.fill: parent
anchors.rightMargin : up.indicator.width
anchors.leftMargin : down.indicator.width
z: 2
text: control.textFromValue(control.value, control.locale)
font.pointSize: Style.textPointSize-2
color: '#7e8d9e'
selectionColor: '#7e8d9e'
selectedTextColor: "white"
horizontalAlignment: Qt.AlignHCenter
verticalAlignment: Qt.AlignVCenter
readOnly: !control.editable
validator: control.validator
inputMethodHints: Qt.ImhFormattedNumbersOnly
}
up.indicator: Rectangle {
x: control.mirrored ? 0 : parent.width - width
height: parent.height
implicitWidth: 20
implicitHeight: 30
color: control.up.pressed ? '#dee2e6' : '#bec6ce'
border.color: enabled ? '#bec6ce' : '#dee2e6'
Text {
text: "+"
font.pixelSize: control.font.pixelSize * 2
color: '#428AC9'
anchors.fill: parent
fontSizeMode: Text.Fit
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
down.indicator: Rectangle {
x: control.mirrored ? parent.width - width : 0
height: parent.height
implicitWidth: 20
implicitHeight: 30
color: control.down.pressed ? '#dee2e6' : '#bec6ce'
border.color: enabled ? '#bec6ce' : '#dee2e6'
Text {
text: "-"
font.pixelSize: control.font.pixelSize * 2
color: '#428AC9'
anchors.fill: parent
fontSizeMode: Text.Fit
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
background: Rectangle {
implicitWidth: 90
}
}
I've just faced the same problem and after some experiments seemed to find that it's somewhat connected to assigning literal values to the value property of SpinBox.
Something similar is also discussed in this report, and these are other things asking for trouble when used in SpinBox mentioned there:
references between internal elements of SpinBox (contentItem, background, [up,down].indicator's)
references to parent in internal elements
assigning id to internal elements
After getting rid of all of that and also changing value: 0 to value: from it automagically stopped warning me with the message in the original post.
Just as a reference, here's the snippet which works for me without the warning:
SpinBox
{
id: control
value: from
from: 0
to: 600
editable: true
enabled: true
leftPadding: topPadding
rightPadding: height
contentItem: Item
{
anchors.left: control.left
anchors.top: control.top
anchors.bottom: control.bottom
implicitWidth: input.implicitWidth
implicitHeight: input.implicitHeight
width: control.width - control.height
height: control.height
TextInput
{
id: input
anchors.fill: parent
text: control.textFromValue(control.value, control.locale)
color: "black"
horizontalAlignment: Qt.AlignHCenter
verticalAlignment: Qt.AlignVCenter
readOnly: !control.editable
validator: control.validator
inputMethodHints: Qt.ImhFormattedNumbersOnly
}
}
up.indicator: Rectangle
{
anchors.top: control.top
anchors.right: control.right
anchors.topMargin: 1
anchors.rightMargin: 1
height: control.height / 2
width: control.height
color: "gold"
}
down.indicator: Rectangle
{
anchors.bottom: control.bottom
anchors.right: control.right
anchors.bottomMargin: 1
anchors.rightMargin: 1
height: control.height / 2
width: control.height
color: "orange"
}
background: Rectangle
{
implicitWidth: 100
border.color: "red"
border.width: 1
radius: 2
}
}

QML Slider : handle and mouse cursor

I created a slider in an item and customized it like in the following code :
Item {
id: item1
x: 0
y: 0
width: 200
height: parent.height
Rectangle {
id: background
anchors.fill: parent;
color:Qt.rgba(0.9,0.9,0.9,1);
}
Slider {
anchors.centerIn: parent
orientation: Qt.Vertical
height: parent.height
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
width: 20
height: 20
radius: 6
}
}
}
}
The problem appears when I change the size of the handle to have it wider than high, so I change in the handle :
width: 20
height: 80 //the height is changed instead of width but I think
//it's because it is a vertical slider
And then, when I move the handle, it doesn't stay under the mouse cursor but there is an offset between the two.
How to fix that?
The slider is internally rotated 90 degrees when the orientation is vertical, so you'll need to set the width instead of the height. In other words, always style the handle assuming that the slider is horizontal, and the rest will just work...
... except for the mouse offset bug that you just ran into. It appears that your use case isn't auto-tested. Please submit a bug report at bugreports.qt.io.

QML: Center variable text and image

I need to horizonally center a variable-length text (red box) and an image (yellow box) in a big box (green box). The text shall wrap if it does not fit the box.
Existing code:
Item {
id: bigBox
x: 255
y: 0
width: 800
height: 100
Image {
id: imageBox
source: "image.png"
width: 52
height: 46
anchors.left: parent.left
anchors.leftMargin: 12
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Image.AlignLeft
verticalAlignment: Image.AlignVCenter
fillMode: Image.Pad
}
Text {
id: textBox
anchors.left: symbol.right
anchors.leftMargin: 12
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
text: qsTr("heading text")
font.pixelSize: 36
font.bold: true
horizontalAlignment: Text.AlignCenter
}
}
Update:
Actual running code and a real screenshot showing the problem:
import QtQuick 2.0
Rectangle {
id: mask
x: 0
y: 0
width: 800
height: 430
color: "#FFFFFF"
property int pageState: 0
Rectangle {
x: 0
y: 0
width: 111
height: 100
color: "#0000FF"
}
Item {
id: whitespace
x: 117
y: 0
width: 800-x
height: 100
Row {
anchors.centerIn: parent
Image {
id: symbol
source: "../img/pepper.png"
width: 52
height: 46
anchors.verticalCenter: parent.verticalCenter
fillMode: Image.Pad
}
Text {
id: heading
property var texts: ["Active Blabla","Active Blaaaaaaah Blaaaah ","Active Blabla and Blaaaaaaah Blaaaah"]
anchors.verticalCenter: parent.verticalCenter
color: "#333191"
text: texts[pageState]
font.family: "Liberation Sans"
font.pixelSize: 36
font.bold: true
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
textFormat: Text.PlainText
width: Math.min(150,contentWidth)
}
}
}
Rectangle {
id: stage
x: 0
y: 106
width: parent.width
height: parent.height-y
color: "#FFFF00"
}
Timer {
interval: 1000 // milliseconds
triggeredOnStart: true
repeat: true
running: true
onTriggered: {
pageState=(pageState+1)%3;
}
}
}
The white area top right is the green box in the first picture. The timer simply runs through the three texts, like the real application would do.
Changing the first parameter of Math.min() to 600 does not change anything.
My set of hacks to solve that problem:
Item {
// ...
Text {
function escapeHTML(text)
{
return text.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""");
}
function toHTML(imageUrl,text)
{
var textlines=escapeHTML(text).replace(/\r?\n/,"\n").split("\n");
var retval="<center>";
retval=retval+'<table><tr>';
if (imageUrl!="") {
retval=retval+'<td rowspan="'+(textlines.length)+'"><img src="'+imageUrl+'"></td>';
retval=retval+'<td rowspan="'+(textlines.length)+'"> </td>';
}
for (var i=0; i<textlines.length; i++) {
if (i>0) {
retval=retval+"<tr>";
}
retval=retval+'<td>'+textlines[i]+'</td></tr>';
}
retval=retval+'</table>';
retval=retval+"</center>";
return retval;
}
anchors.fill: parent
verticalAlignment: Text.AlignVCenter
textFormat: Text.RichText
text: toHtml("../img/pepper.png",qsTr("heading"))
}
}
<center> centers the text in the available space, but not the image
(it stays left - bug!).
<table> can be centered by <center>, and it can contain the
image.
Wrapping does not work as expected, so the translated text returned
by qsTr() has to contain linebreaks at the right positions.
toHTML() splits at the linebreaks and generates table rows from that.
The image needs a table cell with rowspan, or else the image is placed too high relative to the text.
And finally, verticalAlignment: Text.AlignVCenter places all of that vertically centered -- except for the table borders that I luckily don't need. (If you are bored, add border=1 to the <table> tag.)
And no, the HTML and CSS subset supported by Text.RichText does not support vertical alignment. The rendering engine behaves like ancient browsers, you have to stack hacks and workarounds as if it was still 1996.
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.2
Item {
id: bigBox
width: 800
height: 100
Row {
anchors.centerIn: parent
Image {
anchors.verticalCenter: parent.verticalCenter
source: "blue.png"
}
Text {
anchors.verticalCenter: parent.verticalCenter
// maximum width of the text
width: Math.min(150, contentWidth)
text: qsTr("heading")
wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignHCenter
}
}
}

Image size different after second click on it

I have following minimal working example, taken from my current project:
import QtQuick 2.5
import QtQuick.Window 2.2
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.4
Window {
visible: true
width: Screen.width/2
height: Screen.height/2
property real ueMinOpacity: 0.00
property real ueMaxOpacity: 1.00
Rectangle {
anchors.fill: parent
anchors.margins: 8
border.color: "#4682b4"
radius: 16
clip: true
gradient: Gradient {
GradientStop {
position: 0
color: "#ffffff"
} // GradientStop
GradientStop {
position: 1
color: "#303030"
} // GradientStop
} // Gradient
Rectangle {
anchors.fill: parent
antialiasing: true
border.color: "#4682b4"
border.width: 1
radius: 16
clip: true
gradient: Gradient {
GradientStop {
position: 0
color: "#ffffff"
} // GradientStop
GradientStop {
position: 1
color: "#000000"
} // GradientStop
} // Gradient
RowLayout {
spacing: 8
anchors.fill: parent
TextField {
id: ueProductSearchTextField
antialiasing: true
Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignLeft|Qt.AlignVCenter
Layout.margins: 8
placeholderText: qsTr("Enter product info")
} // TextField
Rectangle {
id: ueImageWrapper
Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignRight|Qt.AlignVCenter
Layout.margins: 8
antialiasing: true
border.color: "#4682b4"
border.width: 1
radius: 16
clip: true
visible: ueProductSearchTextField.length > 0
gradient: Gradient {
GradientStop {
position: 0
color: "#636363"
} // GradientStop
GradientStop {
position: 1
color: "#303030"
} // GradientStop
} // Gradient
Image {
anchors.fill: parent
source: "http://www.clipartbest.com/cliparts/9iR/gEX/9iRgEXXxT.png"
antialiasing: true
clip: true
smooth: true
fillMode: Image.PreserveAspectFit
horizontalAlignment: Image.AlignHCenter
verticalAlignment: Image.AlignVCenter
sourceSize.width: 96
sourceSize.height: 96
} // Image
MouseArea {
anchors.fill: parent
enabled: ueImageWrapper.visible
onClicked: {
ueProductSearchTextField.text="";
} // onClicked
} // MouseArea
onWidthChanged: {
print("ueImageWrapper.width:"+ueImageWrapper.width);
} // onWidthChanged
onHeightChanged: {
print("ueImageWrapper.height:"+ueImageWrapper.height);
} // onHeightChanged
} // Rectangle
} // RowLayout
} // Rectangle
} // Rectangle
} // Window
Now, the purpose of this Item/Rectangle is to filter database records according to TextField's entered value, which works perfectly. However, once TextField's text is not empty anymore (when user enters some string), on the right side of Layout Image for clearing text is shown via OpacityAnimator. Once the app is launched, I get following screenshot - clear text icon is hidden since there is not text in TextField:
Then, I enter some text into TextField and clear text icon pops up:
Then, for instance, I clear text by clicking on clear text icon and it (icon) is hidden again, which is ok:
And finally, I reenter text into TextField, clear text icon is visible again, but it has different size:
Why? I did not change the code. It must be some problem with Layouts, but I simply do not see it! Here is also a debug output from onWidthChanged and onHeightChanged handlers:
qml: ueImageWrapper.width:37.56521739130435
qml: ueImageWrapper.height:480
qml: ueImageWrapper.width:132.92307692307693
qml: ueImageWrapper.width:133.83783783783784
BaCaRoZzo's suggestion works, but I'm also a bit unsure about why it behaves the way it does. If you take a simpler example:
import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Layouts 1.0
import QtQuick.Controls 1.0
Window {
visible: true
width: 800
height: 800
Shortcut {
sequence: "Ctrl+Q"
onActivated: Qt.quit()
}
Item {
id: boundary
width: 400
height: 400
anchors.centerIn: parent
RowLayout {
anchors.fill: parent
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
color: "steelblue"
}
Rectangle {
id: rect
Layout.fillWidth: true
Layout.fillHeight: true
color: "salmon"
visible: false
}
}
}
Rectangle {
anchors.fill: boundary
color: "transparent"
border.color: "black"
}
Button {
text: "Toggle visibility"
onClicked: rect.visible = !rect.visible
}
}
The second rectangle starts off being invisible, and is then shown/hidden by clicking the button. However, when it starts off as invisible, it never gets a size once shown. On the other hand, if it starts off visible, then it gets half the width of the layout.
If you read the documentation carefully, it doesn't say that it's necessary to set a preferredWidth/preferredHeight if you just want to make an item fill the available space. For that reason, it seems like a bug in how layouts handle initial visibility of their items. I'd suggest filing a bug report.

QML property is null

I'm trying to define a property with a default value in a reuseable QML component. Here's my code thus far:
property alias value: progressBar.value
property bool error: false
property ProgressBarStyle errorStyle: ProgressBarStyle {
background: Rectangle {
radius: 2
color: "lightgray"
border.color: "gray"
border.width: 1
implicitWidth: 200
implicitHeight: 24
}
progress: Rectangle {
color: "orangered"
border.color: "red"
}
}
Layout.fillWidth: true
ProgressBar {
id: progressBar
Layout.fillWidth: true
minimumValue: 0.0
maximumValue: 100.0
style: errorStyle
}
So the idea is errorStyle is constructed and set as the style of progressBar. I know that errorStyle works, because if I set it directly on progressBar it works. From what I can tell, the problem is errorStyle is null when I run my program.
UPDATE:
Maybe a better way of stating this question is: "How do I get around the 'PropertyChanges does not support creating state-specific objects.' error message that I get if I create the style directly in the PropertyChanges array?
UPDATE 2:
I"ve basically given up on this approach and decided to try and using styling instead. This has lead to another question: Cannot create certain QML types in a singleton
You can try declaring it with an id, and use the id. So dont declary it as a property but just like a component. Like this:
ProgressBarStyle {
id: errorStyle
background: Rectangle {
radius: 2
color: "lightgray"
border.color: "gray"
border.width: 1
implicitWidth: 200
implicitHeight: 24
}
progress: Rectangle {
color: "orangered"
border.color: "red"
}
}
ProgressBar {
id: progressBar
Layout.fillWidth: true
minimumValue: 0.0
maximumValue: 100.0
style: errorStyle
}
But the approach i would take would be the make a property color and bordercolor and change the rectangle color of the style instead of changing the style completely.
Like this:
property Color barColor
property Color barBorderColor
property Color progressColor
property Color progressBorderColor
ProgressBar {
id: progressBar
Layout.fillWidth: true
minimumValue: 0.0
maximumValue: 100.0
style: ProgressBarStyle {
background: Rectangle {
radius: 2
color: barColor
border.color: barBorderColor
border.width: 1
implicitWidth: 200
implicitHeight: 24
}
progress: Rectangle {
color: progressColor
border.color: progressBorderColor
}
}
}