Qt学习笔记-1
1. 第一个Qt程序
1.1 Hello Qt
1 | #include <QApplication> // 头文件引用, 每个Qt类都有对应的头文件,类的定义 |
测试程序
在源码根目录打开命令提示符执行qmake -project生成hello.pro项目文件,然后执行qmake hello.pro从这个项目文件生成makefile文件,在输入make命令就可以构建该应用。
Docker容器互访三种方式
方式一、虚拟ip访问
安装docker时,docker会默认创建一个内部的桥接网络docker0,每创建一个容器分配一个虚拟网卡,容器之间可以根据ip互相访问。
1 | # ifconfig |
运行一个centos镜像, 查看ip地址得到:172.17.0.7
1 | # docker run -it --name centos-1 docker.io/centos:latest |
以同样的命令再起一个容器,查看ip地址得到:172.17.0.8
1 | # docker run -it --name centos-2 docker.io/centos:latest |
容器内部ping测试结果如下:
1 | # ping 172.17.0.7 |
这种方式必须知道每个容器的ip,在实际使用中并不实用。
方式二、link
运行容器的时候加上参数link
运行第一个容器
1 | docker run -it --name centos-1 docker.io/centos:latest |
运行第二个容器
1 | docker run -it --name centos-2 \ |
--link:参数中第一个centos-1是 容器名 ,第二个centos-1是定义的 容器别名 (使用别名访问容器),为了方便使用,一般别名默认容器名。
测试结果如下:
1 | # ping centos-1 |
此方法对容器创建的顺序有要求,如果集群内部多个容器要互访,使用就不太方便。
方式三、创建bridge网络
- 安装好docker后,运行如下命令创建bridge网络:
1 | docker network create testnet |
查询到新创建的bridge testnet。

- 运行容器连接到testnet网络。
使用方法:1
2
3docker run -it --name <容器名> \
--network <bridge> \
--network-alias <网络别名> <镜像名>
1 | docker run -it --name centos-1 --network testnet \ |
- 从一个容器ping另外一个容器,测试结果如下:
1 | # ping centos-1 |
- 若访问容器中服务,可以使用这用方式访问 <网络别名>:<服务端口号>
推荐使用这种方法,自定义网络,因为使用的是网络别名,可以不用顾虑ip是否变动,只要连接到docker内部bright网络即可互访。bridge也可以建立多个,隔离在不同的网段。
Docker部署单节点ETCD
准备
镜像选择
quay.io/coreos/etcd:3.2.7
bitname/etcd
创建ETCD数据目录
1 | # data 存储容器持久化数据 |
创建ETCD配置文件
配置文件路径为 /usr/local/docker/etcd/config/etcd.config.yml
1 | name: etcd # etcd member 名称,可根据实际情况修改 |
创建并启动ETCD服务
1 | docker run -d --name etcd -p 2379:2379 -p 2380:2380 -v /usr/local/docker/etcd/data:/var/etcd -v /usr/local/docker/etcd/config:/var/lib/etcd/config quay.io/coreos/etcd: 3.5.12 |
使用docker-compose部署
创建Docker-compose
1 | version: '3' |
基于环境变量配置, 配置参考配置文件方式
1 | version: '3' |
创建并启动etcd
1 | cd {docker-compose文件所在目录} |
测试命令
1 | etcdctl --endpoints=192.168.1.2:2379 --write-out=table endpoint health |
基于OpenCV的视频流处理
获取VideoCapture实例
1 | # 读取视频流 |
获取摄像头编号可使用ls -al /dev/ |grep video,输出信息以video开头其后缀为数字即为可能的摄像头编号。
检查获取VideoCapture实例是否成功
1 | # 校验获取VideoCapture类实例 |
获取视频流信息
1 | # 获取视频帧的宽 |
获取帧画面
1 | success, frame = capture.read() |
当需要同时处理多路摄像头时一般使用grab()和retrieve()代替
1 | success_1 = capture.grab() |
设置分辨率
1 | # 设置摄像头分辨率的宽 |
保存视频文件
无论是视频文件存储还是摄像头画面保存都是用VideoWriter类,初始化时需要传入文件名(包含文件格式)、视频编解码器、视频保存帧率 、分辨率,保存视频的帧率最好和读入的帧率一致,分辨率可以更改,只是要求写入的帧大小要与分辨率保持一致。
若指定的文件名已存在则会覆盖文件。
1 | writer = cv2.VideoWriter('output.mp4', |
释放资源
不管是VideoCapture还是VideoWriter类,使用完都应该释放资源
1 | # 释放VideoCapture资源 |
完整示例
1 | # -*- coding: utf-8 -*- |
Docke种使用GPU运行Ollama
环境安装
此处使用设备 Tesla P40 + Debian 12为例
显卡驱动:下载 NVIDIA 官方驱动 | NVIDIA
CUDA Toolkit: CUDA Toolkit Archive | NVIDIA Developer
![[Docke种使用GPU运行Ollama/IMG-20260105103041635.png]]
注意CUDA版本对应,否则可能会导致CUDA在容器内无法运行
1 | curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \ |
禁用 nouveau
参考[[../Linux/Ubuntu禁用Nouveau驱动|Ubuntu禁用Nouveau驱动]]验证环境是否安装成功
1
docker run --rm --gpus all nvidia/cuda:12.2.0-runtime-ubuntu22.04 nvidia-smi
![[Docke种使用GPU运行Ollama/IMG-20260105103041714.png]]
直接运行Docker容器
1. 运行Ollama容器
1 | docker run --gpus=all -d -e OLLAMA_MODEL:qwen2.5-coder:7b -e OLLAMA_ENV:production -v=qwen-coder:/root/.ollama -p 11437:11434 --name qwen-coder -d ollama/ollama:latest |
- 如果不需要带显卡, 去除
--gpus=all即可 - 环境变量参考Ollama环境变量与常用CLI命令
2. 拉取模型并运行
1 | ollama run qwen2.5-coder:7b |
使用Docker Compose
1. 创建docker-compose.yml
1 | services: |
2. 启动服务
在docker-compose.yml所在目录运行以下命令:
1 | docker-compose up -d |
验证是否使用GPU启动Ollama
1 | docker exec -it <ollama容器ID> bash # 进入已启动的容器 |
如果PROCESSOR中显示为GPU则启动成功
![[Docke种使用GPU运行Ollama/IMG-20260105103041772.png]]
Ollama运行deepseek-r1示例
1 | # CPU运行 |
注意事项
- 使用_nvidia-smi_确认GPU是否被正确利用。
- 如果仅需CPU支持,可移除_–gpus=all_或相关配置。
- GPU模式下性能显著提升,但需确保驱动和CUDA版本兼容。
Ubuntu禁用Nouveau驱动
1. 创建黑名单配置文件
1 | sudo nano /etc/modprobe.d/blacklist-nouveau.conf |
- 添加以下内容以禁用Nouveau:
1 | blacklist nouveau |
2. 更新initramfs
- 更新内核的initramfs文件以应用更改:
1
sudo update-initramfs -u
3. 重启系统
- 执行以下命令重启系统:
1 | sudo reboot |
4. 验证禁用状态
重启后,检查Nouveau模块是否已禁用:
1
lsmod | grep nouveau
如果没有输出,说明Nouveau已成功禁用。
注意事项
禁用Nouveau后,可以安装NVIDIA专有驱动以获得更好的性能。
如果需要恢复Nouveau驱动,只需删除_/etc/modprobe.d/blacklist-nouveau.conf_文件并重新更新initramfs。
WPF中Binding使用StringFormat格式化字符串
货币格式
1 | <!-- 默认保留两位小数 输出: $12.34 --> |
固定文字
1 | <!-- 固定前缀 输出: 单价:$12.34 --> |
数字格式化
1 | <!-- 固定位数,仅支持整形 输出: 086723 --> |
占位符
1 | <!-- 输出: 0123.46 --> |
时间日期
1 | <!-- 输出: 5/4/2015 --> |
多重绑定
1 | <!-- |
Git代码提交规范
消息格式
每个提交消息都由一个标题、一个正文和一个页脚组成。而标题又具有特殊格式,包括修改类型、影响范围和内容主题:
1 | 修改类型(影响范围): 标题 |
标题是强制性的,但标题的范围是可选的。
修改类型
每个类型值都表示了不同的含义,类型值必须是以下的其中一个:
- feat:提交新功能
- fix:修复了bug
- docs:只修改了文档
- style:调整代码格式,未修改代码逻辑(比如修改空格、格式化、缺少分号等)
- refactor:代码重构,既没修复bug也没有添加新功能
- perf:性能优化,提高性能的代码更改
- test:添加或修改代码测试
- chore:对构建流程或辅助工具和依赖库(如文档生成等)的更改
代码回滚
代码回滚比较特殊,如果本次提交是为了恢复到之前的某个提交,那提交消息应该以revert:开头,后跟要恢复到的那个提交的标题。然后在消息正文中,应该写上This reverts commit <hash>,其中<hash>是要还原的那个提交的SHA值。
影响范围
范围不是固定值,它可以是你提交代码实际影响到的任何内容。例如$location、$browser、$compile、$rootScope、ngHref、ngClick、ngView等,唯一需要注意的是它必须足够简短。
当修改影响多个范围时,也可以使用*。
标题
标题是对变更的简明描述:
- 使用祈使句,现在时态:是“change”不是“changed”也不是“changes”
- 不要大写首字母
- 结尾不要使用句号
正文
正文是对标题的补充,但它不是必须的。和标题一样,它也要求使用祈使句且现在时态,正文应该包含更详细的信息,如代码修改的动机,与修改前的代码对比等。
页脚
任何Breaking Changes(破坏性变更,不向下兼容)都应该在页脚中进行说明,它经常也用来引用本次提交解决的GitHub Issue。
Breaking Changes应该以“BREAKING CHANGE:”开头,然后紧跟一个空格或两个换行符,其他要求与前面一致。
分支功能描述
master: 长期分支,用于对外版本发布,所有版本出自此版本库。此分支不允许直接提交代码,只从bugfix分支和develop分支合并。
develop: 长期分支,用于日常代码开发,与master分支 保持同步,当新功能开发完成后线合并到此分支,经过测试后再合并到master分支。
bugfix: 临时分支,当出现bug时基于master分支新建bugfix/bug-1,bug分支可根据bug编号命名。bug测试完毕合并进入develop分支和master分支
feature: 临时分支,开发新功能时从develop分支新建feature/feature-1,feature分支可根据功能命名。新特性开发完成合并进入develop分支并删除feature分支。
release: 临时分支,需要发布版本时从master分支新建release/release-1.0.0,release分支根据版本号命名。
release分支禁止再合并功能,只提交bug修改,版本发布完成后合并进入master和develop,并再对应的提交上打版本Tag。
提交规范
参考格式
1 | <type>: <subject> |
type: 本次commit的类型,如bugfix,docs,style等
feat: 添加新特性
fix: 修复bug
docs: 修改文档
style: 修改格式缩进,不改变代码逻辑
refactor: 代码重构,没有添加新下功能或者修复bug
perf: 增加代码进行性能测试
test: 增加测试用例
chore: 改变构建流程或者增加依赖库、工具等
scope: 本次commit波及范围
subject: 简明扼要阐述本次commit的主旨
- 使用祈使句
- 首字母不要大写
- 结尾无需添加标点
body: 详细描述本次commit,如需换行则使用
|footer: 描述下与之关联的 issue 或 breadk change
标题行: 50个字符以内,描述主要变更内容
主体内容: 更详细下说明文本,建议72个字符以内。需要描述信息包括:
- 为什么这个变更是必须的,它可能是用来修复一个bug,增加一个feature,提升性能、可靠性、稳定性等
- 如何解决这个问题,具体描述解决问题的步骤
- 是否存在副作用、风险
如果需要的话可以添加一个连接到issue或其他文档
示例
1 | docs(README): README添加代码提交规范 |