Qt实践3: 图片浏览器

Qt实现图片浏览器

Qt实践3: 图片浏览器

引言

因课程教学,需要利用Qt做图形界面设计(GUI)。自学Qt两月有余,发现现有很多资料,讲述C++程序设计QT项目的较多,不利于新手入门,特别是对于C++编程较弱的学生,上手较难。因此,我将所学的资料,进行归纳整理,总结出一种利用Qt Creator平台的UI设计模式进行Qt项目设计的方法,其中信号与槽函数的编写,也利用槽函数自动连接的方法,大大减少C++代码的编写。该GUI设计方法简捷,易于新手学习。
第一个实践项目是密码登录窗设计,主要讲述 QtCreator的基本操作、对话框Dialog窗体的创建,以及两个窗口的切换显示方法。
第二个实践项目是简易计算器的设计,着重讲述Widget窗体的界面设计与布局方法、槽函数编写方法。
本项目设计着重讲述带有菜单栏、工具栏和铆接组件的MainWindow窗体设计、信号与槽函数自动配置,以及槽函数编程方法。
本实践项目是图片浏览器设计,借鉴于[寒江雪Charles的图片浏览器],该文章提供的源代码,着重利用C++代码方式编写程序。这里对其进行简化,充分利用QtCreator的UI设计模式,减少编写的代码,便于新手学习。

一、 实验目的

  1. 熟悉 QtCreator的基本操作,熟练掌握信号与槽在应用程序中的使用。
  2. 熟练Qmainwindow窗口设计方法
  3. 掌握图片浏览器的Qt设计方法

二、 实验内容

  1. 学习 Qt 资源系统使用方法。
  2. 使用 QtCreator,设计图片浏览器。
    在这里插入图片描述

三、实现步骤

1. 创建工程
打开 QtCreator,新建项目,进行以下操作:
 选择“Qt Widgets Application”
 项目名称“ImageViewer”,路径“…/QImageViewer”
 选择类“QmainWindow”,名称“ImageViewer”
 并选中“创建界面”
在这里插入图片描述
2. 添加资源文件
 将图片文件夹“/images”复制到项目路径“…/QImageViewer”中。(该图片文件夹来自于[[寒江雪Charles的图片浏览器]],放置了菜单操作图标)
 右击项目名称,选择“Add New”,打开新建文件界面。
 选择模板Qt->Qt Resource File,名称为“Images”,路径选择上步复制的图片文件夹“/images”,默认选择添加到当前项目中。 窗口正下方,点击“添加”,点击“添加前缀”,修改前缀为“/images”.
 再点击“添加”,选择“添加文件”,全部选中当前图片(ctrl+A),完成资源文件的创建。
在这里插入图片描述
3.菜单栏设计
菜单栏的构成:标题栏、菜单栏、工具栏、锚接部件、中心部件
在这里插入图片描述
双击项目树中的imageviewer.ui文件名,进入设计模式。
1)创建菜单栏和选项
窗口界面上,双击“在这里输入”,可输入菜单栏的名称,回车后进入当前菜单选项设计界面,再双击“在这里输入”,可创建当前菜单下各选项。
这里,创建菜单栏和菜单下选项分别为:
创建菜单栏File,选项有:打开,关闭,退出。(中文不能直接输入,可用复制、黏贴方式输入)。
创建菜单栏operate,选项有:上一张,下一张,左旋,右旋,放大,缩小。
创建菜单栏About,选项有:Qt
在这里插入图片描述
2)添加菜单选项的图标
双击下方动作编辑器窗口的“actionopen”,弹出编辑动作窗口,点击图标选项“…”,弹出图片选择窗口,选择合适的图片。(如,add.png)
在这里插入图片描述
类似操作,分别给选项:打开,关闭,退出;上一张,下一张,左旋,右旋,放大,缩小;About Qt,都选择合适的图标的图片。

3)添加快捷键
如上,打开编辑动作的窗口,在Shortcut空白处按住键盘组合键,即可输入对应的快捷键。比如,这里按住Ctrl和O键,则设置打开选项的快捷键是Ctrl+O
在这里插入图片描述
分别给全部菜单选项添加对应的快捷键。(也可以不添加)
下方的动作编辑器窗口中,修改各菜单选项的名称。最后,如下图所示。
在这里插入图片描述
4.工具栏设计
下方的动作编辑器窗口中,选中某图标,直接拖到上方窗口工具栏的空白处即可。
在这里插入图片描述
5.功能实现
 信号与槽函数自动创建
下方的动作编辑器窗口中,右击某actionOpen,选择“转到槽”,默认选择“triggered()”信号,自动创建槽函数:void ImageViewer::on_actionOpen_triggered()。该槽函数是空函数,需要编写程序实现动作事件。
在这里插入图片描述
在这里插入图片描述
相同操作,依次创建其他action的空白槽函数。

 编写各槽函数的功能程序
多个action的槽函数,都要先进行打开图片、读取图片信息的操作,因此这里先进行2个函数的定义
int loadImageResource(void)函数用于打开本地某文件夹中的一个图片;
int getFileInfoList(void)函数用于读取图片信息。
1) 打开本地某文件夹中的一个图片。
调用QFileDialog::getOpenFileName函数,提供了打开文件窗口。程序如下:

int ImageViewer::loadImageResource(void)
{
    //调用标准对话框QFileDialog类,打开一个图片
    filename = QFileDialog::getOpenFileName(this, tr("Select image:"),
        "D:\\Documents\\Pictures", tr("Images (*.png *.bmp *.jpg *.gif)"));
    if (filename.isEmpty()) {
        return -1 ;
    }
   //QImage类封装了对于一般图像像素级的操作,图像显示则使用QPixmap。
    if (!image.load(filename)) {
        QMessageBox::information(this, tr("Error"), tr("Open file error")); //错误提示
        return -1 ;
    }
    //QImage转换成QPixmap
    pixmap = QPixmap::fromImage(image);
    size = pixmap.size();
    /* get file list */
    getFileInfoList();
    return 0;
}

解释:
QFileDialog::getOpenFileName函数的调用格式,自行百度吧,这里调用它,产生一个对话框,其标题为"Select image:",默认打开路径是 “D:\Documents\Pictures”,只能打开*.png *.bmp *.jpg *.gif格式的图片。选择某图片打开后,该图片名称赋给filename。
image.load(filename)则是根据文件名导入图片像素信息,赋值给变量image
Qimage图片信息需要转换成QPixmap形式,才能显示,调用转换函数:
变量pixmap = QPixmap::fromImage(image);
变量size 用于保存pixmap 的像素长和宽值。
getFileInfoList()函数,是另一个自定义的函数,用于读取打开后的本地图片文件夹目录等信息。

2) 读取图片所在文件夹的路径和目录列表信息
自定义的函数:getFileInfoList(void),程序编写:

int ImageViewer::getFileInfoList(void)
{
    QFileInfo info;            //定义变量
    QFileInfoList infoList;

    path = QFileInfo(filename).absolutePath();  //返回绝对路径
    dir = QFileInfo(filename).absoluteDir();    //返回目录名称
    /* clear list */
    fileInfoList.clear();
    infoList = dir.entryInfoList(QDir::Files);  //列出dir(path)目录文件下所有文件和目录信息,存储到infoList 容器
    //进行文件夹递归遍历,将内容存入infoList 容器
    for (int i = 0; i < infoList.count(); i++) {   //文件数目:fileInfo.count();
        info = infoList.at(i);                     //文件名称:fileInfo.at(i)
        QString suffix = info.suffix();                //后缀名
        if (suffix == "jpg" || suffix == "bmp" || suffix == "png") {
            fileInfoList.append(info);
        }
    }
    QFileInfo curImageInfo = QFileInfo(filename);
        for (int j = 0; j <fileInfoList.count(); j++) {
            info = fileInfoList.at(j);             //进行文件夹递归遍历
            if (info.fileName() == curImageInfo.fileName()) {
                index = j;        //记录索引值
                }
     }
    return 0 ;
}

解释:
这里要调用QFileInfo、QFileInfoList类,
path = QFileInfo(filename).absolutePath(); //返回绝对路径
dir = QFileInfo(filename).absoluteDir(); //返回目录名称
infoList = dir.entryInfoList(QDir::Files); //列出dir(path)目录文件下所有文件和目录信息,存储到infoList 容器
.count(); //文件总数
.at(i); //读取文件名称
fileInfoList.append(info); //fileInfoList文件列表中添加文件名info

3)变量、函数预定义,以及初始化
上面两个函数中使用了多个变量、类及其函数,需要在imageviewer.h头文件预定义,指定库文件。
因此,imageviewer.h头文件中添加库文件引用:
在这里插入图片描述

添加变量定义
public:
int index;
int angle; //后面设计左/右旋槽函数时要用到
QSize size;
QString filename;
QString path;
QDir dir;
QFileInfo fileInfo;
QFileInfoList fileInfoList;
QImage image;
QPixmap pixmap;
添加函数定义:
private:
/* init param /
void initImageResource(void); //初始化函数,接下来会讲解,这里一并先预定义
/
open a image /
int loadImageResource(void);
/
get file info list from current path */
int getFileInfoList(void);

各变量,需要在程序设计开始时进行初始化处理,所以编写初始化函数initImageResource(void)为:

void ImageViewer::initImageResource(void)
{
    index = -1;
    angle = 0;
    size = QSize(0, 0);
    filename.clear();
    path.clear();
}

void initImageResource(void)初始化函数一般放在ImageViewer::ImageViewer(QWidget *parent) 窗口描述中:
{
ui->setupUi(this);
//初始化
initImageResource();
}

4)action “打开”的槽函数的程序设计

void ImageViewer::on_actionOpen_triggered()
{
    loadImageResource();    //打开某目录中的图片
   //Label标签上显示图片
    ui->imageLabel->setPixmap(pixmap);
    ui->imageLabel->resize(size);//实现图片自适应大小
  //设置窗口的标题名称
    setWindowTitle(QFileInfo(filename).fileName() + tr(" - imageViewer")); 
}

解释:
ui->imageLabel是在菜单窗口中间拖放的label标签,用于图片显示。
resize(size)函数是调整图片自适应大小的变化。前面需要引用QSize

5)action “关闭”的槽函数的程序设计

void ImageViewer::on_actionClose_triggered()
{
    //清除图片显示
    ui-> imageLabel->clear();
   //读取资源文件中+号图片
    image.load(":/images/add.png");
    pixmap = QPixmap::fromImage(image);
    size = pixmap.size();
    ui->imageLabel->setPixmap(pixmap);
    ui->imageLabel->resize(size);//实现图片自适应大小
    setWindowTitle(tr("imageViewer"));
}

6)action “退出”的槽函数的程序设计

void ImageViewer::on_actionExit_triggered()
{
  close();
}

7)action “左旋”的槽函数的程序设计

void ImageViewer::on_actionLeft_triggered()
{
    //预先加载图片后,已得到image、size等数据,这里直接进行左旋处理
    QImage imgRotate;     //定义局部变量
    QMatrix matrix;

    angle +=3;
    angle=angle%4;              //取余数
    matrix.rotate(angle*90);    //得到旋转角度,逆时针旋转
    imgRotate = image.transformed(matrix);  //尺度变换函数transformed(matrix)
    pixmap = QPixmap::fromImage(imgRotate); 
    size = pixmap.size();
    //Label标签上显示图片
     ui->imageLabel->setPixmap(pixmap);
     ui->imageLabel->resize(size);//实现图片自适应大小
     return ;
}

action “右旋”的槽函数,类同,修改angle +=1即可。

8)action “放大”的槽函数的程序设计

void ImageViewer::on_actionEnlarge_triggered()
{
    //加载图片后,已得到image、size等数据,这里直接进行处理
    QImage imgScaled;
    QImage imgRotate;
    QMatrix matrix;
    // 调用image.scaled函数,进行尺度变换
     imgScaled = image.scaled(size.width() *1.2,   //放大倍数1.2
                              size.height() * 1.2,
                              Qt::KeepAspectRatio);
     /* modify angle */
     matrix.rotate(angle * 90);    //读取当前旋转角度
     imgRotate = imgScaled.transformed(matrix);  //变换

     pixmap = QPixmap::fromImage(imgScaled);   
     size = pixmap.size();
     //Label标签上显示图片
      ui->imageLabel->setPixmap(pixmap);
      ui->imageLabel->resize(size);//实现图片自适应大小
      return ;
}

action “缩小”的槽函数,与此类同,修改放大倍数1.2为0.8即可。

9)action “上一张”的槽函数的程序设计

void ImageViewer::on_actionLast_triggered()
{
        index = index - 1;        //更新索引值,减一
        int count = fileInfoList.count();    //读取文件个数的统计值
      //判断是否第一张图片
        if (index < 0) {
       QMessageBox::information(this, tr("Tip"), tr("This is the first image."));
       index = count - 1;
        }
       //读取当前路径path下索引值index – 1的文件名
        filename.clear();
        filename.append(path);
        filename += "/";
        filename += fileInfoList.at(index).fileName();
       //根据文件名加载图片,否则错误提示
        if (!image.load(filename)) {  
            QMessageBox::information(this, tr("Error"), tr("Open file error")); 
            return  ;
        }
        //QImage转换成QPixmap
        pixmap = QPixmap::fromImage(image);
        size = pixmap.size();
        //Label标签上显示图片
         ui->imageLabel->setPixmap(pixmap);
         ui->imageLabel->resize(size);//实现图片自适应大小
        //标题栏上,添加图片名和- imageViewer
        setWindowTitle(QFileInfo(filename).fileName() + tr(" - imageViewer"));
        return;
}

action “下一张”的槽函数,与此类同,修改index = index+1;修改判断语句(是否是最后一张图片):
if (index == count) {
QMessageBox::information(this, tr(“Tip”), tr(“This is the last image.”));
index = 0;
}

10)action “Qt”的槽函数的程序设计
这里需要构建QDockWidget窗口部件(锚接部件),它是放置在QMindow窗口上的工具窗口,可移动和悬浮。

void ImageViewer::on_actionQt_triggered()
{
//构建停靠窗口名AboutMe,指定父类为this主窗口
    QDockWidget *AboutMe = new QDockWidget(tr("About Qt"),this);    AboutMe->setWindowTitle(tr("About Me"));   
//设置停靠窗口特性,可移动,可关闭,可漂浮
  AboutMe->setFeatures(QDockWidget::AllDockWidgetFeatures); 
//设置窗口停靠位置
  AboutMe->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);  
//构建显示文本myInfo
  QTextEdit *myInfo = new QTextEdit(tr("<br>Welcom</br><br>blog address:https://blog.csdn.net/leyan118</br>"));
   //构建显示文本myInfo为锚接部件
AboutMe->setWidget(myInfo);
      addDockWidget(Qt::RightDockWidgetArea, AboutMe);  //右侧显示
}

使用QDockWidget以及QTextEdit,需要在imageviewer.h头文件中引入库文件QTextEdit、QDockWidget。

功能自行扩展:

  1. 自动播放。(提示,需要使用定时器)
  2. 其他功能扩展:图像扭曲,或图像处理(灰度变换等)

源码下载


版权声明:本文为leyan118原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。