前言

前面一篇文章介绍了KDDockWidgets的使用(​​文章在这里​​​),其实主要目的就是为了用KDDockWidgets提供的Qt quick 下的窗口停靠功能。Qt原生部并没有提供Qt quick的dockwidget,也不知道为啥。其实窗口停靠功能其实是非常常见的,但是Qt只支持QWidget的。
KDDockWidgets刚好可以解决这个问题,详细介绍在之前的文章已经介绍过了,其功能比QDockWidget更加丰富。

那么,今天就来看一下如何用KDDockWidgets做自己的在qml 下的窗口停靠功能

修改文件

KDDockWidgets的源码编译和demo演示具体可以参照​​上一篇文章​​​,编译后默认安装位置是在C盘下:​​C:\KDAB\KDDockWidgets-1.4.0​​​ ,在源码中定义了一个宏​​KDDOCKWIDGETS_QTQUICK​​​,要使用Qt quick,我们需要修改一下头文件:
打开​​​C:\KDAB\KDDockWidgets-1.4.0_debug\include\kddockwidgets\Config.h​​,找到:

#ifdef KDDOCKWIDGETS_QTQUICK
///@brief Sets the QQmlEngine to use. Applicable only when using QtQuick.
void setQmlEngine(QQmlEngine *);
QQmlEngine* qmlEngine() const;
#endif

将这个宏判断注释掉。

//#ifdef KDDOCKWIDGETS_QTQUICK
///@brief Sets the QQmlEngine to use. Applicable only when using QtQuick.
void setQmlEngine(QQmlEngine *);
QQmlEngine* qmlEngine() const;
//#endif

然后再打开 ​​C:\KDAB\KDDockWidgets-1.4.0_debug\include\kddockwidgets\QWidgetAdapter.h​​ 找到

#if !defined(KDDOCKWIDGETS_QTWIDGETS) && !defined(KDDOCKWIDGETS_QTQUICK)
# define KDDOCKWIDGETS_QTWIDGETS
#endif

修改为:

#if !defined(KDDOCKWIDGETS_QTWIDGETS) && !defined(KDDOCKWIDGETS_QTQUICK)
# define KDDOCKWIDGETS_QTQUICK
#endif

创建工程

ok,接下来就可以创建我们自己的工程了,新建一个QML工程,写个简单的qml程序

在pro工程文件中, CONFIG添加KDDockWidgets

CONFIG += c++11

添加库引用:

win32:CONFIG(release, debug|release): LIBS += -LC:/KDAB/KDDockWidgets-1.4.0/lib/ -lkddockwidgets1
else:win32:CONFIG(debug, debug|release): LIBS += -LC:/KDAB/KDDockWidgets-1.4.0/lib/ -lkddockwidgets1d

INCLUDEPATH += C:/KDAB/KDDockWidgets-1.4.0/include
DEPENDPATH += C:/KDAB/KDDockWidgets-1.4.0/include

写个简单的qml文件:

import QtQuick 2.15
import QtQuick.Window 2.15
import com.kdab.dockwidgets 1.0 as KDDW

Window {
width: 1000
height: 800
visible: true
title: qsTr("Hello World")


Rectangle{
id:rect
width: parent.width
height: 200
color: "cyan"
}


KDDW.MainWindowLayout {
width: parent.width
height:parent.height - rect.height
anchors.top:rect.bottom

// Each main layout needs a unique id
uniqueName: "MainLayout-1"


KDDW.DockWidget {
id: dock1
uniqueName: "dock1" // Each dock widget needs a unique id
Rectangle {
color: "pink"
}
}

KDDW.DockWidget {
id: dock2
uniqueName: "dock2"
Rectangle {
color: "yellow"
}
}
KDDW.DockWidget {
id: dock3
uniqueName: "dock3"
Rectangle {
color: "red"
}
}

Component.onCompleted: {
// Add dock4 to the Bottom location
addDockWidget(dock1, KDDW.KDDockWidgets.Location_OnBottom);
// Add dock5 to the left of dock4
addDockWidget(dock2, KDDW.KDDockWidgets.Location_OnRight, dock1);
addDockWidget(dock3, KDDW.KDDockWidgets.Location_OnTop);
}
}
}

main文件

#include <QGuiApplication>
#include <QQmlApplicationEngine>

#include <kddockwidgets/Config.h>

int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif

QGuiApplication app(argc, argv);
auto flags = KDDockWidgets::Config::self().flags();
KDDockWidgets::Config::self().setFlags(flags);

QQmlApplicationEngine engine;

KDDockWidgets::Config::self().setQmlEngine(&engine);

const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);

return app.exec();
}

然后将kddockwidgets1d.dll 库文件拷贝到程序输出目录后运行代码,效果如下:

qml dockwidget窗口停靠_qt quick窗口停靠

注意,qml代码中只有包含在​​KDDW.MainWindowLayout​​​区域下的​​KDDW.DockWidget​​ 才可以实现dock效果,为了测试,我故意在顶部放了一个Rectangle,其实MainWindowLayout是一个QQuickItem,可以简单理解成一个qml中的Item,所以用法其实是一样的。在此基础上进行拓展就行了。

外部库

以上示例是在编译完源码并安装后直接引用,所以在工程文件中,CONFIG添加KDDockWidget就可以使用了,那如果没有安装KDDockWidget怎么用呢,这就需要直接添加外部库的方式来实现。为方便移植,我们直接在源码下新建一个文件夹,然后将相关的lib include 等都拷贝进去,然后创建一个pri文件:

qml dockwidget窗口停靠_qml窗口停靠_02

!contains(INCLUDEDFIES, KDDockWidgets.pri) {
INCLUDEDFIES += KDDockWidgets.pri

win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lkddockwidgets1
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lkddockwidgets1d

INCLUDEPATH += $$PWD/include
DEPENDPATH += $$PWD/include

}

然后在主工程文件pro中添加:

include(KDDockWidgets/KDDockWidgets.pri)

ok,直接编译运行就可以了。

自定义

以上窗口的效果是KDDockWidget默认的,如果想自定义窗口样式,比如修改边距、标题栏等,就需要修改源码了,在前面的文章中讲到的源码,找到:​​KDDockWidgets\src\private\quick\qml​​ :

qml dockwidget窗口停靠_#endif_03


可以修改这里对应的qml文件,然后重新编译源码后生成动态库,就可以直接在自己的项目中使用了。