QT自定义控件工程结构框架


前言

网上关于QT自定义控件的介绍很多,本文不做具体自定义控件编写的详细介绍,本文的主要目的是介绍一个自己在用的一个工程框架cutewidgets。


一、cutewidgets是什么?

cutewidgets是一个编写Qt Designer自定义控件的框架工程,主要作用的方便自动化部署到本地QT环境,其中也包含测试例程的编写,方便测试。内含一个简单的自定义控件和测试例程。

友情提示:新手在看下面内容时,最好先下载源码,对照阅读,效果会更好。老手就不用了,看个思路就行,当然若是老手能使用这个框架,那也不胜荣幸。

源码放在GitHub上了,可自行下载。本来是想放在gitee上的,无奈因为一些认证原因,就没折腾。GitHub的无奈用过的人都知道。

二、工程结构

在这里插入图片描述

项目 说明
Git相关 .git,.gitattributes,.gitignore,README.md为git版本控制相关文件,不做解释
bin 测试例程运行目录
designer 自定义控件插件源码
examples 测试例程
include 拷贝源码相关头文件的目标路径,作为普通动态库提供的头文件
lib 动态库或静态库输出目录
plugin 自定义控件插件输出目录
src 自定义控件源码
配置文件 cutewidgets.pri,cutewidgets.pro,cutewidgetsbuild.pri,cutewidgetsconfig.pri,cutewidgetsfunctions.pri工程及编译相关配置文件

三、框架的工程配置

本部分内容着重介绍cutewidgets框架的工程配置,主要涉及pro,pri等文件的编写。

1 cutewidgets.pro

工程的总入口,内容如下:

TEMPLATE = subdirs
CONFIG   += ordered

include(cutewidgets.pri)

SUBDIRS += src

contains(CUTEWIDGETS_CONFIG, CuteWidgetsExamples) {
    SUBDIRS += examples
}

contains(CUTEWIDGETS_CONFIG, CuteWidgetsDesigner) {
    SUBDIRS += designer
}

模板为子项目subdirs,比较简单,src默认加载,examples和designer项目按工程配置选择性加载。

这里有个小问题,不知是不是Qt Creator的bug,在配置文件去除examples和designer的配置后,虽然这两个子项目不参与编译,但它们还在整个工程结构里,但可以看到加载的文件都变灰了。这就引入了一个问题。这些灰掉的文件在还在使用它们的子项目里变成了有错误的代码,而QT6版本的Creator有个尿性就是一旦你的文件有错误提示,它的查看或者补全等便捷的编码工具都失效了。这样写起代码来就太痛苦了。所以在编码阶段最好不要把examples和designer去掉。

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

2 cutewidgets.pri

整个工程的公共配置文件,内容如下:

################################################################################
# CONFIG配置文件
################################################################################

include($$PWD/cutewidgetsconfig.pri)

################################################################################
# 函数定义
################################################################################

include($$PWD/cutewidgetsfunctions.pri)

################################################################################
# 构建配置
################################################################################

include($$PWD/cutewidgetsbuild.pri)

它其实就是三个配置文件的包,方便引用,所有引用该文件的地方都会有这么一个包出现
在这里插入图片描述

2.1 cutewidgetsconfig.pri

顾名思义,这个文件为配置文件,内容如下:

################################################################################
# Source paths
################################################################################

CUTEWIDGETS_ROOT            = $$PWD
CUTEWIDGETS_OUTPUT_LIB      = $$CUTEWIDGETS_ROOT/lib
CUTEWIDGETS_OUTPUT_PLUGIN   = $$CUTEWIDGETS_ROOT/plugin

######################################################################
# Install paths
######################################################################

CUTEWIDGETS_INSTALL_PREFIX      = $$[QT_INSTALL_PREFIX]

CUTEWIDGETS_INSTALL_DIR_NAME    = QtCuteWidgets

CUTEWIDGETS_INSTALL_HEADERS     = $${CUTEWIDGETS_INSTALL_PREFIX}/include/$$CUTEWIDGETS_INSTALL_DIR_NAME

CUTEWIDGETS_INSTALL_LIB         = $${CUTEWIDGETS_INSTALL_PREFIX}/lib

######################################################################
# Designer plugin
# creator/designer load designer plugins from certain default
# directories ( f.e the path below QT_INSTALL_PREFIX ) and the
# directories listed in the QT_PLUGIN_PATH environment variable.
# When using the path below CUTEWIDGETS_INSTALL_PREFIX you need to
# add $${CUTEWIDGETS_INSTALL_PREFIX}/plugins to QT_PLUGIN_PATH in the
# runtime environment of designer/creator.
######################################################################

CUTEWIDGETS_INSTALL_PLUGINS_FOR_DESIGNER   = $${CUTEWIDGETS_INSTALL_PREFIX}/plugins/designer
CUTEWIDGETS_INSTALL_PLUGINS_FOR_CREATOR    = $${CUTEWIDGETS_INSTALL_PREFIX}/../../Tools/QtCreator/bin/plugins/designer

######################################################################
# Build the static/shared libraries.
# If CuteWidgetsDll is enabled, a shared library is built, otherwise
# it will be a static library.
######################################################################

CUTEWIDGETS_CONFIG           += CuteWidgetsDll

######################################################################
# If you want to build the CuteWidgets designer plugin,
# enable the line below.
# Otherwise you have to build it from the designer directory.
######################################################################

CUTEWIDGETS_CONFIG     += CuteWidgetsDesigner

######################################################################
# If you want to auto build the examples, enable the line below
# Otherwise you have to build them from the examples directory.
######################################################################

CUTEWIDGETS_CONFIG     += CuteWidgetsExamples

######################################################################
###                      custom widget below                       ###
######################################################################

######################################################################
# CuteWidgetsTestEdit enables all classes, that are needed to use the
# CuteWidgetsTestEdit classes.
######################################################################

CUTEWIDGETS_CONFIG     += CuteWidgetsTestEdit

前半部分是一些变量的定义,包括编译输出路径和部署的QT环境下的一些路径定义。

CUTEWIDGETS_INSTALL_DIR_NAME变量做下说明,QT下include文件夹下都会增加一层模块的文件夹,然后才是相关头文件定义,为了保持统一,我们也定义一个。

CUTEWIDGETS_INSTALL_DIR_NAME    = QtCuteWidgets

CUTEWIDGETS_INSTALL_HEADERS     = $${CUTEWIDGETS_INSTALL_PREFIX}/include/$$CUTEWIDGETS_INSTALL_DIR_NAME

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

再延伸下,pro文件定义的变量如何在cpp中使用,就拿我们的测试控件里的内容说明。
我们在designer.pro文件中定义了CUTEWIDGETS_STR变量,并且赋值为CUTEWIDGETS_INSTALL_DIR_NAME

    #########################################################################
    # 定义QT路径下include下文件名,所有install的头文件放于
    # QT_INSTALL_PRFIX/include/CUTEWIDGETS_STR中
    #########################################################################
    DEFINES += CUTEWIDGETS_STR=$$CUTEWIDGETS_INSTALL_DIR_NAME

下面我们看看如何在designer_plugin.h中把这个值转换成c++可识别的变量。
在这里插入图片描述
在这里插入图片描述
其实主要是这两行起到的作用

#define STR(R) #R
#define STRVALUE(R) STR(R)

第一行用 # 获取宏的名称,第二行获取宏的值。这样就获取了pro文件的变量,这样做的目的是为了统一,install的路径和自定义控件的头文件定义就一致了,其实QT的自定义控件模板工程的做法是直接把自定义控件的头文件放在QT的include文件下,我们是为了和人家文件结构保持一致,才加了这么个变量,没办法,谁叫咱有洁癖呢 (^ _ ^)。
在这里插入图片描述

后半部分为CUTEWIDGETS_CONFIG变量的配置,前面提到的配置examples和designer是否加载即在这里,这里简单说下qmake函数contains,熟悉qmake函数的请自行跳过。

contains(CUTEWIDGETS_CONFIG, CuteWidgetsDesigner) {
   
   
 ...
} else {
   
   
 ...
}

就是判断第一个变量里是否包含第二个变量,qmake的函数的左大括号必须和函数在一行,不能另一起一行

#错误用法
contains(CUTEWIDGETS_CONFIG, CuteWidgetsDesigner)
{
   
   
 ...
} else 
{
   
   
 ...
}

最后一段开始是你可以自由发挥的地方,注释说的也很清楚了,再添加其他自定义控件时,依次添加就好了。

######################################################################
###                      custom widget below                       ###
######################################################################

######################################################################
# CuteWidgetsTestEdit enables all classes, that are needed to use the
# CuteWidgetsTestEdit classes.
######################################################################

CUTEWIDGETS_CONFIG     += CuteWidgetsTestEdit

CUTEWIDGETS_CONFIG     += CuteWidgetsXXX1
CUTEWIDGETS_CONFIG     += CuteWidgetsXXX2

类似CuteWidgetsTestEdit这种配置会同时决定src,examples和designer三个子项目工程是否添加该自定义控件。这里编写时可以参考自带的测试控件例程。
在这里插入图片描述

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

在这里插入图片描述
DEFINE_CUTEWIDGETS_TESTEDIT不用想也肯定和cutewidgetsconfig.pri里的CuteWidgetsTestEdit有关,在CuteWidgetsTestEdit决定的testedit.pri文件里定义如下:
在这里插入图片描述
总之CuteWidgetsTestEdit的目的就是添加或抹除所有和该变量相关的工程文件,后续再添加的自定义控件的写法要参照这个测试控件。

2.2 cutewidgetsfunctions.pri

这个文件比较简单,就是参照QT的写法定义了两个函数

defineReplace(cuteWidgetsLibraryTarget) {

    unset(LIBRARY_NAME)
    LIBRARY_NAME = $$1

    contains(TEMPLATE, .*lib):CONFIG(debug, debug|release) {

        !debug_and_release|build_pass {

            win32:RET = $$member(LIBRARY_NAME, 0)d

        }
    }

    isEmpty(RET):RET = $$LIBRARY_NAME
    return($$RET)
}

defineTest(cuteWidgetsAddLibrary) {

    LIB_PATH = $$1
    LIB_NAME = $$2

    LIBS *= -L$${LIB_PATH}

    unset(LINKAGE)

    isEmpty(LINKAGE) {

        if(!debug_and_release|build_pass):CONFIG(debug, debug|release) {

            win32:LINKAGE = -l$${LIB_NAME}d

        }
    }

    isEmpty(LINKAGE) {

        LINKAGE = -l$${LIB_NAME}

    }

    !isEmpty(QMAKE_LSB) {

        QMAKE_LFLAGS *= --lsb-shared-libs=$${LIB_NAME}

    }

    LIBS += $$LINKAGE
    export(LIBS)
    export(QMAKE_LFLAGS)
    export(QMAKE_LIBDIR_FLAGS)

    return(true)
}

虽然只有两个函数还把defineTest和defineReplace都用上了,没见过的可以去百度一下,涨涨知识。

cuteWidgetsLibraryTarget这个函数的功能就是如果是debug模式那就在原来的名字上加一个d,这在QT的库里太常见了。

cuteWidgetsAddLibrary的功能就是添加依赖库,第一个变量是路径,第二个变量是库名称,其实就是实现了

LIBS += -Ldir -llib

我想看这个博客的人不会不知道LIBS的用法的。

2.3 cutewidgetsbuild.pri

这个文件顾名思义是配置编译的,内容如下:

######################################################################
# qmake internal options
######################################################################

CONFIG           += qt
CONFIG           += warn_on
CONFIG           += no_keywords
CONFIG           += silent
CONFIG           -= depend_includepath

CONFIG += c++17

######################################################################
# release/debug mode
######################################################################

win32 {
    # On Windows you can't mix release and debug libraries.
    # The designer is built in release mode. If you like to use it
    # you need a release version. For your own application development you
    # might need a debug version.
    # Enable debug_and_release + build_all if you want to build both.

    #CONFIG           += debug_and_release
    #CONFIG           += build_all
    CONFIG           += release
}

这里我没写太多内容,因为本人只在Windows系统上做开发,所以这个框架也没那么QT,可以多平台使用,主要是本人没有其他系统的使用需求,故而未作深入研究。

四、源码

下面进入源码的介绍环节。该部分还是主要介绍几个子项目的工程配置文件,捎带说说源码内容,因为自定义控件源码的编写网上的内容太多了,我就不做详细介绍了。

1 src

在这里插入图片描述

  • src.pro
  • cutewidgets_global.h
  • testedit

1.1 src.pro

也是一个子项目,内容如下:


include($$PWD/../cutewidgets.pri)

TEMPLATE          = lib
TARGET            = $$cuteWidgetsLibraryTarget(cutewidgets)
DESTDIR           = $$CUTEWIDGETS_OUTPUT_LIB

contains(CUTEWIDGETS_CONFIG, CuteWidgetsDll) {
    CONFIG += dll
    DEFINES += CUTEWIDGETS_DLL CUTEWIDGETS_LIBRARY

    DLLDESTDIR        = $$CUTEWIDGETS_ROOT/bin
}
else {
    CONFIG += staticlib
}

INCLUDEPATH     += $$CUTEWIDGETS_ROOT/src


unset(INSTALL_INCLUDE_FILES)
INSTALL_INCLUDE_FILES += $$CUTEWIDGETS_ROOT/src/cutewidgets_global.h

#包含指定源码
contains(CUTEWIDGETS_CONFIG, CuteWidgetsTestEdit) {

    include($$CUTEWIDGETS_ROOT/src/testedit/testedit.pri)
}

########################################################################
#                           在此新增自定义控件源码                         #
########################################################################

#new pri here


########################################################################
#头文件拷贝
########################################################################

target_headers.path  = $$CUTEWIDGETS_ROOT/include
target_headers.files = $$INSTALL_INCLUDE_FILES
INSTALLS        += target_headers

捡有用的说几个吧。

项目 说明
include($$PWD/…/cutewidgets.pri) 不必多说,定义这玩意就是让引用的。
DESTDIR = $$CUTEWIDGETS_OUTPUT_LIB 定义动态库或静态库输出位置
contains(CUTEWIDGETS_CONFIG, CuteWidgetsDll) 决定是编译动态库还是静态库,动态库的话,输出dll到bin
INCLUDEPATH += $$CUTEWIDGETS_ROOT/src 这个特殊说明下,这个路径下有cutewidgets_global.h文件,为了可以在所有文件中直接包含#include “cutewidgets_global.h”,这样做的用意是编译designer插件时会把所有相关头文件都拷贝到QT的include/QtCuteWidgets下,和代码的文件结构不同了,避免头文件引用错误
contains(CUTEWIDGETS_CONFIG, CuteWidgetsTestEdit) 前文提到了,根据配置选择是否加载该部分源码
INSTALLS += target_headers 头文件拷贝,具体配置请参考QT INSTALLS使用

1.2 cutewidgets_global.h

内容如下:

#ifndef CUTEWIDGETS_GLOBAL_H
#define CUTEWIDGETS_GLOBAL_H

#include <QtCore/qglobal.h>

#ifdef CUTEWIDGETS_DLL
#ifdef CUTEWIDGETS_LIBRARY
#  define CUTEWIDGETS_EXPORT Q_DECL_EXPORT
#else
#  define CUTEWIDGETS_EXPORT Q_DECL_IMPORT
#endif
#else
#define 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

家有一枚袁宝

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

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

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

打赏作者

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

抵扣说明:

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

余额充值