实例概述

此实例主要介绍QTreeWidget、QDockWidget的使用,以及用QLabel显示图片的方法,实例主要使用QTreeWidget,创建一个照片管理器,实例运行界面效果如下:

此实例的主窗口是从QMainWindow继承而来,主要演示了下面几个组件的使用:

  • QTreeWidget目录树组件

QTreeWidget类是创建和管理目录树结构的类,实例使用了一个QTreeWidget组件管理照片目录,可以添加、删除节点,每个节点设置一个自定义类型,另外,还设置了一个自定义数据,图片节点储存完整文件名,以便单击节点时显示该图片

  • QDockWidget停靠区域组件

QDockWidget是可以在QMainWidget窗口停靠,或在桌面最上层浮动的界面组件,实例将一个QTreeWidget组件放置在一个QDockWidget组件之上,设置其在主窗口的左右停靠或浮动

  • QLabel组件显示图片

窗口右侧是一个QScrollArea组件,ScrollArea上面放置一个QLabel组件,通过QLabel设置一个QPixmap显示图片,通过QPixmap操作可进行缩放显示,包括放大、缩小、实际大小、适合宽度、适合高度等。

界面设计

界面布局设计

此实例界面采用可视化设计,程序功能主要采用Action实现,主菜单和主工具栏也都由其实现

工作区的左侧是一个QDockWidget组件,在其上方放置一个QTreeWidget组件,用水平布局使得treeWidget组件填充整个停靠区

工作区的右侧是一个QScrollArea组件,QScrollArea组件里放置一个QLabel,利用QLabel的pixmap属性显示图片。scrollArea内部的组件采用水平布局,当图片较小时,Label显示的图片可以自动居于scrollArea中间;当Label显示的图片超过scrollArea可显示区域的大小后,scrollArea会自动显示水平或垂直方向的卷滚条,用于显示更大的区域

在主窗口构造函数中将ScrollArea组件设置为主窗口中心组件后,DockWidget与ScrollArea之间自动出现分割条,可以分割两个组件的大小

QDockWidget组件属性设置

在UI设计器中对DockWidget组件的主要属性进行设置,主要属性如下:

  • allowedAreas属性,设置允许停靠的区域

由函数setallowedAreas()函数设置允许停靠区,参数是枚举类型Qt::DockWidgetArea的值得组合,可以设置在窗口的左、右、顶、底停靠,所有的区域都能停靠或不允许停靠,本实例设置为左右两侧停靠

  • features属性,设置停靠区组件的特性

由setFeatures()函数设置停靠区组件的特性,参数features是枚举类型QDockWidget::DockWidgetFeature的值得组合,枚举值如下:

  1. QDockWidget::DockWidgetClosable:停靠区可关闭
  2. QDockWidget::DockWidgetMovalbe:停靠区可移动
  3. QDockWidget::DockWidgetFloatable:停靠去可浮动
  4. QDockWidget::DockWidgetVerticalTitleBar:在停靠区左侧显示垂直标题栏
  5. QDockWidget::AllDockWidgetFeatures:使用所有特征
  6. QDockWidget::NoDockWidgetFeatures:不使用所有特征

QTreeWidget组件的设置

在UI设计器中,双击界面上的QTreeWidget组件,可以打开设计器,该设计器由两页,可以进行Item和Columns的设计

Columns页用于设计目录树的列,在设计器中可以添加、删除、移动列,设置列的文字、字体、前景色、背景色等属性

Items页面用于设计目录树的节点,可以对每个节点的属性进行设置,如文字、字体等,特别是flags属性,可以设置节点是否可选、是否可编辑、是否由CheckBox等,还可以设置节点的CheckState。在上图的下方有一组按钮可以新增节点,新增下级节点、移动节点、删除节点、该变节点级别等

使用设计器设计目录树的列和节点,适用于创建固定结果的目录树,但是目录树一般是根据内容动态创建的,需要运用代码实现节点的创建

Action设计

本例的大多数功能采用Action实现,在Action Editor里设计Action,然后利用Action设计主菜单和主工具栏

注意将QToolBar中的toolButtonStytle设置为ToolButtonTextUnderIcon,因为默认只显示图标,该属性是将Text显示在图标下方

 QTreeWidget操作

此实例的目录树节点操作定义如下一些规则

  • 将目录树的节点分为三种:顶层节点、分组节点、图片节点
  • 窗口创建时初始化目录树,它只有一个顶层节点,这个顶层节点不能被删除,而且不允许创建新的顶层节点
  • 顶层节点下允许添加分组节点和图片节点
  • 分组节点下允许添加分组节点和图片节点,分组节点的级数无限制
  • 图片节点就是终端节点,可以在图片节点同级再添加图片节点
  • 每个节点创建时设置其类型信息,图片节点储存其完整文件名作为自定义数据
  • 单击一个图片节点时,显示其关联文件的图片

由于在接下来的编程过程中会使用到一些数据类型和自定义函数需要提前在主窗口类中声明,先将MainWindow中的内容列出来,具体声明如下:

class MainWindow : public QMainWindow
{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = nullptr);~MainWindow();private:Ui::MainWindow *ui;//枚举类型treeItemType,创建节点时用作type参数,自定义类型必须大于1000enum 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 displayImage(QTreeWidgetItem *item);                           //显示一个图片节点的图片void changeItemCaption(QTreeWidgetItem *item);                      //遍历改变节点标题
};

目录树初始化添加顶层节点

主窗口MainWindow的构造函数会调用自定义函数iniTree(),对目录树进行初始化,窗口构造函数和iniTree()代码如下:

MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);LabFileName = new QLabel("");ui->statusBar->addWidget(LabFileName);this->setCentralWidget(ui->scrollArea);         //将scrollArea设置为主窗口工作区中心组件iniTree();                                      //初始化目录树
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::iniTree()
{//初始化目录树QString dataStr = "";                   //Item的Data储存的stringQIcon icon;icon.addFile("../images/文件夹.png");    //设置图标为:文件夹.pngQTreeWidgetItem* item = new QTreeWidgetItem(MainWindow::itTopItem);item->setIcon(MainWindow::colItem,icon);        //第一列的图标item->setText(MainWindow::colItem, "图片文件");  //第一列的文字item->setText(MainWindow::colItemType,"type=itTopItem");    //第二列item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled| Qt::ItemIsAutoTristate);item->setCheckState(colItem,Qt::Checked);item->setData(MainWindow::colItem, Qt::UserRole,QVariant(dataStr));ui->treeWidget->setHeaderItem(item);           //添加顶层节点
}

QTreeWidget的每个节点都是一个QTreeWidgetItem对象,添加一个节点前先要创建它,并且设置好相关属性

创建节点的语句是:

QTreeWidgetItem* item = new QTreeWidgetItem(MainWindow::itTopItem);

该函数传递了一个枚举常量MainWindow::itTopItem作为构造函数的参数,表示节点的类型。在构造函数中传递了一个类型值后,就可以使用QTreeWidgetItem::type()返回这个节点的类型值

itTopItem是在MainWindow里定义的枚举类型treeItemType的一个常量值。枚举类型treeItemType定义了节点的类型,自定义的节点类型值必须大于1000

QTreeWidgetItem中的setIcon()和setText()都需要传递一个列号作为参数,指定对哪个列进行设置。列号可以使用数字,但是为了便于理解和统一修改,在MainWindow中定义了枚举类型treeColNum,colItem表示第一列,colItemType表示第二列

setFlags()函数设置节点的一些属性标记,是Qt::ItemFlag枚举常量的组合

setData()函数为节点的某一列设置一个角色数据,setData()函数原型为:

void QTreeWidgetItem::setData(int column, int role,const QVariant &dataStr);

其中,column是列号,role是角色的值,value是一个QVariant类型的数

在目录树的初始化函数中,setData()函数为节点的第一列,角色UserRole()设置了一个字符串数据dataStr。Qt::UserRole是枚举类型Qt::ItemDataRole中一个预定义的值,节点创建完成之后,使用setHeaderItem()函数将此节点设置为顶层节点

添加目录节点

actAddFolder是用于添加组节点的Action,当目录树上的当前节点类型是itTopItem或itGropItem类型时,才可以添加组节点。actAddFolder的tiggered()信号的响应槽函数及相关自定义函数如下:

void MainWindow::on_actAddFolder_triggered()
{//添加组节点(目录)QString dir = QFileDialog::getExistingDirectory();          //选择目录if(!dir.isEmpty()){QTreeWidgetItem *parItem = ui->treeWidget->currentItem();addFolderItem(parItem,dir);                 //在父节点下面添加一个组节点}
}void MainWindow::addFolderItem(QTreeWidgetItem *parItem, QString dirName)
{QIcon icon("../images/文件夹.png");QString NodeText=getFinalFolderName(dirName);       //获取最后的文件夹的名字QTreeWidgetItem *item;item = new QTreeWidgetItem(MainWindow::itGroupItem);    //节点类型为itGroupItemitem->setIcon(colItem,icon);item->setText(colItem,NodeText);item->setText(colItemType,"type=itGroupItem");item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled| Qt::ItemIsAutoTristate);item->setCheckState(colItem,Qt::Checked);item->setData(colItem, Qt::UserRole,QVariant(dirName));parItem->addChild(item);                            //添加子节点
}QString MainWindow::getFinalFolderName(const QString &fullPathName)
{//获取最后一个文件夹名字int cnt = fullPathName.length();int i = fullPathName.lastIndexOf("/");QString str = fullPathName.right(cnt-i-1);qDebug()<<str<<endl;return  str;
}

actAddFolder的槽函数首先用一个文件对话框获取一个文件名称,在获取目录树的当前节点,然后调用自定义函数addFloderItem添加一个组节点,新添加的节点将会作为当前节点的子节点

addFolderItem()函数根据传递过来的父节点parItem和目录全程dirName,创建并添加子节点。首先用自定义函数getFinalFolderName()获取目录全称的最后一级文件夹的名字,这个文件夹名称将作为新建节点的标题;然后创建一个节点,创建时设置其节点类型为itGroupItem,表示分节点,再设置属性和关联数据,关联数据就是目录的全路径字符串;最后调用QTreeWidgetItem::addChild()函数,将创建的子节点作为父节点的一个子节点添加到目录树

添加图片文件节点

actAddFiles是添加图片文件节点的Action,目录树的当前节点为任何类型时这个Action都可以使用。actAddFiles的槽函数以及相关自定义函数的代码如下:

void MainWindow::on_actAddFile_triggered()
{//添加图片文件节点,支持多选QStringList files = QFileDialog::getOpenFileNames(this,"选择图片文件","","Images(*.jpg)");QTreeWidgetItem *item;item=ui->treeWidget->currentItem();for (int i=0; i < files.size(); i++) {QString aFilename = files.at(i);addImageItem(aFilename);}
}void MainWindow::addImageItem(QString aFilename)
{//添加一个图片节点QIcon icon("../images/图片.png");QString NodeText = getFinalFolderName(aFilename);QTreeWidgetItem *item;item = new QTreeWidgetItem(MainWindow::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->setData(MainWindow::colItem, Qt::UserRole,QVariant(aFilename));ui->treeWidget->currentItem()->addChild(item);
}

该槽函数首先使用QFileDialog::getOpenFileNames(),获取图片文件列表,通过QTreeWidgetItem::currentItem()函数获得目录树的当前节点item

函数使用files.at(i)获取当前图片文件的文件名,调用addImageItem()函数,将一个或多个图片文件节点添加到当前列表下

列表变化的响应

目录树上的列表项发生变化时,会发射currentItemChanged()信号,为此信号创建槽函数,实现当前节点类型的判断、Action按钮的使能设置、显示图片等响应功能

在UI设计器中的treewidget组件中,点击右键,在转到槽之后选择currentItemChanged()信号,编写该信号的响应槽函数

void MainWindow::on_treeWidget_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
{//列表树的变化响应槽函数Q_UNUSED(previous);         //Q_UNUSED()函数能够消除为引用参数的警告if(current == NULL)return;int var = current->type();switch (var) {case itTopItem:ui->actAddFile->setEnabled(true);ui->actAddFolder->setEnabled(true);ui->actDelete->setEnabled(false);break;case itGroupItem:ui->actAddFile->setEnabled(true);ui->actAddFolder->setEnabled(true);ui->actDelete->setEnabled(true);break;case itImageItem:ui->actAddFile->setEnabled(false);ui->actAddFolder->setEnabled(false);ui->actDelete->setEnabled(true);displayImage(current);break;}
}

current是变化后的当前节点,通过current->type()获取当前节点的类型,根据节点类型调整相应的Action的使能关系和其它功能(显示图片),其中显示图片相关函数会在后面详细介绍

删除节点

除了顶层节点外,其它节点都可以在选中之后将其删除。详细代码如下:

void MainWindow::on_actDelete_triggered()
{//删除节点QTreeWidgetItem *item,*parItem;item = ui->treeWidget->currentItem();parItem = item->parent();parItem->removeChild(item);         //父节点移除子节点,但不会删除该节点delete item;
}

但是,一个节点不能移除自己,因此需要使用item->parent()函数获取其父节点,让其父节点移除自己,之后再使用delete将其删除

若要删除顶层节点,则使用QTreeWidget::takeTopLevelItem(int index)函数,参数index为顶层列表的序号

QLabel和QPixmap显示图片

显示节点关联的图片

在目录树上单击一个节点后,如果其类型为图片节点,就会调用displayImage()函数显示节点的图片,当前节点为函数传递参数

void MainWindow::displayImage(QTreeWidgetItem *item)
{//显示图片,节点item保存了图片文件名QString filename = item->data(colItem,Qt::UserRole).toString();LabFileName->setText(filename);curPixmap.load(filename);on_actZoomIn_triggered();           //自动适应高度显示
}

QTreeWidgetItem::data()返回节点储存的数据,也就是用setDataa()设置的数据,在添加图片节点时,已经将文件名的全名存储为节点的数据,因此可以使用item->data()获取文件节点信息

curPixmap是在MainWindow中定义的一个QPixmap类型的变量,用于操作图片。QPixmap::load(QString &filename)直接将图片文件载入

最后直接调用on_actZoomIn_triggered()显示图片,这是actZoomFiH的槽函数,以自动适应高度的形式显示图片

图片的显示与缩放

在此实例中,包括适合宽度、适合高度、放大、缩小、实际大小等多个图片的缩放的Action,详细代码如下:

void MainWindow::on_actZoomIn_triggered()
{//放大显示pixRatio = pixRatio*1.2;int w = pixRatio*curPixmap.width();int h = pixRatio*curPixmap.height();QPixmap pix = curPixmap.scaled(w,h);ui->label->setPixmap(pix);
}void MainWindow::on_actZoomHig_triggered()
{//适合高度显示int H = ui->scrollArea->height();int realH = curPixmap.height();pixRatio = float(H)/realH;          //获取当前页面显示比例,且必须转化为floatQPixmap pix = curPixmap.scaledToHeight(H-30);   //图片缩放到指定高度ui->label->setPixmap(pix);
}void MainWindow::on_actZoomOut_triggered()
{//缩小显示pixRatio = pixRatio*0.8;int w = pixRatio*curPixmap.width();int h = pixRatio*curPixmap.height();QPixmap pix = curPixmap.scaled(w,h);ui->label->setPixmap(pix);
}void MainWindow::on_actZoomRealSize_triggered()
{//实际大小pixRatio = 1;ui->label->setPixmap(curPixmap);
}void MainWindow::on_actQuit_triggered()
{//退出按钮this->close();
}void MainWindow::on_actZoomWid_triggered()
{//适合宽度显示int W = ui->scrollArea->width();int realW = curPixmap.width();pixRatio = float(W)/realW;          //获取当前页面显示比例,且必须转化为floatQPixmap pix = curPixmap.scaledToWidth(W-30);   //图片缩放到指定宽度ui->label->setPixmap(pix);
}

QPixmap储存了图片数据,可以缩放图片,有以下几个函数:

  • QPixmap scaledToHeight(int height):返回一个缩放后的图片的副本,图片缩放到指定高度height
  • QPixmap scaledToWidtht(int width):返回一个缩放后的图片的副本,图片缩放到指定宽度width
  • QPixmap scaled(int width,int height):返回一个缩放后的图片的副本,图片缩放到指定高度和宽度

变量curPixmap保存了图片的原始副本,要缩放只需要调用curPixmap的相应函数,返回缩放后的图片副本

在界面上的标签label上显示图片,使用了setPixmap()函数

QDockWidget操作

程序运行时,主窗口上的DockWidget组件可以被拖动,在主窗口的左、右两侧停靠,或者是在桌面上浮动。工具栏上的窗口浮动和窗口可见按钮可以用代码控制组件是否浮动、是否可见,代码如下:

void MainWindow::on_actFloat_triggered(bool checked)
{//窗口浮动ui->dockWidget->setFloating(checked);
}void MainWindow::on_actVisible_toggled(bool arg1)
{//窗口可见ui->dockWidget->setVisible(arg1);
}

当点击DockWidget组件标题栏的关闭按钮时,会隐藏停靠区并发射信号visibilityChanged(bool)信号,当拖动DockWidget组件,使其浮动或停靠时,会发射信号topLevelChanged(bool)。为这两个信号编写槽函数,可以更新两个Aciton的状态

在UI设计器中点击DockWidget组件,单击右键转到槽,之后选择visibilityChanged(bool),为其编写响应槽函数

同理为topLevelChanged(bool)信号编写响应槽函数,详细代码如下:

void MainWindow::on_dockWidget_visibilityChanged(bool visible)
{//停靠区域可见性变化ui->actVisible->setChecked(visible);
}void MainWindow::on_dockWidget_topLevelChanged(bool topLevel)
{//停靠区浮动性变化ui->actFloat->setChecked(topLevel);
}

QT常见界面设计组件——QTreeWidget和QDockWidget相关推荐

  1. QT 可视化界面设计

    qt 界面设计使用布局,有布局层次(包括对象和类)和布局管理 1.有两个组件面板有layouts和spacers. 先拖放布局组件到窗体,在往布局组件里拖放其他控件. 或者是选择多个空间后,在选择设计 ...

  2. Activiti-5.22.0——activiti-modeler界面设计组件介绍

    目录 1.启动事件(Start Events): (1)无启动事件(Start event): A.描述: B.图标: (2)计时器事件(Start timer event): A.描述: B.图标: ...

  3. C++ QT图形界面设计:基本类和语法框架认知

    1.helloworld代码框架(QT初认知) int main(int argc,char *argv[])//程序台控制参数不要乱删,删了就启动不了了 {//1.a应用程序对象,在QT中,应用程序 ...

  4. 一文读懂qt界面设计(分裂器,布局,拉伸,各种属性设置)

    可以先看看我这个文章:qt关于界面设计中的一些知识总结_我是标同学的博客-CSDN博客_qt 水平伸展 现在我们来正式开始讲解. 布局种类 qt中能称为布局管理器的有如下6个: 水平布局(QHBoxL ...

  5. 五子棋ai:极大极小搜索和α-β剪枝算法的思想和实现(qt和c++)(一)引言和界面设计

    源代码 GitHub上:Github livingsu/Gobang-ai:极大极小搜索和α-β剪枝 引言 alphaGo击败围棋冠军李世石的新闻让我对棋类博弈产生了浓厚的兴趣,无奈本人不会围棋,但算 ...

  6. QT界面设计并保存到文件(以JSON格式)

    这两天写了关于QT的界面设计的东西,总之在大家的努力下搞好了.下面是一些主要的代码和思路 首先头文件就不讲了,要包含一大堆头文件,当然还有槽函数,因为我是在点击的时候才保存到文件中的. 下面只讲.cp ...

  7. QT实时视频播放界面设计

    QT播放界面设计 今天写了个QT的实时视频播放界面,其实要写一个播放界面非常容易,以下为代码 首先定义一个用于播放的控件: * PlsyItem.h #ifndef PLAYITEM_H #defin ...

  8. 精美的手机界面设计素材和线框图设计工具推荐

    在制作界面原型的时候,如果有现成的界面基础元素可以使用的话,设计师就可以非常快速的完成原型的制作,能够节省大量的时间和精力.在这篇文章,我向大家分享45套非常有用的 UI 和 Wireframe 套件 ...

  9. 45套精美的 ( Android, iPhone, iPad ) 手机界面设计素材和线框图设计工具

    在制作界面原型的时候,如果有现成的界面基础元素可以使用的话,设计师就可以非常快速的完成原型的制作,能够节省大量的时间和精力.在这篇文章,我向大家分享45套非常有用的 UI 和 Wireframe 套件 ...

最新文章

  1. 实现无线AP无缝漫游
  2. 高等数学上-赵立军-北京大学出版社-题解-练习2.7
  3. android view使用方法,android – 如何使用getView()方法,它在哪里被调用?
  4. Nexus 3.31.1-01搭建 maven 私服 windows
  5. python 怎么将数组转为列表_Python怎么将文件读入列表?
  6. 前端开发 样式表的建立和优先级 0229
  7. 大数据自学——Spark
  8. Python小笔记——urllib2得到重定向最终链接
  9. 蓝色圆形门禁卡怎么模拟_手把手教你把门禁卡复制到手机,跟实体门禁卡说拜拜...
  10. Python推导式comprehension:列表推导式、集合推导式、字典推导式
  11. 微型计算机通信与接口技术 pdf,微机原理与接口技术 pdf
  12. Visual studio 代码管理工具Git
  13. AirBuddy技巧:如何检查Mac电脑是否支持低功耗蓝牙?
  14. 2021-07-07 分类页面结构
  15. MJPEG和MP4——视频转换随想
  16. ERROR StatusLogger No log4j2 configuration file found. Using default configuration解决方式
  17. Playable Director (TimeLine) 3D游戏的开场动画制作
  18. 马赛克颗粒感天空Canvasjs特效
  19. 【中危】Sweet32: TLS 64位分组密码生日攻击(CVE-2016-2183)
  20. ns3--TapBridge, TapNetDevice,FdNetDevice等

热门文章

  1. 《匠人精神》读书笔记要点记录及自我剖析
  2. 付宇泽20190912-3 词频统计
  3. idea error jdk isnt specified for module
  4. 一个神奇指标公式,能找到立刻单边行情的品种,准确率惊人,堪称交易法宝!
  5. [C语言] 文件操作《一》
  6. day21-pdf作业
  7. 云栖专辑 | 阿里开发者们的第8个感悟:在信息大爆炸的时代,保持专注度显得尤为可贵
  8. 哈佛大学统计学教材_哈佛校友在职场上的统计数据
  9. Java web项目利用POI导出EXCEL表格
  10. android 开放聊天室