关于KDDockWidget源码修改和自定义

news2024/11/24 9:14:32

前言

前面的文章介绍过KDDockWidget的基本使用及示例,文章在这里:
KDDockWidgets源码编译及安装
qml dockwidget窗口停靠
QML + KDDockWidget 实现 tabwidget效果( 窗口可独立浮动和缩放)

今天主要记录一些在KDDockWidget源码中的修改,修改源码的目的是为了根据自己的项目来实现相关风格,KDDockWidget是第三方开源代码, 不是Qt官方的,提供的可修改的接口不一定非常完善,而且部分功能还会有bug。总之,要想实现自有风格的样式,原有接口不满足的情况下,就得去改源码了。
本文主要是记录之前在使用KDDockWidget过程中的修改记录,不一定非常完善,但是大致思路是没问题的。

首先来看看KDDockWidget提供的原有风格样式,自带的示例:
在这里插入图片描述

源码修改

1.编译QtQuick模式

KDDockWidget源码是支持QWidget和QtQuick两种实现方式,由于QWidget体系Qt官方提供了QDockWidget可以使用,而QtQuick却没有,所以用KDDockWidget更多是看中它能支持QML下的dock实现,那么,我们在编译KDDockWidget时需要修改配置才能编译出QtQuick使用的动态库。

如果要使用Quick ,Qt需要5.15版本以上,而且编译时默认关闭了编译QtQuick,所以如果需要编译运行Quick示例的话,需要修改编译文件,在根目录下找到CMakeLists.txt文件并打开,然后找到

option(${PROJECT_NAME}_QTQUICK "Build for QtQuick instead of QtWidgets" OFF)

将OFF改成ON即可

option(${PROJECT_NAME}_QTQUICK "Build for QtQuick instead of QtWidgets" ON)

接下来重新编译就可以生成QtQuick使用的动态库,并且bin目录下会编译生成quick的示例exe
在这里插入图片描述

2.自定义标题栏和窗口

在源码目录下提供的示例中,有一个叫customtitlebar,就是介绍如何实现自定义工具栏样式,
customtitlebar 中部分代码

class CustomFrameworkWidgetFactory : public KDDockWidgets::DefaultWidgetFactory
{
public:

    ~CustomFrameworkWidgetFactory() override;

    QUrl titleBarFilename() const override
    {
        return QUrl("qrc:/MyTitleBar.qml");
    }
};

通过以上方式可以设置自定义的工具栏。KDDockWidgets::DefaultWidgetFactory类中提供了四个可以自定义的样式,包括标题栏、frame窗口、dockwidget、浮动窗口
在这里插入图片描述
所以我们可以根据以上示例,自定义其他几个窗口样式:
在这里插入图片描述
然后通过设置config应用

auto flags = KDDockWidgets::Config::self().flags();
auto &config = KDDockWidgets::Config::self();
config.setFlags(flags);
config.setFrameworkWidgetFactory(new CustomFrameworkWidgetFactory());

而这四个qml自定义可以参考源码目录下原有实现:
在这里插入图片描述
也就是说,这四个我们可以在自己项目单独实现然后来实现自定义,这样会比较灵活一些,当然也可以直接在源码中修改这几个文件来达到想要的效果。
文件说明:

  • DockWidget.qml 是对应每一个可移动的子窗口
  • Frame.qml 是对应dock窗口的上层外窗口
  • FloatingWindow.qml 是对应浮动窗口
  • TitleBar.qml 是对应标题栏

3.修改导航图标

当拖动一个dock窗口时,会在出现一个导航图标,指示需要将窗口拖动到哪个位置去,如下图:
在这里插入图片描述
图标目录在src/img/classic_indicators/下
在这里插入图片描述
可以直接替换成新的图标,重新编译源码即可。
若要修改导航图标显示逻辑,可以在src\private\quick\qml\ClassicIndicatorsOverlay.qml中修改

4.修改dock之间的分隔线样式

修改dock之间的分隔线,文件在 src\private\multisplitter\qml\Separator.qml, 比如修改分隔线颜色:

import QtQuick 2.6

Rectangle {
    id: root
    anchors.fill: parent
    color: "#171717"

    readonly property QtObject kddwSeparator: parent

    MouseArea {
        cursorShape: kddwSeparator ? (kddwSeparator.isVertical ? Qt.SizeVerCursor : Qt.SizeHorCursor)
                                   : Qt.SizeHorCursor
        anchors.fill: parent
        onPressed: {
            kddwSeparator.onMousePressed();
        }

        onReleased: {
            kddwSeparator.onMouseReleased();
        }

        onPositionChanged: (mouse) => {
            kddwSeparator.onMouseMoved(Qt.point(mouse.x, mouse.y));
        }

        onDoubleClicked: {
            kddwSeparator.onMouseDoubleClicked();
        }
    }
}

5.修改分隔符宽度和dock最小最大尺寸

文件位置:src\private\multisplitter\Item.cpp

int Layouting::Item::separatorThickness = 5;
// There are the defaults. They can be changed by the user via Config.h API.
QSize Layouting::Item::hardcodedMinimumSize = QSize(80, 90);
QSize Layouting::Item::hardcodedMaximumSize = QSize(16777215, 16777215);

以上是默认值,可以对应修改。dock最小和最大尺寸是对应窗口能拖动最小和最大的尺寸。

6.在标题栏上添加按钮

标题栏上默认有floating和close按钮,如果想再添加一个,关键步骤是要将按钮点击事件传出来让好在外层中响应,可以按照以下流程操作。
首先,如果我们有自定义标题栏,如上面第二点提到的,重新实现了标题栏,那就在自定义的标题栏qml中添加按钮,如果没有自定义,那就在源码中进行修改,找到 src\private\quick\qml\TitleBar.qml, 可以看到这里面有floating和close按钮的定义,直接在这里添加即可:

 TitleBarButton {
     id: floatButton
     visible: root.floatButtonVisible
     imageSource: "qrc:/img/dock-float.png"
     anchors {
         verticalCenter: parent ? parent.verticalCenter : undefined
         right: closeButton.left
         topMargin: 5
         bottomMargin: 5
         rightMargin: 2
     }
     onClicked: {
         root.floatButtonClicked();
     }
 }

 TitleBarButton {
     id: closeButton
     enabled: root.closeButtonEnabled
     imageSource: "qrc:/img/close.png"
     visible:true
     anchors {
         verticalCenter: parent ? parent.verticalCenter : undefined
         right: parent ? parent.right : undefined
         topMargin: 5
         bottomMargin: 5
         leftMargin: 5
         rightMargin: 2
     }
     onClicked: {
         root.closeButtonClicked();
     }
 }

加入要添加一个菜单按钮:

TitleBarButton {
     id: menuButton
     imageSource: "qrc:/img/dock-menu.png"
     anchors {
         verticalCenter: parent ? parent.verticalCenter : undefined
         right: floatButton.left
         topMargin: 5
         bottomMargin: 5
         rightMargin: 2
     }
     onClicked: {
         root.sigMenuButtonClicked();
     }
 }

这里点击按钮发送信号sigMenuButtonClicked(),我们需要在 TitleBarBase.qml 中定义该信号
在这里插入图片描述

然后在本文件内添加信号连接,并调用cpp中的接口

onSigMenuButtonClicked:{
    titleBarCpp.onMenuClicked();
}

接着在TitleBar_p.h中定义onMenuClicked()接口:
在这里插入图片描述
TitleBar.cpp中添加接口实现

void TitleBar::onMenuClicked()
{
    if(m_frame){
        if (DockWidgetBase *dw = m_frame->currentDockWidget()) {
            qDebug() << __FUNCTION__ << "dock dw->sigMenuClicked()";
            Q_EMIT dw->sigMenuClicked();
        }
    }
    else if(m_floatingWindow){
        if (Frame *f = m_floatingWindow->singleFrame()) {
            if (DockWidgetBase *dw = f->currentDockWidget()) {
                qDebug() << __FUNCTION__ << "floating dw->sigMenuClicked()";
                Q_EMIT dw->sigMenuClicked();
            }
            else{
                qWarning() << Q_FUNC_INFO << "Frame with no dock widgets";
            }
        }
        else{
            qWarning() << Q_FUNC_INFO << "m_floatingWindow singleFrame() is null";
        }
    }
}

这里 dw->sigMenuClicked() 继续向上层传递信号,所以需要在 DockWidgetBase.h中定义这个信号:

在这里插入图片描述

最后,在DockWidgetInstantiator_p.h中也定义信号,然后在DockWidgetInstantiator.cpp中将DockWidgetBase发出的信号关联起来:

在这里插入图片描述
在这里插入图片描述

connect(m_dockWidget, &DockWidgetQuick::sigMenuClicked, this,
            &DockWidgetInstantiator::sigMenuClicked);

ok,这样就可以在qml中使用DockWidget的时候直接关联菜单按钮点击事件了,示例如下:

KDDW.MainWindowLayout {
	id: dockWidgetArea
    anchors.fill: parent
    uniqueName: "MyMainLayout"
    KDDW.DockWidget {
        id: dock3
        uniqueName: "dock3" // Each dock widget needs a unique id
        Rectangle{
            color: "yellow"
        }
        onSigMenuClicked:{
            console.log("---------onSigMenuClicked-------------")
        }
    }
  Component.onCompleted: {
      console.log("--------MainWindowLayout onCompleted------")
        addDockWidget(dock3, KDDW.KDDockWidgets.Location_OnTop);
  } 
}

7.修改dock被均分宽度的问题

如果当前MainWindowLayout 中有两个dock窗口,浮动一个窗口后恢复添加到MainWindowLayout 中去,会发现原本两个dock宽度不同的窗口会被均分宽度,这个在实际项目中 每个窗口都有对应的显示宽度,如果直接被layout均分显示,可能会倒是界面显示异常,所以要修改不让在恢复时均分宽度的问题。
修改也很简单,找到src\private\multisplitter\Item_p.h 找到以下两个接口,修改其默认参数:

Item类中:

virtual void setSize_recursive(QSize newSize, ChildrenResizeStrategy strategy = ChildrenResizeStrategy::Percentage);

改为

virtual void setSize_recursive(QSize newSize, ChildrenResizeStrategy strategy = ChildrenResizeStrategy::Side2SeparatorMove);

ItemContainer类继承于Item,所以对应的虚函数也要修改

virtual void setSize_recursive(QSize newSize, ChildrenResizeStrategy strategy = ChildrenResizeStrategy::Percentage);

改为

virtual void setSize_recursive(QSize newSize, ChildrenResizeStrategy strategy = ChildrenResizeStrategy::Side2SeparatorMove);

还有:

void growItem(Item *, int amount, GrowthStrategy,
                  NeighbourSqueezeStrategy neighbourSqueezeStrategy,
                  bool accountForNewSeparator = false,
                  ChildrenResizeStrategy = ChildrenResizeStrategy::Percentage);
                  
void applyGeometries(const SizingInfo::List &sizes, ChildrenResizeStrategy = ChildrenResizeStrategy::Percentage);

这两个的默认参数都要修改

void growItem(Item *, int amount, GrowthStrategy,
                  NeighbourSqueezeStrategy neighbourSqueezeStrategy,
                  bool accountForNewSeparator = false,
                  ChildrenResizeStrategy = ChildrenResizeStrategy::Side2SeparatorMove);
                  
void applyGeometries(const SizingInfo::List &sizes, ChildrenResizeStrategy = ChildrenResizeStrategy::Side2SeparatorMove);

ok,接下来重新编辑动态库即可。

当前暂时涉及到以上部分的修改,后续若有新增会及时更新。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/168489.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

来自元宇宙的声音:Chord Hero

这一集&#xff0c;我们邀请了 Chord Hero 的联合创始人兼行政总裁 Anthony Chau 来谈谈促使他加入 The Sandbox 元宇宙的原因以及即将在即将到来的游戏赛季推出的第一个项目。 请告诉我们更多关于 Chord Hero 的信息吧。 Chord Hero 通过一系列实体和数字产品让学习音乐变得有…

视图(view)

1、视图&#xff1a;&#xff08;了解内容&#xff09; 就是站在不同的角度去看待同一份数据。 视图是MySQL服务器中的一个对象&#xff0c;用于存储查询语句&#xff0c;目的的提高查询语句的使用效率&#xff0c;避免在多处地方重复性开发相同的查询语句。 - 将查询语句交给一…

Transformer学习笔记1

模型分类&#xff1a;GPT类型&#xff1a; auto-regressive&#xff08;decoder模型&#xff0c;过去时刻的输出也是现在的输入&#xff0c;例如要得到y8还需要知道y1到y7&#xff0c;但不能使用y9&#xff0c;例如用于文本生成任务&#xff09;GPTGPT2CTRLTransformer XLBERT类…

Docker 容器监控

目录 cAdvisor 安装cAdvisor 使用Prometheus监控cAdvisor cAdvisor暴露的Prometheus指标 容器指标 1. 文档&#xff1a; 2. 指标 硬件指标 1. 文档&#xff1a; 2. 指标&#xff1a; Node Exporter 安装Node Exporter 1. 启动容器&#xff0c;默认端口为9100 2. …

2023免费电脑c盘磁盘数据恢复软件EasyRecovery

无论是台式机还是笔记本电脑&#xff0c;我们都习惯将其划分成多个大小不一的磁盘&#xff0c;有的是用于安装系统&#xff0c;有的则是用于存储文件。今天小编就和大家解答一下关于电脑磁盘的问题&#xff0c;电脑只剩c盘是硬盘坏了吗&#xff0c;电脑突然就剩c盘怎么恢复。想…

【BP靶场portswigger-客户端16】测试WebSockets安全漏洞-3个实验(全)

前言&#xff1a; 介绍&#xff1a; 博主&#xff1a;网络安全领域狂热爱好者&#xff08;承诺在CSDN永久无偿分享文章&#xff09;。 殊荣&#xff1a;CSDN网络安全领域优质创作者&#xff0c;2022年双十一业务安全保卫战-某厂第一名&#xff0c;某厂特邀数字业务安全研究员&…

CMMI落地4大工具 助力CMMI3-5级高效落地

CMMI落地4大工具近日正式上线&#xff0c;全面支持CMMI3-5级&#xff0c;助力CMMI高效落地。CoCode旗下的Co-ProjectV3.0智能项目管理平台全新发布&#xff1a;CMMI成熟度自测工具、量化管理工具&#xff08;组织级过程改进工具和量化项目管理工具&#xff09;、组织级过程资产…

分享视频剪辑必备的三个素材软件(配音/文案/图片)

hello&#xff0c;大家好&#xff0c;相信现在很多小伙伴都需要制作视频&#xff0c;无论是从事短视频行业&#xff0c;还是单纯想分享生活视频的都需要对视频进行简单的处理吧&#xff1f;有时候会需要介绍视频内容或是给视频增加点配音&#xff0c;来让视频不那么单调&#x…

C++11 解决内存泄露问题的智能指针:shared_ptr、unique_ptr、weak_ptr

我们经常听到内存泄漏&#xff0c;但是对这个抽象的概念一直没有什么理解&#xff0c;比如产生内存泄漏又将如何&#xff0c;我平时写程序从来不考虑这个等等。这篇的目的&#xff1a;第一&#xff0c;给大家实验实验内存泄露带来的问题&#xff0c;让大家直观感受内存泄露。第…

[数据结构基础]链式二叉树及其前序、中序和后序遍历

一. 链式二叉树的结构和实现 1.1 链式二叉树的结构 链式二叉树&#xff0c;即使用链来表示一颗二叉树。链式二叉树的存储又可分为二叉链和三叉链&#xff0c;其中二叉链存储节点数据、指向左子节点的指针和指向右子节点的指针&#xff0c;三叉链相对于二叉链多存储指向父亲节…

一种基于肌电信号运动起点、波峰、终点实时自动检测的方法

一种基于肌电信号运动起点、波峰、终点实时自动检测的方法 (⊙o⊙)…,这篇是我写收费文章的第一篇。咱也尝试下知识付费,哈哈。 先看下效果,在给定理想正弦波的情况下,可以准确识别到正弦波的起点、波峰和终点。机器实拍图如下。 因为我的实际环境没有专利里面那么复杂,所…

Android 蓝牙开发——基础开发(三)

蓝牙开发这部分主要以 APP 端调用功能接口为开始&#xff0c;到 Framework 端的调用流程&#xff0c;最后到调用状态机结束&#xff0c;不涉及蓝牙协议栈的开发分析。 一、BluetoothAdapter 1、APP获取适配器 蓝牙权限 <mainifest><uses-permission android:name&…

3.ESP32-S2/S3 USB 挂载SPI-SD,当作U盘使用,无线U盘

使用的 IDF_4.4 C语言开发 1.ESP32-S2/S3 USB烧录 输出日志 2.ESP32-S2/S3 USB 挂载内部Flash&#xff0c;当作U盘使用&#xff0c;无线U盘 3.ESP32-S2/S3 USB 挂载SPI-SD&#xff0c;当作U盘使用&#xff0c;无线U盘 目录1.打开 usb_msc_wireless_disk 工程 Confinguration2.…

数学建模-数学规划(Matlab)

目录 一、线性规划求解 二、非线性规划问题 三、整数规划&#xff08;包括0-1规划&#xff09; 四、最大最小化模型 五、多目标规划模型 注意&#xff1a;代码文件仅供参考&#xff0c;一定不要直接用于自己的数模论文中国赛对于论文的查重要求非常严格&#xff0c;代码雷同…

微服务Spring Boot 整合 Redis 实现 UV 数据统计

文章目录⛄引言一、HyperLoglog基础用法⛅HyperLoglog 基本语法、命令⚡HyperLoglog 命令完成功能实现二、UV统计 测试百万数据的统计☁️什么是UV统计⚡使用SpringBoot单元测试进行测试百万数据统计⛵小结⛄引言 本文参考黑马 点评项目 在各个项目中&#xff0c;我们都可能需…

DaVinci:限定器 - HSL

调色页面&#xff1a;限定器Color&#xff1a;Qualifier限定器 - HSL Qualifier - HSL根据色相、饱和度和亮度等来选择画面上的对应区域&#xff0c;从而将二级调色与修饰限制在一定的范围。选择范围Selection Range拾取器Picker在检视器画面上按住并拖动&#xff0c;可以选择相…

Linux FHS结构

FHS是Filesystem Hierarchy Standard&#xff08;文件系统层次化标准&#xff09;的缩写&#xff0c;多数Linux版本采用这种文件组织形式&#xff0c;类似于Windows操作系统中c盘的文件目录&#xff0c;FHS采用树形结构组织文件。FHS定义了系统中每个区域的用途、所需要的最小构…

格式化输出

1、golang不同输出语句的区别&#xff1a; 特点PrintPrintlnPrintf输出内容到控制台&#xff08;终端输出&#xff09;SprintSprintlnSprintf输出内容为字符串FprintFprintlnFprintf输出内容到文件特点 输出内容不会换行。 不能格式化字符串。 输出内容换行,。 不能格式化字符…

【C语言进阶】枚举与联合体

目录一&#xff1a;枚举1.1&#xff1a;枚举类型的定义&#xff1a;1.1&#xff1a;枚举的优点&#xff1a;1.2&#xff1a;枚举的使用&#xff1a;二&#xff1a;联合&#xff08;共用体&#xff09;2.1&#xff1a;联合类型的定义&#xff1a;2.2&#xff1a;联合类型的特点&…

cin、cin.getline(arr, size)、getline(cin, str)

一、cin使用空白&#xff08;空格、制表符、换行符&#xff09;来确定字符串的截止位置 注意下方这段代码 使用cin来接收姓名和甜点名&#xff0c;当我的名字长度大于一个单词长度时&#xff0c;cin直接按空格进行接收&#xff0c;将我输入的xiao接收到name中&#xff0c;wei接…