QML + KDDockWidget 实现 tabwidget效果( 窗口可独立浮动和缩放)

56 篇文章 45 订阅
4 篇文章 0 订阅

前言

前面文章介绍过在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


  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
QML 中,可以通过设置窗口的 `flags` 属性来启用窗口的拖拽效果。具体实现方法如下: 1. 在窗口的 `Component.onCompleted` 信号中设置窗口的 `flags` 属性: ``` Component.onCompleted: { flags: Qt.Window | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.X11BypassWindowManagerHint } ``` 2. 在窗口的 `MouseArea` 中添加鼠标事件处理程序: ``` MouseArea { anchors.fill: parent cursorShape: Qt.SizeAllCursor onPressed: { if (mouse.button === Qt.LeftButton) { mouse.accepted = true window.startDrag() } } onMouseXChanged: { if (mouse.button === Qt.LeftButton && mouse.accepted) { window.drag(x - mouse.startX, y - mouse.startY) } } onReleased: { if (mouse.button === Qt.LeftButton && mouse.accepted) { window.stopDrag() } } } ``` 其中,`startDrag()` 方法用于启动窗口的拖拽效果,`drag()` 方法用于实现窗口的拖拽,`stopDrag()` 方法用于停止窗口的拖拽。 3. 在窗口的 `onDragStarted`、`onDragUpdated` 和 `onDragFinished` 信号中实现窗口的拖拽效果: ``` onDragStarted: { startX = x startY = y } onDragUpdated: { window.x = startX + offsetX window.y = startY + offsetY } onDragFinished: { startX = 0 startY = 0 offsetX = 0 offsetY = 0 } ``` 其中,`startX` 和 `startY` 分别表示鼠标按下时窗口的位置,`offsetX` 和 `offsetY` 分别表示鼠标移动的偏移量。在 `onDragUpdated` 信号中,根据鼠标移动的偏移量更新窗口的位置,最后在 `onDragFinished` 信号中重置参数。 通过以上步骤,就可以实现窗口的拖拽效果了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luoyayun361

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值