What I am trying to do is create this in Qml (w/o using any images):
Specification
It is a button that has:
- a linear gradient as background
- two borders
- each has a width of 1px
- the colors have an alpha, so the background will effect the actual visible color of each pixel
- the outer border is above the general background of the application
- the inner border is above the gradient
- the colors of the inner and outer border of the left side is interchanged compared to the bottom and right border (i.e. color of inner border left = color of outer border bottom, etc.)
- on the bottom left and bottom right (but not on the top!) there is a 3px radius
In CSS (the reference implementation is a browser single-page application) it is done with this code:
border-bottom-left-radius: 3px;
border-bottom-right-radius: 3px;
box-shadow: rgba(152, 182, 219, 0.15) 0px 0px inset, rgba(2, 2, 4, 0.4) -1px 0px inset, rgba(2, 2, 4, 0.4) 0px -1px inset, rgba(152, 182, 219, 0.15) 1px 0px inset;
background: linear-gradient(rgb(47, 72, 99) 30%, rgb(36, 51, 71) 100%) padding-box;
border-bottom: 1px solid rgba(152, 182, 219, 0.15);
border-left: 1px solid rgba(2, 2, 4, 0.4);
border-right: 1px solid rgba(152, 182, 219, 0.15)
I am having trouble recreating this in Qml. As the radius property of the rectangle can only be set equal for all corners, I followed the idea mentioned in https://stackoverflow.com/a/39971599 . The result without using borders looks like this:
no borders
And this is the code I use for it:
Button {
id: headerConfigButton
// ...
background: Rectangle {
color: "transparent"
Rectangle {
height: headerConfigButton.height - headerConfigButtonLowerBackground.radius
width: headerConfigButton.width
}
Rectangle {
id: headerConfigButtonLowerBackground
radius: 3
height: headerConfigButton.height
width: headerConfigButton.width
color: "#242e3a"
}
LinearGradient {
source: parent
anchors.fill: parent
start: Qt.point(0, 0)
end: Qt.point(0, parent.height)
gradient: Gradient {
GradientStop {
position: 0.0
color: "#344a62"
}
GradientStop {
position: 1.0
color: "#293749"
}
}
}
}
}
Applying the borders was a little clumsy - I made a rectangle ("1px line") for each side and each border. Without the radius it looks like as in this picture:
no radius
Please note that the alpha values of the borders are not respected in this imgage; I found it easier to see what happens without using them.
The code for this:
Button {
id: headerConfigButton
// ...
background: Rectangle {
color: "transparent"
Rectangle { // left outer border
width: 1
height: headerConfigButton.height
color: "#181e26"
}
Rectangle { // left inner border
x: 1
width: 1
height: headerConfigButton.height - 1
color: "#4d637d"
}
Rectangle { // bottom outer border
x: 1
y: headerConfigButton.height - 1
width: headerConfigButton.width - 2
height: 1
color: "#344151"
}
Rectangle { // bottom inner border
x: 2
y: headerConfigButton.height - 2
width: headerConfigButton.width - 4
height: 1
color: "#181e26"
}
Rectangle { // right inner border
x: headerConfigButton.width - 2
width: 1
height: headerConfigButton.height - 1
color: "#181e26"
}
Rectangle { // right outer border
x: headerConfigButton.width - 1
width: 1
height: headerConfigButton.height
color: "#344151"
}
Rectangle { // gradient fill
id: headerConfigButtonGradientFill
x: 2
width: headerConfigButton.width - 4
height: headerConfigButton.height - 2
LinearGradient {
source: parent
anchors.fill: parent
start: Qt.point(0, 0)
end: Qt.point(0, parent.height)
gradient: Gradient {
GradientStop {
position: 0.0
color: "#344a62"
}
GradientStop {
position: 1.0
color: "#293749"
}
}
}
}
}
}
But now I struggle to create the round corners in conjunction with the borders. One issue is that the color of the outer and inner borders are not the same on each side. In conjunction with the opacity of the border colors, I have no idea how to get the colors in the corners right. Additionally, the gradient needs to be cropped as well.
The colors of the gradient and borders shall be themeable later on. Thus, using a background image or recreating the corners pixel by pixel with fixed colors taken from the spec is not an option.
Has anyone got an idea how to solve this? Maybe I am completely off and there is a much better and easier way to do this?
Thanks in advance!