04-7_Qt 5.9 C++开发指南_QTreeWidget和QDockWidget

2023-11-19

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 out

    void on_actZoomIn_triggered(); //放大,zoom in

    void 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()
{ //初始化Tree
    QString    dataStr=""; // Item的Data 存储的string

    ui->treeFiles->clear();//清除目录树所有节点
    QIcon   icon;
    icon.addFile(":/images/icons/15.ico"); //设置ICON的图标

    QTreeWidgetItem*  item=new QTreeWidgetItem(MainWindow::itTopItem); //新建节点时设定类型为 itTopItem
    item->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的Data
    ui->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为 itGroupItem
    item->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); //新建节点时设定类型为 itImageItem
    item->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.8

    int 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.8

    int 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;  //恢复显示比例为1
    ui->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 deleted
    delete 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);
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

04-7_Qt 5.9 C++开发指南_QTreeWidget和QDockWidget 的相关文章

随机推荐

  • Educoder - Java面向对象 - 文件类

    掌握知识点 第一关 IO包了解 File类了解 FileFileter类了解 IOException类了解 linux操作系统了解 通关源码 第1关 创建文件 package step1 import java io File import
  • JSON字符串不规范命名(java的规范)的解决办法

    为什么80 的码农都做不了架构师 gt gt gt 在建立json对应的java实体的时候 正常我们是实体的属性名和json的key名字保持一致的 这样在转换的过程中就能保存上对应key的value值 但是遇到不规范命名的json的时候咋办
  • flatten-maven-plugin 的使用

    引入 flatten maven plugin flatten maven plugin 插件的功能就不赘述了 网上也有很多文章描述这一块的内容 以一个 maven 多模块的项目为例 使用的时候直接在项目的父 pom 里加入如下的配置
  • matlab 分类学习工具箱 Classification Learner的使用及导出其生成的图,混淆矩阵confusion matrix的画法

    声明 转自https blog csdn net qq 27914913 article details 71436838 https blog csdn net evil xue article details 89765890 在mat
  • Golang语言记录

    编译成Linux可执行文件 先设置环境 SET GOARCH amd64 SET GOOS linux SET CGO ENABLED 0 然后运行 go build o 编译成的文件名 Golang的格式化输出 定义示例类型和变量 typ
  • GD32F310 (二) 按键轮询输入

    目录 首言 一 按键输入初始化 二 按键main 应用 首言 作者 小飞虫科技 淘宝 首页 小虫飞科技 淘宝网 taobao com 开发板 GD32F3X0系列 一 按键输入初始化 void KEY Init void enable th
  • 【华为OD机试真题2023B卷 JAVA&JS】勾股数元组

    华为OD2023 B卷 机试题库全覆盖 刷题指南点这里 勾股数元组 知识点编程基础 时间限制 1s 空间限制 256MB 限定语言 不限 题目描述 如果3个正整数 a b c 满足a2 b2 c2的关系 则称 a b c 为勾股数 著名的勾
  • C#中Validating和Validated事件

    您可能经常需要检查用户输入到 Windows 窗体中的信息是否有效 例如 如果您有一个电话号码的 TextBox 控件 则可以检查该控件是否只包含适当的字符 数字 括号和连字符等等 通常 可使用正则表达式验证用户输入的数据 了解Valida
  • powerdesigner汉化包

    PowerDesigner是一款专业的建模工具 如果你希望使用中文界面 你可以尝试使用汉化包 汉化包是一种用于翻译软件界面的工具 它可以将英文界面翻译成中文 你可以在网上搜索 PowerDesigner汉化包 并下载适合你当前版本的汉化包
  • 字符串函数的使用及模拟实现:strtok&strstr&strerror:

    字符串函数strstr的使用 char strstr const char str1 const char str2 Returns a pointer to the first occurrence of str2 in str1 or
  • LeetCode338. 比特位计数

    题目连接 https leetcode cn com problems counting bits 解题思路 这道题需要计算从 0 到 num 的每个数的二进制表示中的 1 的数目 最直观的方法是对每个数直接计算二进制表示中的 1 的数目
  • 使用c++超详细解释数据结构中的顺序栈和链栈

    在C 中 栈 Stack 是一种数据结构 它可以用来存储数据 并支持两种基本操作 压入 Push 和弹出 Pop 栈的特点是后进先出 Last In First Out LIFO 也就是最后压入的元素最先弹出 栈可以用数组或链表等数据结构来
  • hdu2030 汉字统计

    hdu2030 汉字统计 Time Limit 2000 1000 MS Java Others Memory Limit 65536 32768 K Java Others Total Submission s 4080 Accepted
  • 树莓派的杂七杂八

    一 交叉编译jpeg 9a 生成的库为libjpeg so 先从官网下载交叉编译器 直接解压到本地 将bin目录加入到系统变量中后 进入目录执行 configure CC arm none linux gnueabi gcc enable
  • 如何在 Flink 1.9 中使用 Hive?

    Flink on Hive 介绍 SQL 是大数据领域中的重要应用场景 为了完善 Flink 的生态 发掘 Flink 在批处理方面的潜力 我们决定增强 FlinkSQL 的功能 从而让用户能够通过 Flink 完成更多的任务 Hive 是
  • 字符串 有效的字母异位词

    LC 有效的字母异位词 给定两个字符串 s 和 t 编写一个函数来判断 t 是否是 s 的字母异位词 注意 若 s 和 t 中每个字符出现的次数都相同 则称 s 和 t 互为字母异位词 func isAnagram s String t S
  • 华为云云耀云服务器L实例评测|使用Docker部署Leanote笔记工具

    华为云云耀云服务器L实例评测 使用Docker部署Leanote笔记工具 一 前言 1 1 云耀云服务器L实例介绍 1 2 Leanote简介 二 本次实践介绍 2 1 本次实践简介 2 2 本次环境规划 三 购买云耀云服务器L实例 3 1
  • Vue2基本知识

    记录Vue2基本知识 从引入vue js文件开始 然后提出问题 1 我们使用vue后怎样将外部数据传递给我们的DOM对象 2 DOM对象中的数据如果改变 如何通知外部数据改变 最后对问题分析得出答案 完整记录vue2中基础指令知识 提供完整
  • 一文教你在 centos7 下安装 Oracle19 C(完整版)

    前言 安装 Oracle 一直是本人工作以来想要做的事情 但是一直都没有安装成功 本人有一个习惯 所有的软件基本上都安装在centos系统下 这样 一方面是 在日常工作中 都是linux环境 另一方面 装在linux虚拟中 万一哪天你想退出
  • 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