前言
QtWidgets开发实现这两个功能网上有很多,qml却有很少,但是要想用qml去做好看的桌面端,这些工作就必不可少。
这篇文章参考的是网上的一篇博客QtQuick实现无边框窗口的拉伸,拖拽和自定义标题栏 - 简书 (jianshu.com)
,在此基础上进行了一些修改。
自定义标题栏
先说一下标题栏一般有什么功能:
1.显示标题
2.最小化,最大化(还原)、关闭
3.按着鼠标左键,可移动窗口(当时最大化窗口时,还原为常态),双击标题栏放大或还原窗口
由于我应用的标题是图片显示的,所以代码中就没有Text等控件来书写标题,所以代码中只有2、3功能的代码。
对了,在main.qml文件里别忘了设置窗口为无边框(Qt.FramelessWindowHint)
Window {
id:mainWindow;
width: 1500;
height: 846;
visible: true
flags: Qt.Window | Qt.FramelessWindowHint;
}
2功能:最小化和关闭按钮都比较简单,写个按钮,直接调用窗口函数就可以。最大化(还原)按钮比较麻烦一些,就是图标切换麻烦些,我用属性maxImg、maxImg_hover和maxImg_pressed
代表最大化(还原)按钮的底图地址,通过切换属性的值来改变最大化时按钮的底图和常态时按钮的底图
3功能,逻辑与QtWidgets开发的一样,只是有不同的语言实现了。
以下是TitleBar.qml的全部内容:
import QtQuick 2.7
import QtQuick.Controls 2.13
import QtQuick.Window 2.2
Item{
z:1;
height: 100*hr;
property bool isMaximized: false;
MouseArea{
anchors.fill: parent
acceptedButtons: Qt.LeftButton //只处理鼠标左键
property bool isDoubleClicked:false
property point clickPos: "0,0"
onPressed:
{
isDoubleClicked = false;
clickPos = Qt.point(mouse.x,mouse.y)
}
onPositionChanged: {
if(!isDoubleClicked && pressed && mainWindow.visibility !== Window.Maximized && mainWindow.visibility !== Window.FullScreen) {
var delta = Qt.point(mouse.x-clickPos.x, mouse.y-clickPos.y)
mainWindow.x += delta.x
mainWindow.y += delta.y
}
if(mainWindow.visibility === Window.Maximized && pressed && !isDoubleClicked)
{
isMaximized = false;
mainWindow.showNormal();
normBtn.maxImg="qrc:/res/max.png";
normBtn.maxImg_pressed="qrc:/res/max_pressed.png";
normBtn.maxImg_hover="qrc:/res/max_hover.png";
}
}
onDoubleClicked :
{
isDoubleClicked = true; // 这个时候一定不能响应onPositionChanged不然会一直置顶。
if(isMaximized){
isMaximized = false;
mainWindow.showNormal();
normBtn.maxImg="qrc:/res/max.png";
normBtn.maxImg_pressed="qrc:/res/max_pressed.png";
normBtn.maxImg_hover="qrc:/res/max_hover.png";
}else{
isMaximized = true;
mainWindow.showMaximized();
normBtn.maxImg="qrc:/res/restore.png";
normBtn.maxImg_pressed="qrc:/res/restore_pressed.png";
normBtn.maxImg_hover="qrc:/res/restore_hover.png";
}
}
}
Button{
id:closeBtn
anchors{right: parent.right; rightMargin: 51*wr; top: parent.top;
topMargin: 23*wr;}
width: 65*wr; height:65*wr;
hoverEnabled : true;
background: Rectangle{
color: Qt.rgba(0,0,0,0);
Image {
anchors.fill: parent;
source: closeBtn.hovered ? (closeBtn.pressed ? "qrc:/res/close_pressed.png" :
"qrc:/res/close_hover.png") : "qrc:/res/close.png";
}
}
onClicked: {
mainWindow.close()
}
}
Button{
id: normBtn;
property string maxImg: "qrc:/res/max.png";
property string maxImg_hover: "qrc:/res/max_hover.png";
property string maxImg_pressed: "qrc:/res/max_pressed.png";
anchors{right: closeBtn.left; rightMargin: 10*wr; top: parent.top;
topMargin: 23*wr;}
width: 65*wr; height:65*wr;
hoverEnabled : true
background: Rectangle{
color: Qt.rgba(0,0,0,0);
Image {
id:normBtnBg;
anchors.fill: parent;
source: normBtn.hovered ? (normBtn.pressed ? normBtn.maxImg_pressed:
normBtn.maxImg_hover) : normBtn.maxImg;
}
}
onClicked:{
if(isMaximized){
isMaximized = false;
mainWindow.showNormal();
normBtn.maxImg="qrc:/res/max.png";
normBtn.maxImg_pressed="qrc:/res/max_pressed.png";
normBtn.maxImg_hover="qrc:/res/max_hover.png";
}else{
isMaximized = true;
mainWindow.showMaximized();
normBtn.maxImg="qrc:/res/restore.png";
normBtn.maxImg_pressed="qrc:/res/restore_pressed.png";
normBtn.maxImg_hover="qrc:/res/restore_hover.png";
}
}
}
Button{
id: minBtn
anchors{right: normBtn.left; rightMargin: 10*wr; top: parent.top;
topMargin: 23*wr;}
width: 65*wr; height:65*wr;
hoverEnabled : true
background: Rectangle{
color: Qt.rgba(0,0,0,0);
Image{
anchors.fill: parent;
source: minBtn.hovered ? (minBtn.pressed ? "qrc:/res/min_pressed.png" :
"qrc:/res/min_hover.png") : "qrc:/res/min.png";
}
}
onClicked:{
mainWindow.showMinimized();
}
}
}
无边框实现拖拽边沿改变大小
这部分代码和参考博客的不同的是,鼠标的形状的改变是我用qml实现的,而不是用c++.
ResizeItem.qml
import QtQuick 2.0
import QtQuick.Window 2.2
Item {
property int enableSize: 4
property bool isPressed: false
property point customPoint
//左上角
Item {
id: leftTop
width: enableSize
height: enableSize
anchors.left: parent.left
anchors.top: parent.top
z: 1000
MouseArea {
anchors.fill: parent
hoverEnabled: true
onPressed: press(mouse)
cursorShape: containsMouse?Qt.SizeFDiagCursor:Qt.ArrowCursor;
onReleased: release()
onPositionChanged: positionChange(mouse, -1, -1)
}
}
//Top
Item {
id: top
height: enableSize
anchors.left: leftTop.right
anchors.right: rightTop.left
anchors.top: parent.top
z: 1000
MouseArea {
anchors.fill: parent
hoverEnabled: true
onPressed: press(mouse)
cursorShape: containsMouse?Qt.SizeVerCursor:Qt.ArrowCursor;
onReleased: release()
onMouseYChanged: positionChange(Qt.point(customPoint.x, mouseY), 1, -1)
}
}
//右上角
Item {
id: rightTop
width: enableSize
height: enableSize
anchors.right: parent.right
anchors.top: parent.top
z: 1000
MouseArea {
anchors.fill: parent
hoverEnabled: true
onPressed: {
press(mouse);
}
cursorShape: containsMouse?Qt.SizeBDiagCursor:Qt.ArrowCursor;
onReleased: release()
onPositionChanged: positionChange(mouse, 1, -1)
}
}
//Left
Item {
id: left
width: enableSize
anchors.left: parent.left
anchors.top: leftTop.bottom
anchors.bottom: leftBottom.top
z: 1000
MouseArea {
anchors.fill: parent
hoverEnabled: true
onPressed: press(mouse)
cursorShape: containsMouse?Qt.SizeHorCursor:Qt.ArrowCursor;
onReleased: release()
onMouseXChanged: positionChange(Qt.point(mouseX, customPoint.y), -1, 1)
}
}
//Center - 5
Item {
id: center
anchors.left: left.right
anchors.right: right.left
anchors.top: top.bottom
anchors.bottom: bottom.top
MouseArea {
anchors.fill: parent
property point clickPos
onPressed: clickPos = Qt.point(mouse.x,mouse.y)
onPositionChanged: {
if(pressed && mainWindow.visibility !== Window.Maximized && mainWindow.visibility !== Window.FullScreen) {
var delta = Qt.point(mouse.x-clickPos.x, mouse.y-clickPos.y)
mainWindow.x += delta.x
mainWindow.y += delta.y
}
}
}
}
//Right
Item {
id: right
width: enableSize
anchors.right: parent.right
anchors.top: rightTop.bottom
anchors.bottom: rightBottom.top
z: 1000
MouseArea {
anchors.fill: parent
hoverEnabled: true
onPressed: press(mouse)
cursorShape: containsMouse?Qt.SizeHorCursor:Qt.ArrowCursor;
onReleased: release()
onMouseXChanged: positionChange(Qt.point(mouseX, customPoint.y), 1, 1)
}
}
//左下角
Item {
id: leftBottom
width: enableSize
height: enableSize
anchors.left: parent.left
anchors.bottom: parent.bottom
z: 1000
MouseArea {
anchors.fill: parent
hoverEnabled: true
onPressed: press(mouse)
cursorShape: containsMouse?Qt.SizeBDiagCursor:Qt.ArrowCursor;
onReleased: release()
onPositionChanged: positionChange(mouse, -1, 1)
}
}
//bottom
Item {
id: bottom
height: enableSize
anchors.left: leftBottom.right
anchors.right: rightBottom.left
anchors.bottom: parent.bottom
z: 1000
MouseArea {
anchors.fill: parent
hoverEnabled: true
onPressed: press(mouse)
cursorShape: containsMouse?Qt.SizeVerCursor:Qt.ArrowCursor;
onReleased: release()
onMouseYChanged: positionChange(Qt.point(customPoint.x, mouseY), 1, 1)
}
}
//右下角
Item {
id:rightBottom
width: enableSize
height: enableSize
anchors.right: parent.right
anchors.bottom: parent.bottom
z: 1000
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: containsMouse?Qt.SizeFDiagCursor:Qt.ArrowCursor;
onPressed: press(mouse)
onReleased: release()
onPositionChanged: positionChange(mouse,1,1)
}
}
function press(mouse) {
isPressed = true
customPoint = Qt.point(mouse.x, mouse.y)
}
function release() {
isPressed = false
//customPoint = undefined
}
function positionChange(newPosition, directX/*x轴方向*/, directY/*y轴方向*/) {
if(!isPressed) return
var delta = Qt.point(newPosition.x-customPoint.x, newPosition.y-customPoint.y)
var tmpW,tmpH
if(directX >= 0)
tmpW = mainWindow.width + delta.x
else
tmpW = mainWindow.width - delta.x
if(directY >= 0)
tmpH = mainWindow.height + delta.y
else
tmpH = mainWindow.height - delta.y
if(tmpW < mainWindow.minimumWidth) {
if(directX < 0)
mainWindow.x += (mainWindow.width - mainWindow.minimumWidth)
mainWindow.width = mainWindow.minimumWidth
}
else {
mainWindow.width = tmpW
if(directX < 0)
mainWindow.x += delta.x
}
if(tmpH < mainWindow.minimumHeight) {
if(directY < 0)
mainWindow.y += (mainWindow.height - mainWindow.minimumHeight)
mainWindow.height = mainWindow.minimumHeight
}
else {
mainWindow.height = tmpH
if(directY < 0)
mainWindow.y += delta.y
}
}
}
main.qml里加ResizeItem后的代码
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
Window {
id:mainWindow;
width: 1500;
height: 846;
visible: true
flags: Qt.Window | Qt.FramelessWindowHint;
title: qsTr("RX-Box");
ResizeItem {
enableSize: 8
anchors.fill: parent
focus: true
Image {
id: bgImg;
z:1;
anchors.fill: parent;
source: "qrc:/res/bg.png";
}
TitleBar{
id:titleBar
z:mystackview.z+1;
anchors{left: parent.left;right: parent.right; top: parent.top;}
}
Component.onCompleted: {
mainWindow.show();
}
}
结束语
就这样吧~