创建 Qt 工程时,我们通常使用 Qt 提供的 Online installer 安装 Qt Creator 和 Qt 库来创建、编译、发布 Qt 项目,这对开发环境和 CI Agent 环境有较强的要求,一旦环境安装不对或者安装时缺少了一些组件,可能导致无法编译出产物。最近一段时间,Qt 也拥抱 Conan,使我们可以通过 Conan 管理 Qt 库,这样我们就可以真正实现一套 CMake 脚本来管理和发布 Qt 的应用了。以下我们将演示如何通过 CMake + Conan 来组织 Qt 工程和实现程序的发布流程。
自定义 npm 包读取外部 npm install 时传入的命令行参数
正常情况下我们安装一个 npm 包只需要执行 npm install 或者 yarn 就可以了,这基本上都是在发布环境。当我们自定义的 npm 包需要在测试阶段根据环境动态设置一些参数时就显得有些麻烦了。如果能在 npm install 时传递一些参数来提供内部 npm 包读取就会变的比较方便。本文介绍如何通过 npm install 增加的命令行参数和 .npmrc
来动态配置自定义 npm 包的行为。
node-pre-gyp 应用场景介绍及使用方法
Node.js 提供了使用 C++ addon 方案作为扩展的能力。我们可以编写 C++ 的代码来扩展 Node.js 或封装自己产品相关的能力接口为 Node.js 接口提供用户或者开发者使用。将编写好的源代码上传至 npm publish 平台,开发者通过 npm install 就可以使用你的扩展包了。但使用的前提是引入方必须要具备编译 C++ 代码的环境,比如在 Windows 下需要安装 MSVC 的编译工具链。而正常的前端开发者并不会将这些组件安装到系统里面,他们更关注的是前端业务逻辑。
基于 git flow + gitlab 协作开发:02 解决问题
上一篇文章中我们提到了在一个周维度或者月维度发布产品的小型协作项目中,会遇到各类协作上的问题,随着发布的越来越紧凑,问题也就越来越突出。本文主要对上一篇文章中提到的问题解决方案做细化,让大家可以清楚的知道如何通过合理的 git 工作流来解决这些问题,让原来发布时的手忙脚乱不再出现。通过 git flow 我们可以对项目做一个分支模型管理:
- master 固定,一致保持当前最新稳定的发布版本代码,在 CI/CD 建设时,你可以只在该分支做签名、公证等一系列自动化流程
- develop 固定,这是我们日常的开发分支,所有新功能分支都将合并到该分支
- release/* 可删,进入预发布阶段时基于 develop 创建的分支,再此基础集成,它名字可能是 release/2.8.0,release/2.9.0 等。
- bugfix/* 可删,这种分支一般情况下基于 develop 或者 release/* 分支开出,作为简单的缺陷修复分支,最终合并到 develop 或 release/* 分支中
- hotfix/* 可删,是对线上最新版本或长期服务版本做紧急修复时使用的分支,他不是常驻的
说多不多,说少也不少,还没有了解 git-flow 的同学可能会有点不太好理解,下面就详细介绍每个分支类型是如何在我们平时工作协作中起到重要作用的。
Qt 通过自定义 URL Scheme 给已经运行的应用传参(Windows&macOS)
在传统的应用程序设计中,我们可以看到很多通过浏览器唤起本地应用的案例,比如百度网盘、迅雷等工具,他们在浏览器访问一个非 http/https 协议开头的地址时,会自动打开其自己的应用程序并传递一定的参数。该功能的实现方式网络上有很多示例,在 Windows 和 macOS 不同平台下他们分别需要如下设置:
基于 git flow + gitlab 协作开发:01 抛出问题
很久以来,我一直在寻找一个适合小型团队独立项目的 git 协同工作流。主要原因是实际工作中很难在繁忙的迭代中兼顾真正的协同和代码质量管理。造成的现象就是在一个以月维度发布版本的产品中出现各种各样的分支、hotfix。到底哪个是主线,哪个分支修复了哪些问题、不同的分支是否与主线同步更新都是未知数。如果不叫一个从开始就参与到项目中的人给你做介绍,很难去做维护。
Qt Quick 5.15.0 Connections 新语法
过去的 Connection 连接某个对象的信号时是这样写的:
Connections {
target: authManager
onError: {
busyContainer.visible = false
buttonJoin.enabled = Qt.binding(function () {
return textMeetingId.length >= 11 && textNickname.length > 0
})
message.error(result.msg)
}
}
新的语法中可以这样写:
Connections {
target: authManager
function onError(resCode, result) {
busyContainer.visible = false
buttonJoin.enabled = Qt.binding(function () {
return textMeetingId.length >= 11 && textNickname.length > 0
})
message.error(result.msg)
}
}
对于日常开发中,新的写法有助于我们定义槽函数的形参个数和实际作用。代码看起来更容易读懂。另外 Qt 官方文档中也介绍了一些其他好处,见:Qt官方文档
如果你使用 Qt 15.5.0 版本打开了一个旧的工程并使用的是旧的写法,那么会收到一个警告:
qrc:/qml/AnonJoinPage.qml:54:5: QML Connections: Implicitly defined onFoo properties in Connections are deprecated. Use this syntax instead: function onFoo(<arguments>) { ... }
既然是个警告,则不影响代码继续执行。但这样的警告不得不让你重写这部分代码来适配新的语法。
使用 CMake + Git Submodule 方式管理项目三方库
在项目开发过程中,避免不了要使用一些开源的三方库,我参加过的一些团队有不同的管理三方库的方式。不同的方式都各有优缺点,我们先列举一下碰到过的管理方式,说一些他们的优缺点,最后再来讨论我们今天介绍的管理方式弥补了哪些缺点。
Qt Quick Windows 下实现无边框窗口阴影效果
Qt Quick 中实现一个无边框窗口阴影效果的中心思想是将 Window 容器背景设置为透明的,在 Windows 容器中添加一个填满窗口的容器(如 Page、Rectangle 等),然后将这个容器设置一些边距,再给这个容器附加一个阴影效果,实现的效果如下:
注意:本文所描述的方案会有严重的性能损耗,尤其是在 2k 4k 显示器上性能损耗严重、帧率极低,如非特殊需求,建议不使用类似方案。
Qt QML qtquickcontrols2.conf 使用系统未安装的自定义字体
现在很多视觉设计最终给出的字体可能并不是所有系统都安装过的,所以项目中可能需要单独把字体文件打包进去在程序运行的时候加载。Qt QML 有多种方式加载一个自定义字体,本文将介绍所有我知道的方式,大家根据自己的需要选择使用任意一种即可。
递归修改当前目录 .cpp、.h、.md 文件为 UTF8 或 UTF8-BOM 格式
有些代码目录下的文件格式不同,会导致一些编译错误或者中文出现错误等等问题,下面脚本就是解决这个问题而生的。使用 Autoit3 编译脚本后放到你要转换的目录中,运行脚本会转换所有 .cpp、.h、.md 文件为 UTF8 格式,如果你希望修改成 UTF8-BOM 格式,可以将 $FO_UTF8_NOBOM 修改为 $FO_UTF8
Qt Quick QML MouseArea 事件穿透
MouseArea
是 QML 中一个不可见的鼠标操作区域,可响应所有鼠标事件。一般情况下在自定义按钮、自定义需要鼠标交互的区域时使用。有时你只需要它的 hover 通知来做一些事情,而另外的点击等操作需要传递给其下层的控件,这时你就需要忽略其自身的鼠标按下释放等操作让其消息传递到下层了。
Qt Quick QML 中使用自定义字体文件
为了视觉上的统一,有时你需要保持 UI 上的字体与其他端字体一致,但是又不是所有字体所有系统都带有的,所以有时需要加载一个自定义字体来满足需求。本文重点介绍如何加载以及使用自定义字体。
下载并导入字体
下载好你需要的字体文件后通过 Qt Creator 将字体文件导入到资源列表(这样字体会加载到执行程序中,执行程序会比较大):
在导入完字体文件后,需要执行一下 qmake,在项目名称右键->执行qmake
加载字体
首先复制字体路径:
在 main.qml 中增加如下代码(这样全局都可以访问到)
FontLoader {
id: localFont;
source: "qrc:/fonts/PingFang.ttf"
}
字体的 ID 自己随便定义,路径就是上图中拷贝出来的路径,保存后字体就加载成功了。
使用字体
在需要使用字体的位置像如下代码一样,使用 localFont.name 属性来获取字体名称:
Text {
color: "#333333"
font.family: localFont.name
font.pixelSize: 14
textFormat: Text.PlainText
}
这样这个 Text 就使用了我们加载的 PingFang
字体了。