I'm trying to create a gradient color border for a button on a Popup. It seems good if I don't try to centering the popup. I have no word to call the name or describe the issue. Please take a look at the border of the Cancel button in the attached image and the code. (I'm using Qt 6.3)
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
//import QtQuick3D
import Qt5Compat.GraphicalEffects
ApplicationWindow {
id: root
width: 666
height: 777
visible: true
color: "grey"
Button
{
width: 111
height: 44
text: "Show"
onClicked: menu.open()
}
Popup {
id: menu
width: (559)
height: (643)
modal: true
dim: false
focus: true
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
background: Rectangle {
// color: "transparent"
border.color: "transparent"
LinearGradient {
anchors.fill: parent
start: Qt.point(0, 0)
end: Qt.point(0, parent.height)
gradient: Gradient {
GradientStop { position: 0.0; color: "#29395D" }
GradientStop { position: 1.0; color: "#1C2341" }
}
}
}
// Component.onCompleted: {
// x: (parent.width - width) / 2
// y: (parent.height - height) / 2
//// anchors.centerIn = parent
//// anchors.centerIn = Overlay.overlay
// }
// onAboutToShow: anchors.centerIn = Overlay.overlay
anchors.centerIn : Overlay.overlay
Button {
id: okBt
anchors.top: parent.top
anchors.topMargin: (410)
anchors.horizontalCenter: parent.horizontalCenter
width: (276)
height: (41)
text: "OK"
// font.family: FontModel.family
font.pixelSize: (16)
font.weight: Font.Normal //400
contentItem: Text {
text: parent.text
font: parent.font
color: "#FFFFFF"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
flat: true
background: Rectangle {
implicitWidth: (276)
implicitHeight: (41)
radius: (6)
border.width: 0
gradient: Gradient {
orientation: Gradient.Horizontal
GradientStop { position: 1.0; color: "#2F3D6D" }
GradientStop { position: 0.0; color: "#3C5199" }
}
}
}
Button {
id: cancelBt
// visible: false
anchors.top: parent.top
anchors.topMargin: (471)
anchors.horizontalCenter: parent.horizontalCenter
width: (276)
height: (41)
text: "Cancel"
// font.family: FontModel.family
font.pixelSize: (16)
font.weight: Font.Normal //400
contentItem: Text {
text: parent.text
font: parent.font
color: "#FFFFFF"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
flat: true
}
Rectangle {
id: gradientBorder
anchors.top: parent.top
anchors.topMargin: (471)
anchors.horizontalCenter: parent.horizontalCenter
width: (276)
height: (41)
radius: (6)
z: cancelBt.z + 11
color: "transparent"
Rectangle {
id: bd
anchors.fill: parent
radius: parent.radius
gradient: Gradient {
orientation: Gradient.Horizontal
GradientStop { position: 1.0; color: "#2F3D6D" }
GradientStop { position: 0.0; color: "#3C5199" }
}
layer.enabled: true
layer.effect: OpacityMask {
invert: true
maskSource: Item {
width: bd.width
height: bd.height
Rectangle {
anchors.centerIn: parent
width: parent.width -2
height: parent.height -2
radius: gradientBorder.radius
}
}
}
}
}
}
}
The issue you encountering has definitely something to do with half pixel rounding. This is especially an issue when using texture/layers, because internally the textures size (sourceSize
) gets rounded when creating textures from floating point positioned/sized items. I didn't had a proper look at your example when I've created my comment.
In order to work around the issue you should tweak your sizes in order for the items to be pixel aligned. In my example below I've made all your odd sizes even so the anchoring logic doesn't place items on half pixels.
Also instead of using OpacityMask
to create a cutout, I've used a LinearGradient
from the Qt5Compat.GraphicalEffects
and an invisible Rectangle
that gets assigned as the source
.
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Qt5Compat.GraphicalEffects
ApplicationWindow {
id: root
width: 666
height: 777
visible: true
color: "grey"
Button {
width: 111
height: 44
text: qsTr("Show")
onClicked: popup.open()
anchors.centerIn: parent
}
Popup {
id: popup
width: 560
height: 644
modal: true
dim: false
focus: true
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
anchors.centerIn : Overlay.overlay
background: Rectangle {
border.color: "transparent"
LinearGradient {
anchors.fill: parent
start: Qt.point(0, 0)
end: Qt.point(0, parent.height)
gradient: Gradient {
GradientStop { position: 0.0; color: "#29395D" }
GradientStop { position: 1.0; color: "#1C2341" }
}
}
}
Button {
id: okBt
anchors.top: parent.top
anchors.topMargin: 410
anchors.horizontalCenter: parent.horizontalCenter
width: 276
height: 42
text: qsTr("OK")
font.pixelSize: 16
font.weight: Font.Normal
flat: true
contentItem: Text {
text: parent.text
font: parent.font
color: "#FFFFFF"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
background: Rectangle {
implicitWidth: okBt.width
implicitHeight: okBt.height
radius: 6
gradient: Gradient {
orientation: Gradient.Horizontal
GradientStop { position: 1.0; color: "#2F3D6D" }
GradientStop { position: 0.0; color: "#3C5199" }
}
}
}
Button {
id: cancelBt
anchors.top: parent.top
anchors.topMargin: 471
anchors.horizontalCenter: parent.horizontalCenter
width: 276
height: 42
text: qsTr("Cancel")
font.pixelSize: 16
font.weight: Font.Normal
flat: true
contentItem: Text {
text: parent.text
font: parent.font
color: "#FFFFFF"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
Rectangle {
id: dummy
width: cancelBt.width
height: cancelBt.height
color: "transparent"
border.width: 2
radius: 6
visible: false
}
background: LinearGradient {
anchors.centerIn: parent
//anchors.alignWhenCentered: false
width: dummy.width
height: dummy.height
start: Qt.point(0, 0)
end: Qt.point(dummy.width, 0)
source: dummy
gradient: Gradient {
GradientStop { position: 1.0; color: "#2F3D6D" }
GradientStop { position: 0.0; color: "#3C5199" }
}
}
}
}
}