Qt 项目中同时使用 CMAKE_AUTOUIC 和 UiTools 的注意事项

news2024/12/27 4:36:09

在 Qt 项目开发中,.ui 文件是界面设计的重要组成部分。开发者可以通过两种主要方式使用 .ui 文件:

  1. 编译期处理:通过 Qt 的 uic 工具将 .ui 文件转化为 C++ 代码(ui_xxx.h),静态绑定到项目中。
  2. 运行时动态加载:通过 Qt 的 UiTools 模块(主要是 QUiLoader),在运行时加载 .ui 文件,动态生成界面。

然而,当项目同时启用了 CMAKE_AUTOUIC(自动处理 .ui 文件生成代码)和 UiTools 模块时,可能会引发资源重复处理、代码复杂性提升等问题。本文将深入探讨这种混合使用的情况,分析潜在问题,并提供最佳实践方案。


CMAKE_AUTOUIC 与 UiTools 的作用

1. CMAKE_AUTOUIC

CMAKE_AUTOUIC 是 CMake 提供的自动化功能,用于在构建时调用 Qt 的 uic 工具,将项目中的 .ui 文件转化为对应的 ui_xxx.h 文件。这些文件可以直接包含到代码中,从而简化界面绑定。例如:

#include "ui_mainwindow.h"

class MainWindow : public QMainWindow {
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = nullptr) {
        ui.setupUi(this); // 静态绑定界面
    }
private:
    Ui::MainWindow ui;
};

启用 CMAKE_AUTOUIC 的项目可以通过如下方式配置:

set(CMAKE_AUTOUIC ON)
find_package(Qt6 REQUIRED COMPONENTS Widgets)

2. UiTools

UiTools 模块允许在运行时动态加载 .ui 文件。开发者可以在不需要重新编译的情况下修改 .ui 文件,并通过 QUiLoader 类在程序运行时生成界面。这种方法适合动态界面场景,如插件化应用或需要灵活更新界面的场景。

示例代码:

#include <QUiLoader>
#include <QFile>
#include <QWidget>

QFile file(":/example.ui"); // 动态加载 .ui 文件
if (!file.open(QFile::ReadOnly)) {
    qWarning("Cannot open file: %s", qPrintable(file.errorString()));
    return nullptr;
}

QUiLoader loader;
QWidget *widget = loader.load(&file); // 生成界面
file.close();

if (widget) {
    widget->show();
}

UiTools 模块通常需要在 CMake 中单独引入:

find_package(Qt6 REQUIRED COMPONENTS Widgets UiTools)


同时使用的情况

在某些项目中,可能需要同时使用 CMAKE_AUTOUICUiTools

  • 静态处理的 .ui 文件用于固定界面(如主窗口)。
  • 动态加载的 .ui 文件用于插件界面或运行时变化的部分。

此时项目可能包含以下配置:

set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(Qt6 REQUIRED COMPONENTS Widgets UiTools)

潜在问题

1. 资源重复处理

如果同一个 .ui 文件既被静态编译(通过 uic 生成 ui_xxx.h),又通过 QUiLoader 动态加载,可能会导致:

  • 内存浪费:同一界面被重复加载到内存中。
  • 逻辑混乱:开发者可能意外调用了两个不同的界面实例。
2. 维护成本增加

动态加载 .ui 文件允许运行时更新界面,而静态生成的 ui_xxx.h 文件只能在编译时更新。如果 .ui 文件被修改而忘记重新编译,动态加载的界面会显示最新效果,但静态绑定的界面仍然显示旧效果。这种行为不一致会增加调试难度。

3. 信号与槽复杂化

静态生成的界面代码会为每个控件生成成员变量(如 ui->button),开发者可以直接操作。而动态加载时,需要通过 findChild() 手动查找控件,增加了代码复杂性。例如:

// 静态绑定
ui->button->setText("Click Me");

// 动态加载
QPushButton *button = widget->findChild<QPushButton*>("button");
if (button) {
    button->setText("Click Me");
}
4. 混用的维护成本

在大型项目中,如果部分界面静态处理,部分界面动态加载,可能让团队成员困惑,需要额外文档明确每个 .ui 文件的用途。


解决方案与最佳实践

1. 区分静态与动态 .ui 文件

明确哪些 .ui 文件需要静态处理,哪些需要动态加载。可以通过命名或路径加以区分,例如:

  • 静态文件:放在 static_ui/ 文件夹。
  • 动态文件:放在 dynamic_ui/ 文件夹。

在 CMake 中手动设置这些文件的属性:

# 跳过动态文件的 AUTOUIC

set_property(SOURCE dynamic_ui/example.ui PROPERTY SKIP_AUTOUIC ON)

2. 优先单一方式

如果项目中大多数 .ui 文件都使用动态加载,可以考虑关闭 CMAKE_AUTOUIC

set(CMAKE_AUTOUIC OFF)

反之,如果绝大部分界面是静态的,尽量减少动态加载的 .ui 文件。

3. 明确用途场景
  • 静态加载:适用于固定界面(如主窗口、工具栏)。
  • 动态加载:适用于插件化界面、需要灵活更新的界面。
4. 结合资源管理

将动态加载的 .ui 文件加入 Qt 资源系统(qrc 文件)中,确保它们在运行时可以正确加载:

<RCC>

        <qresource prefix="/">

                <file>dynamic_ui/example.ui</file>

        </qresource>

</RCC>

5. 文档化规范

在团队开发中,为 .ui 文件的使用方式制定明确的规范,并记录在项目文档中。例如:

  • 静态文件路径:static_ui/
  • 动态文件路径:dynamic_ui/
  • 动态加载代码示例。
  • CMake 配置示例。

示例 CMake 配置

以下是一个混合使用静态和动态 .ui 文件的 CMake 配置示例:

cmake_minimum_required(VERSION 3.16)

project(UiToolsExample LANGUAGES CXX)

find_package(Qt6 REQUIRED COMPONENTS Widgets UiTools)

# 自动处理静态 .ui 文件
set(CMAKE_AUTOUIC ON)

# 静态文件
set(STATIC_UI_FILES
    static_ui/mainwindow.ui
)

# 动态文件
set(DYNAMIC_UI_FILES
    dynamic_ui/plugin.ui
)

# 跳过动态文件的 AUTOUIC
foreach(file IN LISTS DYNAMIC_UI_FILES)
    set_property(SOURCE ${file} PROPERTY SKIP_AUTOUIC ON)
endforeach()

# 添加资源文件
set(RESOURCES
    resources.qrc
)

# 源代码
set(SOURCES
    main.cpp
)

add_executable(UiToolsExample ${SOURCES} ${RESOURCES} ${STATIC_UI_FILES})

target_link_libraries(UiToolsExample PRIVATE Qt6::Widgets Qt6::UiTools)

总结

在 Qt 项目中同时使用 CMAKE_AUTOUICUiTools 是可行的,但需要注意以下问题:

  1. 避免对同一 .ui 文件进行重复处理。
  2. 明确每个 .ui 文件的用途(静态或动态)。
  3. 通过命名规范和 CMake 配置区分静态与动态文件。
  4. 为团队成员提供清晰的使用规范和文档。

通过合理规划和配置,可以有效避免资源浪费和维护成本上升,提升项目的开发效率和稳定性。

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

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

相关文章

osg、osgearth源码编译(二)

如果比较懒&#xff0c;也可以不看这篇文章&#xff0c;网上应该有很多编译好的库。也可以找我要。 本人还是建议学会编译&#xff0c;因为其他人电脑上编译好的&#xff0c;可能在你的电脑环境上&#xff0c;出现这样那样奇怪的问题&#xff0c;所以&#xff0c;最好还是自己能…

【QGIS入门实战精品教程】4.11:文本型字段转浮点型

《QGIS入门实战精品教程(配套案例数据)》:本专栏以实战案例的形式,深入浅出地介绍了QGIS的基本使用方法,用一个个实例讲解了QGIS基本操作与常见的空间分析方法。订阅专栏,获取专栏内所有文章阅读权限,从私信查收配套实验数据等资料,持续同步更新! 文章目录 一、加载实…

【R库包安装】R库包安装总结:conda、CRAN等

【R库包安装】R studio 安装rgdal库/BPST库 R studio 安装rgdal库解决方法 R studio 安装BPST库&#xff08;github&#xff09;解决方法方法1&#xff1a;使用devtools安装方法2&#xff1a;下载安装包直接在Rstudio中安装 参考 基础 R 库包的安装可参见另一博客-【R库包安装】…

探索 IntelliJ IDEA 中 Spring Boot 运行配置

前言 IntelliJ IDEA 作为一款功能强大的集成开发环境&#xff08;IDE&#xff09;&#xff0c;为 Spring Boot 应用提供了丰富的运行配置选项&#xff0c;定义了如何在 IntelliJ IDEA 中运行 Spring Boot 应用程序&#xff0c;当从主类文件运行应用程序时&#xff0c;IDE 将创建…

Qt支持RKMPP硬解的视频监控系统/性能卓越界面精美/实时性好延迟低/录像存储和回放/云台控制

一、前言 之前做的监控系统&#xff0c;已经实现了在windows上硬解码比如dxva2和d3d11va&#xff0c;后续又增加了linux上的硬解vdpau的支持&#xff0c;这几种方式都是跨系统的硬解实现方案&#xff0c;也是就是如果都是windows系统&#xff0c;无论X86还是ARM都通用&#xf…

全面解读权限控制与RBAC模型在若依中的实现

目录 前言1 权限控制基础概念1.1 权限控制的核心要素1.2 常见权限控制模型 2 RBAC模型详解2.1 RBAC的基本原理2.2 RBAC的优点2.3 RBAC的扩展模型 3 若依框架中的权限管理3.1 菜单管理3.2 角色管理3.3 用户管理 4 若依权限管理的实现流程4.1 创建菜单4.2 创建角色并分配权限4.3 …

qt QGraphicsEllipseItem详解

1、概述 QGraphicsEllipseItem是Qt框架中QGraphicsItem的一个子类&#xff0c;它提供了一个可以添加到QGraphicsScene中的椭圆项。QGraphicsEllipseItem表示一个带有填充和轮廓的椭圆&#xff0c;也可以用于表示椭圆段&#xff08;通过startAngle()和spanAngle()方法&#xff…

SAP SD学习笔记15 - 返品处理流程2 - 参照请求传票(发票)来生成返品传票

上一章讲了返品处理&#xff08;退货处理&#xff09;的流程。 SAP SD学习笔记14 - 返品处理&#xff08;退货处理&#xff09;的流程以及系统实操&#xff0c;比如 返品传票&#xff1b;请求Block标记&#xff1b;收到退货之后的处理&#xff0c;请求传票的登录_sap 销售返品…

在 ASP.NET C# Web API 中实现 Serilog 以增强请求和响应的日志记录

介绍 日志记录是任何 Web 应用程序的关键方面。它有助于调试、性能监控和了解用户交互。在 ASP.NET C# 中&#xff0c;集成 Serilog 作为记录请求和响应&#xff08;包括传入和传出的数据&#xff09;的中间件可以显著提高 Web API 的可观察性和故障排除能力。 在过去的几周里&…

Y20030018基于Java+Springboot+mysql+jsp+layui的家政服务系统的设计与实现 源代码 文档

家政服务系统的设计与实现 1.摘要2.开发目的和意义3.系统功能设计4.系统界面截图5.源码获取 1.摘要 随着人们生活水平的提高&#xff0c;老龄化、少子化等多重因素影响&#xff0c;我国对家政服务人群的需求与日俱增。家政服务行业对我国的就业和社会效益贡献也与日俱增&#…

基于AutoEncode自编码器的端到端无线通信系统matlab误码率仿真

目录 1.算法仿真效果 2.算法涉及理论知识概要 3.MATLAB核心程序 4.完整算法代码文件获得 1.算法仿真效果 matlab2022a仿真结果如下&#xff08;完整代码运行后无水印&#xff09;&#xff1a; 仿真操作步骤可参考程序配套的操作视频。 2.算法涉及理论知识概要 自编码器是…

深度学习与持续学习:人工智能的未来与研究方向

文章目录 1. 持续学习与深度学习1.1 深度学习的局限1.2 持续学习的定义 2. 目标与心智2.1 奖励假说2.2 心智的构成 3. 对研究方法的建议3.1 日常写作记录3.2 中立对待流行趋势 1. 持续学习与深度学习 1.1 深度学习的局限 深度学习注重“瞬时学习”&#xff0c;如ChatGPT虽在语…

使用C#开发VTK笔记(三)-使用VTK创建可视化界面和简单点线面体模型

一.使用VTK创建可视化界面 1.创建C#可视化界面 使用Visual Studio 2022用.net 8.0创建窗体应用 放入两个水平分割的Panel左侧演示VTK 右侧放按钮 按照第一章节环境搭建的步骤,加入对应Kitware的dll并导入依赖 2.初始化Vtk窗口 引用Kitware.VTK,Form1_Load中,创建渲染窗口控…

ctrl键和大写键互换解决方法

电脑卡住之后突然发现Ctrl键和大小写键&#xff08;CapsLock&#xff09;互换了&#xff0c;后面试了几种方法都没解决这个问题&#xff0c;最后在万能的贴吧中找到解决方法——键位复位。 108和87键位复位操作&#xff1a; 1.先按住FN不放&#xff0c; 然后&#xff0c;再按住…

PVE相关名词通俗表述方式———多处细节实验(方便理解)

PVE设置初期&#xff0c;对CIDR、 网关、 LinuxBridge、VLAN等很有困惑的朋友一定很需要一篇能够全面通俗易懂的方式去理解PVE 中Linux网桥的工作方式&#xff0c;就像操作一个英雄&#xff0c;多个技能&#xff0c;还是需要一点点去学习理解的&#xff0c;如果你上来就对着别人…

UG NX二次开发(C++)-Ufun函数-UF_MODL_ask_face_props说明

文章目录 1、前言2、UF_MODL_ask_face_props的函数说明3、UF_MODL_ask_face_props的应用3.1 获取归一化曲面上的点3.2 获取非归一化曲面上的点1、前言 UF_MODL_ask_face_props是获取曲面上的微分几何的函数,其能根据曲面上的参数,获取点、矢量等,也是经常用到的一个函数,但…

软件测试技术面试题及参考答案整理

一、什么是兼容性测试?兼容性测试侧重哪些方面? 参考答案&#xff1a; 兼容测试主要是检查软件在不同的硬件平台、软件平台上是否可以正常的运行&#xff0c;即是通常说的软件的可移植性。 兼容的类型&#xff0c;如果细分的话&#xff0c;有平台的兼容&#xff0c;网络兼…

【面试题】2025年百度校招Java后端面试题

文章目录 前言一、网络IO1、服务器处理并发请求有哪几种方式&#xff1f;2、说一下select&#xff0c;poll&#xff0c;epoll的区别&#xff1f;3、Java 有一种现代的处理方式&#xff0c;属于异步I/O&#xff0c;是什么&#xff1f;redis&#xff0c;nginx&#xff0c;netty 是…

HDU Go Running(最小点覆盖 + 网络流优化)

题目大意&#xff1a;有一条无限长跑道&#xff0c;每个人可以规定自己跑步的方向&#xff0c;起点&#xff0c;跑步起止时间。每个人跑步的速度都是1m/s。最后从监控人员哪里得到了n个报告&#xff0c;每个报告给出了某人在某一时候所在的位置&#xff0c;问跑步的最少可能人数…

.NET9 - Swagger平替Scalar详解(四)

书接上回&#xff0c;上一章介绍了Swagger代替品Scalar&#xff0c;在使用中遇到不少问题&#xff0c;今天单独分享一下之前Swagger中常用的功能如何在Scalar中使用。 下面我们将围绕文档版本说明、接口分类、接口描述、参数描述、枚举类型、文件上传、JWT认证等方面详细讲解。…