04-7_Qt 5.9 C++开发指南_QTreeWidget和QDockWidget
文章目录
- 1. 实例功能简述
- 2. 源码
- 2.1 可视化UI设计
- 2.2 mainwindow.h
- 2.3 mainwindow.cpp
1. 实例功能简述
本节介绍 QTreeWidget、QDockWidget 的使用,以及用 QLabel 显示图片的方法。实例 samp4_8以QTreeWidget 为主要组件,创建一个照片管理器,实例运行时的界面如图 4-14 所示。

这个实例主要演示如下几个组件的使用方法。
- QTreeWidget目录树组件
QTreeWidget 类是创建和管理目录树结构的类。实例使用一个 QTreeWidget 组件管理照片目录,可以添加、删除节点,每个节点设置一个自定义类型,另外,还设置了一个自定义数据,图片节点存储完整文件名,以便单击节点时显示该图片。
- QDockWidget 停靠区域组件
QDockWidget 是可以在QMainWindow 窗口停靠,或在桌面最上层浮动的界面组件。本实例将一个QTreeWidget 组件放置在 QDockWidget 区域上,设置其可以在主窗口的左或右侧停靠,也可以浮动。 - QLabel组件显示图片
右侧是一个QScrollArea 组件,ScrollArea 上面放置一个 QLabel组件,通过为 QLabel设置一个QPixmap 显示图片。通过 QPixmap 操作可进行缩放显示,包括放大、缩小、实际大小、适合宽度、适合高度等。
QTreeWidget、QDockWidget和QLabel组件详细的使用方法,请见源码或书籍
2. 源码
2.1 可视化UI设计

2.2 mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QTreeWidgetItem>
#include <QLabel>namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{Q_OBJECT
private:
//枚举类型treeItemType, 用于创建 QTreeWidgetItem 时作为节点的type, 自定义类型必须大于1000
//itTopItem 顶层节点; itGroupItem 组节点; itImageItem 图片enum treeItemType{itTopItem=1001,itGroupItem,itImageItem};//枚举类型,表示列号enum treeColNum{colItem=0, colItemType=1}; //目录树列的编号定义QLabel *LabFileName;QPixmap curPixmap; //当前的图片float pixRatio;//当前图片缩放比例void iniTree();//目录树初始化void addFolderItem(QTreeWidgetItem *parItem, QString dirName);//添加一个目录节点QString getFinalFolderName(const QString &fullPathName);//从目录全名称中获取最后的文件夹名称void addImageItem(QTreeWidgetItem *parItem,QString aFilename);//添加一个图片节点void displayImage(QTreeWidgetItem *item); //显示一个图片节点的图片void changeItemCaption(QTreeWidgetItem *item); //遍历改变节点标题
public:explicit MainWindow(QWidget *parent = 0);~MainWindow();private slots:
//目录树当前节点变动的信号void on_treeFiles_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous);void on_actAddFolder_triggered();//添加目录节点void on_actAddFiles_triggered();//添加图片节点void on_actZoomOut_triggered(); //缩小,zoom outvoid on_actZoomIn_triggered(); //放大,zoom invoid on_actZoomFitW_triggered(); //适合宽度void on_actZoomFitH_triggered();//适合高度void on_actZoomRealSize_triggered(); //实际大小void on_actDeleteItem_triggered(); //删除节点void on_actScanItems_triggered(); //遍历节点void on_actDockVisible_toggled(bool arg1);void on_dockWidget_visibilityChanged(bool visible);void on_dockWidget_topLevelChanged(bool topLevel);void on_actDockFloat_triggered(bool checked);private:Ui::MainWindow *ui;
};#endif // MAINWINDOW_H
2.3 mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"#include <QTreeWidgetItem>
#include <QFileDialog>void MainWindow::iniTree()
{ //初始化TreeQString dataStr=""; // Item的Data 存储的stringui->treeFiles->clear();//清除目录树所有节点QIcon icon;icon.addFile(":/images/icons/15.ico"); //设置ICON的图标QTreeWidgetItem* item=new QTreeWidgetItem(MainWindow::itTopItem); //新建节点时设定类型为 itTopItemitem->setIcon(MainWindow::colItem,icon); //设置第1列的图标item->setText(MainWindow::colItem,"图片文件"); //设置第1列的文字item->setText(MainWindow::colItemType,"type=itTopItem"); //设置第2列的文字item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsAutoTristate);item->setCheckState(colItem,Qt::Checked);//设置为选中item->setData(MainWindow::colItem,Qt::UserRole,QVariant(dataStr)); //设置节点第1列的Qt::UserRole的Dataui->treeFiles->addTopLevelItem(item);//添加顶层节点
}void MainWindow::addFolderItem(QTreeWidgetItem *parItem, QString dirName)
{//添加一个目录节点QIcon icon(":/images/icons/open3.bmp");QString NodeText=getFinalFolderName(dirName); //从一个完整目录名称里,获得最后的文件夹名称QTreeWidgetItem *item; //节点item=new QTreeWidgetItem(MainWindow::itGroupItem); //新建节点, 设定type为 itGroupItemitem->setIcon(colItem,icon); //设置图标item->setText(colItem,NodeText); //最后的文件夹名称,第1列item->setText(colItemType,"type=itGroupItem"); //完整目录名称,第2列item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsAutoTristate); //设置节点选项item->setCheckState(colItem,Qt::Checked); //节点选中item->setData(colItem,Qt::UserRole,QVariant(dirName)); //设置角色为Qt::UserRole的Data,存储完整目录名称parItem->addChild(item); //在父节点下面添加子节点
}QString MainWindow::getFinalFolderName(const QString &fullPathName)
{//从一个完整目录名称里,获得最后的文件夹名称int cnt=fullPathName.length(); //字符串长度int i=fullPathName.lastIndexOf("/");// 最后一次出现的位置QString str=fullPathName.right(cnt-i-1); //获得最后的文件夹的名称return str;
}void MainWindow::addImageItem(QTreeWidgetItem *parItem, QString aFilename)
{//添加一个图片文件节点QIcon icon(":/images/icons/31.ico");//ICON的图标QString NodeText=getFinalFolderName(aFilename); //获得最后的文件名称QTreeWidgetItem *item; //节点item=new QTreeWidgetItem(MainWindow::itImageItem); //新建节点时设定类型为 itImageItemitem->setIcon(colItem,icon); //设置图标item->setText(colItem,NodeText); //最后的文件夹名称item->setText(colItemType,"type=itImageItem"); //完整目录名称item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsAutoTristate); //设置节点选项item->setCheckState(colItem,Qt::Checked); //节点选中item->setData(colItem,Qt::UserRole,QVariant(aFilename)); //设置节点Qt::UserRole的Data,存储完整文件名称parItem->addChild(item); //在父节点下面添加子节点
}void MainWindow::displayImage(QTreeWidgetItem *item)
{//显示图片,节点item存储的图片文件名QString filename=item->data(colItem,Qt::UserRole).toString();//获取节点data里存的文件名LabFileName->setText(filename);curPixmap.load(filename); //从文件载入图片on_actZoomFitH_triggered(); //自动适应高度显示ui->actZoomFitH->setEnabled(true);ui->actZoomFitW->setEnabled(true);ui->actZoomIn->setEnabled(true);ui->actZoomOut->setEnabled(true);ui->actZoomRealSize->setEnabled(true);
}void MainWindow::changeItemCaption(QTreeWidgetItem *item)
{ //改变节点的标题文字QString str="*"+item->text(colItem); //节点标题前加“*”item->setText(colItem,str); //设置节点标题if (item->childCount()>0) //如果有子节点for (int i=0;i<item->childCount();i++) //遍历子节点changeItemCaption(item->child(i)); //调用自己,可重入的函数
}MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);LabFileName=new QLabel("");ui->statusBar->addWidget(LabFileName);this->setCentralWidget(ui->scrollArea); //设置中心布局组件iniTree();//初始化目录树
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::on_treeFiles_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
{ //当前节点选择变化时触发Q_UNUSED(previous);if (current==NULL)return;int var=current->type();//节点的类型switch(var){case itTopItem: //顶层节点ui->actAddFolder->setEnabled(true);ui->actAddFiles->setEnabled(true);ui->actDeleteItem->setEnabled(false); //顶层节点不能删除break;case itGroupItem: //文件组节点ui->actAddFolder->setEnabled(true);ui->actAddFiles->setEnabled(true);ui->actDeleteItem->setEnabled(true);break;case itImageItem: //图片文件节点ui->actAddFolder->setEnabled(false); //图片节点下不能添加目录节点ui->actAddFiles->setEnabled(true);ui->actDeleteItem->setEnabled(true);displayImage(current); //显示图片break;}
}void MainWindow::on_actAddFolder_triggered()
{// 选择一个文件夹,作为当前节点的子节点加入QString dir=QFileDialog::getExistingDirectory();//选择目录if (!dir.isEmpty()) //选择目录名称不为空{QTreeWidgetItem* parItem=ui->treeFiles->currentItem(); //当前节点addFolderItem(parItem,dir);//在父节点下面添加一个组节点}
}void MainWindow::on_actAddFiles_triggered()
{//添加图片文件节点QStringList files=QFileDialog::getOpenFileNames(this,"选择一个或多个文件","","Images(*.jpg)");//多选文件if (files.isEmpty()) //如果一个文件都没选return;QTreeWidgetItem *parItem,*item; //节点item=ui->treeFiles->currentItem(); //当前节点if (item->type()==itImageItem) //若当前节点是图片节点,取其父节点作为父节点parItem=item->parent();else //否则取当前节点为父节点parItem=item;for (int i = 0; i < files.size(); ++i){QString aFilename=files.at(i); //得到StringList里的一行,也就是一个文件名addImageItem(parItem,aFilename); //添加一个图片节点}
}void MainWindow::on_actZoomOut_triggered()
{ //缩小显示pixRatio=pixRatio*0.8; //在当前比例基础上乘以0.8int w=pixRatio*curPixmap.width();// 显示宽度int h=pixRatio*curPixmap.height();//显示高度QPixmap pix=curPixmap.scaled(w,h); //图片缩放到指定高度和宽度,保持长宽比例ui->LabPicture->setPixmap(pix);
}void MainWindow::on_actZoomIn_triggered()
{//放大显示pixRatio=pixRatio*1.2;//在当前比例基础上乘以0.8int w=pixRatio*curPixmap.width();// 显示宽度int h=pixRatio*curPixmap.height();//显示高度QPixmap pix=curPixmap.scaled(w,h);//图片缩放到指定高度和宽度,保持长宽比例ui->LabPicture->setPixmap(pix);
}void MainWindow::on_actZoomFitW_triggered()
{ //适应宽度显示int w=ui->scrollArea->width()-20;//得到scrollArea的高度int realw=curPixmap.width();//原始图片的实际宽度pixRatio=float(w)/realw;//当前显示比例,必须转换为浮点数QPixmap pix=curPixmap.scaledToWidth(w-30);ui->LabPicture->setPixmap(pix);
}void MainWindow::on_actZoomFitH_triggered()
{//适应高度显示图片int H=ui->scrollArea->height();//得到scrollArea的高度int realH=curPixmap.height(); //原始图片的实际高度pixRatio=float(H)/realH; //当前显示比例,必须转换为浮点数QPixmap pix=curPixmap.scaledToHeight(H-30); //图片缩放到指定高度ui->LabPicture->setPixmap(pix); //设置Label的PixMap
}void MainWindow::on_actZoomRealSize_triggered()
{ //实际大小显示pixRatio=1; //恢复显示比例为1ui->LabPicture->setPixmap(curPixmap);
}void MainWindow::on_actDeleteItem_triggered()
{//删除节点QTreeWidgetItem* item =ui->treeFiles->currentItem(); //当前节点QTreeWidgetItem* parItem=item->parent(); //父节点parItem->removeChild(item);//The removed item will not be deleteddelete item;
}void MainWindow::on_actScanItems_triggered()
{//遍历节点for (int i=0;i<ui->treeFiles->topLevelItemCount();i++){QTreeWidgetItem *item=ui->treeFiles->topLevelItem(i); //顶层节点changeItemCaption(item); //更改节点标题}
}void MainWindow::on_actDockVisible_toggled(bool arg1)
{// 停靠区的可见性ui->dockWidget->setVisible(arg1);
}void MainWindow::on_dockWidget_visibilityChanged(bool visible)
{//停靠区可见性变化ui->actDockVisible->setChecked(visible);
}void MainWindow::on_dockWidget_topLevelChanged(bool topLevel)
{//停靠区浮动性变化ui->actDockFloat->setChecked(topLevel);
}void MainWindow::on_actDockFloat_triggered(bool checked)
{//停靠区浮动性ui->dockWidget->setFloating(checked);
}相关文章:
04-7_Qt 5.9 C++开发指南_QTreeWidget和QDockWidget
文章目录 1. 实例功能简述2. 源码2.1 可视化UI设计2.2 mainwindow.h2.3 mainwindow.cpp 1. 实例功能简述 本节介绍 QTreeWidget、QDockWidget 的使用,以及用 QLabel 显示图片的方法。实例 samp4_8以QTreeWidget 为主要组件,创建一个照片管理器ÿ…...
Keburnetes YAML配置文件管理
Kubernetes 支持 YAML 和 JSON 格式管理资源对象JSON 格式:主要用于 api 接口之间消息的传递YAML 格式:用于配置和管理,YAML 是一种简洁的非标记性语言,内容格式人性化,较易读 YAML 语法格式 大小写敏感使用缩进表示层…...
opencv基础-33 图像平滑处理-中值滤波cv2.medianBlur()
中值滤波是一种常见的图像处理滤波技术,用于去除图像中的噪声。它的原理是用一个滑动窗口(也称为卷积核)在图像上移动,对窗口中的像素值进行排序,然后用窗口中像素值的中值来替换中心像素的值。这样,中值滤…...
后端进阶之路——深入理解Spring Security配置(二)
前言 「作者主页」:雪碧有白泡泡 「个人网站」:雪碧的个人网站 「推荐专栏」: ★java一站式服务 ★ ★前端炫酷代码分享 ★ ★ uniapp-从构建到提升★ ★ 从0到英雄,vue成神之路★ ★ 解决算法,一个专栏就够了★ ★ 架…...
怎么绘制汤姆索亚历险记思维导图?掌握这几个绘制步骤就可以
怎么绘制汤姆索亚历险记思维导图?如果你正在为学习汤姆索亚历险记而感到困惑,或者你想要更好地理解小说中的人物关系、情节和舞台背景,那么一个清晰的思维导图就可以帮助你梳理思路。那么下面就给大家介绍一下绘制步骤。 在进行思维导图绘制的…...
Redis和数据库更新先后顺序
在使用 Redis 和数据库时,更新的先后顺序可以根据具体场景来决定。一般来说,有以下两种典型的更新顺序: 先更新数据库,再更新 Redis: 这种更新顺序适用于需要保证数据的一致性和可靠性的场景。当有数据更新时,首先将数据更新到数据库中,确保数据持久化。然后再更新 Redi…...
JavaScript--AJAX
概述 传统的web交互是用户触发一个http请求服务器,然后服务器收到之后,在做出响应到用户,并且返回一个新的页面,每当服务器处理客户端提交的请求时,客户都只能空闲等待,并且哪怕只是一次很小的交互、只需从…...
AI Chat 设计模式:13. 代理模式
本文是该系列的第十三篇,采用问答式的方式展开,和前面的文章有一些不同,我不再进行提问了,改为由 GPT 1 号提问,GPT 2 号作答,每一节的小标题是我从 GPT 1 号的提问中总结出来的。我现在是完完全全的旁观者…...
嵌入式开发实用工具——QFSViewer
嵌入式开发实用工具——QFSViewer 介绍 今天给大家推荐个我个人业余时间开发的一个嵌入式开发实用工具——QFSViewer,这个工具主要是用来加载查看各种嵌入式常用的文件系统映像,目前支持JFSS2、Fat32、Fat16、Fat12、exFat、Ext2、Ext3、Ext4等文件系统…...
appium自动爬取数据
爬取类容:推荐知识点中所有的题目 爬取方式:appium模拟操作获取前端数据 入门级简单实现,针对题目和答案是文字内容的没有提取出来 适用场景;数据不多,参数加密,反爬严格等场景 from appium import webdriver impor…...
jenkins 在pinline克隆代码的两种方式
在pinline克隆代码的两种方式 1.pipline语法直接实现方式1.1例子11.2例子2 2.jenkins pinline 流水线中调用 shell脚本方式 jenkins搭建流水线从拉取代码开始其实是最正规的方式,但是如何拉取有多种方式 可以用jenkins的插件以钩子的形式,也可以在piplin…...
Python入门【编辑、组合、设计模式_工厂模式实现 、设计模式_单例模式实现、工厂和单例模式结合、异常是什么?异常的解决思路 】(十七)
👏作者简介:大家好,我是爱敲代码的小王,CSDN博客博主,Python小白 📕系列专栏:python入门到实战、Python爬虫开发、Python办公自动化、Python数据分析、Python前后端开发 📧如果文章知识点有错误…...
65 # 实现 http-server 里的 gzip 压缩
用 zlib 来实现 gzip 压缩 服务端优化都是:压缩 缓存 前端可以通过 webpack 插件进行压缩 gzip 根据替换来实现的,重复率越高,压缩后的结果越小 const zlib require("zlib"); const fs require("fs"); const path …...
点成分享丨qPCR仪的原理与使用——以Novacyt产品为例
近年来,PCR检测在多种领域发挥着巨大的作用。短时高效和即时监测都成为了PCR仪发展的方向。作为世界领先的制造商之一,Novacyt公司为来自全球多个国家和行业的用户提供了优质的qPCR仪。 MyGo Mini S qPCR仪是一种紧凑型的实时qPCR仪,非常适合…...
Postman如何做接口测试
目录 Postman如何做接口测试1:如何导入 swagger 接口文档 Postman如何做接口测试2:如何切换测试环境 Postman如何做接口测试3:什么?postman 还可以做压力测试? Postman如何做接口测试4:如何自动添加请求…...
每天一道leetcode:剑指 Offer 32 - II. 从上到下打印二叉树 II(适合初学者)
今日份题目: 从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。 示例 例如: 给定二叉树: [3,9,20,null,null,15,7], 3 / \ 9 20 / \ 15 7 返回其层次遍历结果: [ [3], […...
vue动态生成行
vue代码 <el-table :data"form.lineInfos" :bordertrue style"width: 99.99%;"> <el-table-column type"index" label"序号" width"50"></el-table-column> <el-table-column prop"unitPrice&qu…...
IPC之一:使用匿名管道进行父子进程间通信的例子
IPC 是 Linux 编程中一个重要的概念,IPC 有多种方式,本文主要介绍匿名管道(又称管道、半双工管道),尽管很多人在编程中使用过管道,但一些特殊的用法还是鲜有文章涉及,本文给出了多个具体的实例,每个实例均附…...
前端将页面转化为图片---进行下载导出、打印等功能
1.需要实现一个将div页面的东西导出,使用到了html2canvas 官网: 配置型 | HTML2CANVAS 中文文档 (allenchinese.github.io) 2.下载html2canvas npm install --save html2canvas 3.导入使用到的页面 import html2canvas from html2canvas 4.创建图片基础应用 …...
docker安装code-service在线开发vscode工具及node版本过低问题
docker安装code-service 拉去镜像 docker pull codercom/code-server创建项目存放映射路径 mkdir /data/code-service/project运行 这里不唯一,但注意密码 docker run -itd --name code-service -u root -p 1024:8080 -v /data/code-service/project:/home/cod…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...
Docker 本地安装 mysql 数据库
Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker ;并安装。 基础操作不再赘述。 打开 macOS 终端,开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论
路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中(图1): mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...
