压测工具开发(一)——使用Qt Designer构建简单界面

在这里插入图片描述

你好,我是安然无虞。

文章目录

  • 项目功能概述
  • 构建菜单栏、工具栏
    • 1. 菜单栏注意事项
    • 2. 工具栏注意事项
    • 3. 日志停靠窗口

在这里插入图片描述

项目功能概述

开发一款 Qt版本的压测工具, 可以用来做 基于HTTP API接口的 性能测试.

要求做一个 MDI 多功能子窗口的 图形界面程序, 方便公司内部测试人员使用.

界面如下:

image

该项目主要涉及到的知识点有:

  • Qt图形界面开发的各个要点:
    • 菜单栏、工具栏、dock window、树控件、表格控件、字体图标的使用、MDI多子窗口、控件动态边界调整、上下文菜单、编辑框文本语法高亮、动态曲线图、matplotlib作图.
  • Socket编程
    • 使用 UDP Socket 来接收压测进程的统计数据, 并且可视化呈现.
  • 多进程外部程序调用
    • 启动独立的新压测进程, 而不是在图形界面进程中运行压测.

接下来我们一步一步开发这款软件.

构建菜单栏、工具栏

构建菜单栏和工具栏都很简单, 只需要使用Qt Designer拖拽对应的控件即可, 所以这里主要是记录遇到的坑以及Qt Designer相关bug.

1. 菜单栏注意事项

  1. 菜单栏消失不见了怎么办?

在这里插入图片描述

已经在 Qt Designer 中添加菜单栏了, 但是在预览的时候并没有, 有两点可能的原因是:

  1. 窗口类型问题
    • 只有基于 QMainWindow 的窗口才能在 Qt Designer 中正确显示 QMenuBar。如果使用的是其他窗口类型(如 QWidget),则无法直接显示菜单栏. 解决方法是将窗口类型改为 QMainWindow
  2. nativeMenuBar 属性问题
    • 在某些系统(如 macOS)上,QMenuBar 默认会隐藏在窗口标题栏中。可以通过设置 nativeMenuBar 属性为 false 来解决. 在 Qt Designer 中,找到 QMenuBar 的属性,将 nativeMenuBar 设置为 false

由于我选择的窗口类型就是QMainWindow并且使用的电脑系统是macOS所以很快确定是第2个问题导致的, 所以只需要进行如下改动即可:

取消勾选 nativeMenuBar即可解决问题.

  1. 为什么添加子菜单或动作Action, 命名时中文不可用

在这里插入图片描述

这是 Qt Designer 的一个bug, 解决方法也很简单, 我们只需要在其他的文本编辑器中输入想要设置的文本, 然后复制过来即可, 比如我在 Sublime Text中输入‘打开文本编辑框’:

在这里插入图片描述

注意哦, 还有一个坑就是不能直接使用快捷键ctr+v, 这样是没有效果的, 需要鼠标右键选择粘贴才能复制成功.

在这里插入图片描述

回车之后会自动在 动作编辑器 里创建一个action(默认在菜单栏的一级菜单中再次创建菜单时是action, 当然你也可以自己手动设置为子菜单形式):

在这里插入图片描述

如果我们想要改动这个action名称, 可以自行命名, 这里我们命名为action_openProjectFolder.

2. 工具栏注意事项

  1. 添加工具栏很简单, 只需要在窗口上右键点击选择 ‘添加工具栏’即可.

在这里插入图片描述

  1. 如果工具栏中想复用上面菜单栏中某一个action只需将动作编辑器中对应的action拖到工具栏中即可.

在这里插入图片描述

  1. 如果我们觉得使用文本样式不好看, 想设置为我们本地的图片样式, 可以双击 动作编辑器中对应的action进行更改, 比如这里的:

在这里插入图片描述

这样设置好了之后, 对应的action显示就变成这样子了:
在这里插入图片描述

这里我们使用 Qt Designer 的预览功能, 显示是正常的:

在这里插入图片描述

但是我们 运行 PySide6 程序时发现不对劲, 没有将图标显示出来:

在这里插入图片描述

所以这肯定是有问题的, 我们第一时间应该能猜到可能是图片的存放位置导致的, 看看这里的代码结构, 图片存放在images目录下的 folder.png:
在这里插入图片描述

为什么说是图片的存放位置导致的呢, 因为在 UI文件(也就是Qt Designer)中打开文件的逻辑和在程序中运行打开文件的地址是不一样的, UI文件中打开图片的当前目录是UI文件所在的目录, 所以我们以文本编辑器的方式打开UI文件, 可以看到:

图片的所在位置是相对于当前UI文件所在目录的上一级目录的images下, 而在程序中使用load()加载这个UI文件时使用的目录是程序文件所在的目录.

在这里插入图片描述

解决方法:

  • 如果是Windows系统电脑可以创建硬链接
  • 如果是Linux或是macOS系统可以创建符号链接

因为我使用的是macOS系统的电脑, 所以这里我讲的是创建符号链接的方式:

  1. 确定图片的实际路径

    首先,需要确定 images 目录的绝对路径, 假设程序目录的路径为 /Users/your_username/your_project,那么 images 目录的路径为 /Users/your_username/your_project/images

  2. 创建符号链接

    ui 目录下创建一个符号链接,指向 images 目录, 打开终端并执行以下命令:

    ln -s /Users/your_username/your_project/images /Users/your_username/your_project/ui/images
    

    这将在 ui 目录下创建一个名为 images 的符号链接,指向实际的 images 目录

  3. 更新UI文件中的图片路径

    在 UI 文件中,将图片路径更新为符号链接的路径. 例如,如果符号链接的路径为 images/folder.png,则在 UI 文件中设置图片路径为 images/folder.png

此时我们再看程序目录:

在这里插入图片描述

可能有老铁会说: 直接讲原来images目录复制一份到ui目录下不就行了, 能达到一样的效果.

简单解释一下吧:

  • 符号链接
    • 符号链接是一个特殊的文件系统对象,它指向另一个文件或目录
    • 它并不包含实际的数据,而是存储了目标文件或目录的路径
    • 在文件系统中,符号链接被视为一个“快捷方式”
  • 直接复制目录
    • 直接复制 images 目录是将目录及其内容完整地复制到目标位置
    • 复制后的目录是一个独立的副本,与原始目录没有直接关联

我在网上查看这部分资料时说以硬链接/符号链接的方式管理图片资源并不是最优解, 因为这种虽然可以解决图片路径问题, 但是可能会导致项目可移植性变差, 且在不同操作系统上需要额外配置.

所以更推荐的解决方案是使用 Qt 的资源文件(.qrc)来管理图片资源.

这个解决方案在后面的学习中会讲解到.

4.文件选择对话框标题不显示的问题

我们在代码中设置了 选择目录时选择框会显示标题:

filepath = QFileDialog.getExistingDirectory(self.ui, "请选择项目目录" )

但是在执行的时候没有显示提示标题:

在这里插入图片描述

查了之后发现是使用了macOS系统的原生对话框, 我们可以使用以下代码强制使用 PySide6 的文件对话框:

options = QFileDialog.Options() # 创建一个对话框选项的实例
options |= QFileDialog.DontUseNativeDialog  # 强制使用PySide6的文件对话框而不是macOS的原生对话框
filepath = QFileDialog.getExistingDirectory(self.ui, "请选择项目目录", options=options)

这样改动之后再次执行代码就正常显示了:

在这里插入图片描述

3. 日志停靠窗口

对于日志停靠窗口的要求如下:

  1. 程序各模块可以调用打印日志库函数, 日志窗口显示这些打印信息

  2. 日志窗口可以停靠在主窗口的下面、右侧,也可以单独分离出主窗口

  3. 设置日志窗口的最大显示行数为1000行

    # 设置日志窗口的最大显示行数为1000行
    self.ui.tb_logger.document().setMaximumBlockCount(1000)
    
  4. 超过日志窗口可见范围,要能始终显示最新打印的内容

我们可以使用 Dock Widget 来创建可以拖动并且停靠的控件:

在这里插入图片描述

我们可以直接在 Qt Designer中对其进行一些基本的设置:

  • 日志窗口可以停靠在主窗口的下面、右侧,也可以单独分离出主窗口

在这里插入图片描述

然后我们可以拖动一个 文本浏览框Text Browser(与多行纯文本框PlainTextEdit不同的是只读不可写, 当然我们也可以讲PlainTextEdit控件设置为只读):

在这里插入图片描述

因为在 Dock Widget 容器中只有一个Text Browser控件, 所以我们可以直接设置其布局, 这样的话这块看起来就美观一些:

设置布局之后看:
在这里插入图片描述

但是我们觉得边界不够美观, 有点大, 可以设置布局的上下左右margin:

在这里插入图片描述

将这里的上下左右margin由原先的12全部设置为0, 可以看到下面结果:

在这里插入图片描述

这样就好看多了.

遇见安然遇见你,不负代码不负卿。
谢谢老铁的时间,咱们下篇再见~

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

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

相关文章

Ubuntu 22 Linux上部署DeepSeek R1保姆式操作详解(ollama方式)

操作系统:Ubuntu Linux 22.04 一、安装模型运行环境 打开链接https://ollama.com/download/linux 1.安装ollama (1)一条指令即可实现的简易版安装方法(也可称为在线安装) curl -fsSL https://ollama.com/install.s…

MySQL 和 Redis 数据一致性解决方案

MySQL 和 Redis 数据一致性解决方案 MySQL 和 Redis 作为两种不同类型的数据库(关系型 vs 内存型),在配合使用时需要特别注意数据一致性问题。以下是几种常见的解决方案: 1. 缓存更新策略 1.1 Cache Aside Pattern (旁路缓存模式) 读操作&#xff1a…

Java高频面试之集合-20

hello啊,各位观众姥爷们!!!本baby今天来报道了!哈哈哈哈哈嗝🐶 面试官:讲讲 HashSet 的底层实现? HashSet 是 Java 集合框架中用于存储唯一元素的高效数据结构,其底层实…

【MySQL】从零开始:掌握MySQL数据库的核心概念(四)

人们之所以不愿改变,是因为害怕未知。但历史唯一不变的事实,就是一切都会改变。 前言 这是我自己学习mysql数据库的第四篇博客总结。后期我会继续把mysql数据库学习笔记开源至博客上。 上一期笔记是关于mysql数据库的表格约束,没看的同学可以…

Manus:通用智能体的架构革命与产业破局

🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》、《前端求职突破计划》 🍚 蓝桥云课签约作者、…

HTTP协议手写服务器

目录 一、请求的是Web根目录 二、GET方法通过URL传参 三、根据资源类型对应出Content-Type值 四、Http代码 项目完整源代码:Http 周不才/cpp_linux study - 码云 - 开源中国 一、请求的是Web根目录 如果URL中请求的资源是Web根目录,则自动跳转到主…

小蓝和钥匙

错位排序组合数 从28个人里面选14个人分到原来房间的钥匙 C 28 14 另外14个人错位排序 模板 请在此处填写你的解题思路 D14 都是模板记住就好了 无需理解 做题可以看出来是错位排序 或者组合数 然后会写代码就行了 import java.util.Scanner;/*** author zb* date2025/3…

使用飞书API自动化更新共享表格数据

飞书API开发之自动更新共享表格 天马行空需求需求拆解1、网站数据爬取2、飞书API调用2.1 开发流程2.2 创建应用2.3 配置应用2.4 发布应用2.5 修改表格权限2.6 获取tenant_access_token2.7 调用API插入数据 总结 天马行空 之前一直都是更新的爬虫逆向内容,工作中基本…

Python-Django入手

18.1 建立项目 18.1.1 制定规范 - 定义项目目标:明确应用的核心功能 - 创建项目文档:用README.md记录技术栈和开发流程 - 规划目录结构:建议遵循Django官方推荐的项目布局 18.1.2 建立虚拟环境 在命令行执行: python -m ven…

LangChain4j 入门(二)

LangChain 整合 SpringBoot 下述代码均使用 阿里云百炼平台 提供的模型。 创建项目&#xff0c;引入依赖 通过 IDEA 创建 SpringBoot 项目&#xff0c;并引入 Spring Web 依赖&#xff0c;SpringBoot 推荐使用 3.x 版本。 引入 LangChain4j 和 WebFlux 依赖 <!--阿里云 D…

3.30学习总结 Java包装类+高精度算法+查找算法

包装类&#xff1a; 基本数据类型对应的引用数据类型。 基本数据类型&#xff1a;在内存中记录的是真实的值。 八种包装类的父类都是Object类。 对象之间不能直接进行计算。 JDK5之后可以把int和integer看成一个东西&#xff0c;因为会进行内部优化。自动装箱和自动拆箱。 …

centos 7 LVM管理命令

物理卷&#xff08;PV&#xff09;管理命令 pvcreate&#xff1a;用于将物理磁盘分区或整个磁盘创建为物理卷。 示例&#xff1a;sudo pvcreate /dev/sdb1 解释&#xff1a;将 /dev/sdb1 分区创建为物理卷。 pvdisplay&#xff1a;显示物理卷的详细信息&#xff0c;如大小、所属…

借助FastAdmin和uniapp,高效搭建AI智能平台

在数字化办公时代&#xff0c;效率与协作是企业发展的核心竞争力。传统的办公工具虽然功能丰富&#xff0c;但在面对复杂多变的团队协作需求时&#xff0c;往往显得力不从心。为了解决这一痛点&#xff0c;我们推出了一款全新的办公AI平台&#xff0c;它不仅能够满足文字和语音…

项目上传github——SSH连接配置文档

1. 检查是否已有 SSH 密钥 打开终端&#xff0c;检查是否已经存在 SSH 密钥对&#xff1a; ls ~/.ssh如果你看到类似 id_rsa 和 id_rsa.pub 的文件&#xff0c;说明你已经有 SSH 密钥。否则&#xff0c;继续下一步。 2. 生成 SSH 密钥 如果你没有 SSH 密钥&#xff0c;使用…

传奇类网游页游2.5D游戏场景地图素材Eagle库 沙漠沙海隔壁

传奇类网游页游2.5D游戏场景地图素材Eagle库 沙漠沙海隔壁 链接: https://pan.baidu.com/s/1GY8N-KEkHBGEbS7uxrE4Dg 提取码: yrs8 备用下载地址&#xff1a;http://pan.1234f.com:5212/s/rLzIp 电子资料文档&#xff1a;https://www.1234f.com/sj/GitHub/sucai/20250327/1323…

通过TIM+DMA Burst 实现STM32输出变频且不同脉冲数量的PWM波形

Burst介绍&#xff1a; DMA控制器可以生成单次传输或增量突发传输&#xff0c;传输的节拍数为4、8或16。 为了确保数据一致性&#xff0c;构成突发传输的每组传输都是不可分割的&#xff1a;AHB传输被锁定&#xff0c;AHB总线矩阵的仲裁器在突发传输序列期间不会撤销DMA主设备…

鸿蒙学习手册(HarmonyOSNext_API16)_数据持久化③:关系型数据库

概述 关系型数据库&#xff1a;像“Excel表格联合作战”的管家 关系型数据库就像一个超级智能的表格管理系统&#xff0c;专门处理数据之间有复杂关联的情况。比如学生和成绩、订单和商品、用户和评论——这些数据像蜘蛛网一样相互连接&#xff0c;用键值数据库的“独立抽屉”…

Windows 11 VS Code C/C++ 开发环境搭建——一种尽量“绿色”的方法

我的电脑是Windows 11 系统&#xff0c;安装了Visual Studio Code&#xff0c;在上面搭建C/C开发环境&#xff0c;当然&#xff0c;这需要用到MinGW之流了。作为一个绿色爱好者&#xff08;帽子除外&#xff09;&#xff0c;我也尽量绿色地架设这样一个环境…… 第一步&#x…

mysql-分区和性能

mysql自身只支持表的横向分区。 常听到开发人员说“”对表做个分区“&#xff0c;然后数据的查询就会快了。这是真的吗&#xff1f;实际上可能跟根本感觉不到查询速度的提升&#xff0c;甚至会发现查询速度急剧下降。因此&#xff0c;在合理使用分区之前&#xff0c;必须了解分…

DeepSeek协助优化-GTX750Ti文物显卡0.65秒卷完400MB float 音频512阶时域FIR

文章目录 1. 学习目的2. 阶段成果2.1 NVVP 性能探查2.2 测试编译环境2.3 测试样例 3 学习过程3.1 提问DeepSeek3.2 最终代码 4. 体会 1. 学习目的 最近在学习cuda&#xff0c;准备给我的taskBus SDR添加CUDA的模块支持&#xff0c;以便可以用PC机压榨山寨 B210那56M的带宽。 因…