前言
前面文章介绍过在QML中使用ListView实现TabBar标签拖拽交换位置效果(文章在这里)
先在此基础上升级一下,结合KDDockWidget做一个可浮动的窗口效果。
关于KDDockWidget的介绍,以前的文章有写过,可参考:
qml dockwidget窗口停靠
KDDockWidgets源码编译及安装
KDDockWidget是第三方开源项目,可以用于实现QML中Dock窗口效果,Qt本身不支持QML的Dock效果,所以正好弥补这部分空缺。而KDDockWidget中其实是支持Tab合并效果,但是在实际使用过程中遇到很多问题,该功能并不是很完善,所以索性自己使用QML来实现tabbar效果,然后结合KDDockWidget,可将每个tab页面进行单独的浮动和缩放。
先看效果:
本文Demo下载
点击下载
KDDockWidget动态库编译环境 VS2019
Demo使用环境 Qt5.15.2+VS2019
正文
关于ListView实现一个tabbar移动效果,前面文章有介绍过,这里简单贴个代码:
ListView{
id:tabBar
anchors.left: parent.left
anchors.right: parent.right
anchors.rightMargin: 66
interactive: false
anchors.leftMargin: 20
z:15
height: 30
spacing: 1
orientation:ListView.Horizontal
currentIndex: -1;
move: Transition {
NumberAnimation { property: "x"; duration: 150 }
}
moveDisplaced: Transition {
NumberAnimation { property: "x"; duration: 150 }
}
model:ListModel{
id:tabModel
onCountChanged: {
if(count > 0)
tabBar.currentIndex = count-1
}
}
delegate: TabButton{
id:tabButton
height: 30
width: 120
contentItem: Text {
font.pixelSize: 14
font.family: "Source Han Sans SC"
text: dockname
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
color: tabBar.currentIndex === index ? "#3692F0" :"#525252"
elide: Text.ElideMiddle
}
background:Item{
Rectangle {
color: tabBar.currentIndex === index ? "#171717" : "transparent"
border.width: tabBar.currentIndex === index ? 1 : 0
border.color: "#404040"
height: parent.height+3
width: parent.width
x:-1;y:-2
Rectangle{
y:parent.height-1
width: parent.width
height: 3
color: "#171717"
visible: tabBar.currentIndex === index
z:20
}
}
}
MouseArea{
id:ma2
anchors.fill: parent
preventStealing: true
hoverEnabled: true
onPositionChanged: {
var other_index = tabBar.indexAt(ma2.mouseX + tabButton.x, ma2.mouseY + tabButton.y);
if (other_index !== -1 && pressed) {
if (index !== other_index) {
tabModel.move(index, other_index,1);
tabBar.positionViewAtIndex(other_index,ListView.Center)
}
}
}
onClicked: {
tabBar.currentIndex = index
}
}
}
}
接下来看每个单独的dock窗口
import QtQuick 2.0
import QtQuick.Controls 2.15
import com.kdab.dockwidgets 1.0 as KDDW
KDDW.MainWindowLayout{
id:panel
property string dockName: "dock#1"
uniqueName:"MainLayout1"
KDDW.DockWidget{
id:dock1
uniqueName:"dock#1"
property bool isFirstFloating: true
property bool floating: false
Rectangle{
color:"#171717"
Label{
text:"This is Dock #1"
anchors.centerIn: parent
font.pixelSize:40
color: "white"
}
}
onSigFloatClicked:{
dock1.floating = !dock1.floating
if(!dock1.isFloating){
removeTimer.name = panel.dockName
removeTimer.start()
}
else{
addData(panel.dockName)
}
}
//关闭按钮已在DockTitleBar中隐藏
// onSigCloseClicked:{
// removeData(panel.dockName)
// }
}
Component.onCompleted: {
addDockWidget(dock1,KDDW.KDDockWidgets.Location_OnLeft)
}
}
由于我们是自定义的tabbar效果,所以这里没有用KDDockWidget提供的addDockWidgetAsTab接口,而是直接使用addDockWidget,每个tab page是一个单独的MainWindowLayout,包含一个独立的DockWidget。浮动窗口功能是直接点击floating button来调用相应接口实现。
代码中用到的KDDockWidget是在源码基础上进行部分修改后重新编译成的动态库,可根据实际项目需求,对源码进行适当修改,若需要修改后的源码,可联系我提供。
本文只实现了窗口的浮动效果,没有添加窗口关闭,若有需要,可在自动以标题栏中将关闭按钮显示出来,并添加其逻辑即可。
不解之处,可私信。
本文Demo下载
点击下载
KDDockWidget动态库编译环境 VS2019