I'm working on making nice Ui using qml, first I have4 to make the window frameless, then reimplement move and resize behavior from within qml, I found an answer for that on stackoverflow. However, when I try to add some components especially a Toolbar
inside a ColumnLayout
or a Column
I cannot resize the window from the edges where the toolbar exists.
A snippet of my code reproduces this problem try to compile it and resize the window from top, top left or top right edges
.
PS: I'm using Qt 6.2.1 same behavior with glitches in Qt 6.4
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
Window {
id:window
width: 640
height: 480
visible: true
title: qsTr("Hello World")
flags: Qt.FramelessWindowHint | Qt.Window
MouseArea{
id:mouseArea
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.LeftButton
propagateComposedEvents: true
property int edges: 0
property int edgeOffset: 5
function setEdges(x,y){
edges = 0;
if (x < edgeOffset) edges |= Qt.LeftEdge;
if (x > (width - edgeOffset)) edges |= Qt.RightEdge;
if (y < edgeOffset) edges |= Qt.TopEdge;
if (y > (height - edgeOffset)) edges |= Qt.BottomEdge;
}
cursorShape: {
return !containsMouse ? Qt.ArrowCursor:
edges == 3 || edges == 12 ? Qt.SizeFDiagCursor :
edges == 5 || edges == 10 ? Qt.SizeBDiagCursor :
edges & 9 ? Qt.SizeVerCursor :
edges & 6 ? Qt.SizeHorCursor : Qt.ArrowCursor;
}
onPositionChanged: setEdges(mouseX, mouseY);
onPressed: {
setEdges(mouseX, mouseY);
if(edges && containsMouse){
window.startSystemResize(edges);
}
}
}
ColumnLayout{
width: parent.width
height: 50
ToolBar{
DragHandler{
onActiveChanged: if(active) startSystemMove()
}
Layout.fillHeight: true
Layout.fillWidth: true
RowLayout{
Layout.fillWidth: true
Layout.fillHeight: true
ToolButton{
text: " "
onClicked: {
console.log("Hello World")
}
}
Label{
text: "title"
horizontalAlignment: Qt.AlignHCenter
verticalAlignment: Qt.AlignVCenter
Layout.fillWidth: true
}
ToolButton{
text: "x"
onClicked: close()
}
}
}
}
}
CodePudding user response:
I would put the MouseArea
on top by changing the order or the z
property and use the MouseEvent
accepted
property to tell the MouseArea
that the event wasn't consumed and needs to be send further down.
But the bigger issue is that the system move in the DragHandler
doesn't stop when releasing the mouse button. I tried to solve this by using pressAndHold
of the MouseArea
, but without any luck yet.
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
Window {
id: window
width: 640
height: 480
visible: true
title: qsTr("Hello World")
flags: Qt.FramelessWindowHint | Qt.Window
ColumnLayout {
width: parent.width
height: 50
ToolBar {
id: toolBar
Layout.fillHeight: true
Layout.fillWidth: true
RowLayout {
Layout.fillWidth: true
Layout.fillHeight: true
ToolButton {
text: " "
onClicked: console.log("Hello World")
}
Label {
text: "title"
horizontalAlignment: Qt.AlignHCenter
verticalAlignment: Qt.AlignVCenter
Layout.fillWidth: true
}
ToolButton {
text: "x"
onClicked: window.close()
}
}
}
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.LeftButton
property int edges: 0
property int edgeOffset: 5
function setEdges(x, y) {
mouseArea.edges = 0
if (x < mouseArea.edgeOffset) mouseArea.edges |= Qt.LeftEdge
if (x > (mouseArea.width - mouseArea.edgeOffset)) mouseArea.edges |= Qt.RightEdge
if (y < mouseArea.edgeOffset) mouseArea.edges |= Qt.TopEdge
if (y > (mouseArea.height - mouseArea.edgeOffset)) mouseArea.edges |= Qt.BottomEdge
}
cursorShape: {
switch(mouseArea.edges) {
case Qt.LeftEdge | Qt.TopEdge:
case Qt.RightEdge | Qt.BottomEdge:
return Qt.SizeFDiagCursor
case Qt.LeftEdge | Qt.BottomEdge:
case Qt.RightEdge | Qt.TopEdge:
return Qt.SizeBDiagCursor
case Qt.LeftEdge:
case Qt.RightEdge:
return Qt.SizeHorCursor
case Qt.TopEdge:
case Qt.BottomEdge:
return Qt.SizeVerCursor
default:
return Qt.ArrowCursor
}
}
onPositionChanged: function(mouse) {
mouseArea.setEdges(mouse.x, mouse.y)
}
onPressed: function(mouse) {
mouseArea.setEdges(mouse.x, mouse.y)
if (mouseArea.edges && mouseArea.containsMouse)
window.startSystemResize(mouseArea.edges)
mouse.accepted = mouseArea.edges
}
}
}
CodePudding user response:
It seems to me that everything is very clear here. The Toolbar
overlaps that MouseArea
. You probably have to add some margins for the toolbar item. for example:
ColumnLayout{
anchors.top: window.contentItem.top
anchors.left: window.contentItem.left
anchors.right: window.contentItem.right
anchors.margins: 5
height: 50
...
}
Another issue, your RowLayout
inside the toolbar isn't inside some Layout so Layout.fill*
are not applicable for that. You can replace it with anchors.fill: parent