Qt案例:实现显示图片

效果图:
Qt案例:实现显示图片_第1张图片

17.1 组件使用

17.1.1 QDockWidget

含义:停靠区窗口,和状态栏、标题栏是一个等级

属性:

  • allowedAreas:设置允许停靠区域,或者使用代码setAllowedAreas(Qt::DockWidgetAreas areas)
  • features:设置停靠的属性。setFeatures(DockWidgetFeatures features)
Qt案例:实现显示图片_第2张图片
17.1.2 QTreeWidget

含义:目录树

属性:

  • Columns页用于设计目录树的列,目录树可以有多个列。在设计器里可以添加、删除、移动列,设置列的文字、字体、前景色、背景色、文字对齐方式、图标等。

  • Items页面用于设计目录树的节点,可对每个节点设置属性,如文字、字体、图标等,特别是fags属性,可以设置节点是否可选、是否可编辑、是否有CheckBox等,还可以设置节点的CheckState。

Qt案例:实现显示图片_第3张图片

17.2 Action

Qt案例:实现显示图片_第4张图片

17.3 定义基本变量

private:
    // 创建节点时用作type参数,自定义类型必须大于1000
    enum treeItemType{
        itTopItem = 1001,
        itGroupItem,
        itImageItem
    };
    enum treeColNum{
        colItem=0,
        colItemType=1
    };

    QLabel *LabFileName;// 显示状态栏文件名称
    QPixmap curPixmap; // 当前图片
    float pixRatio; // 当前图片比例


    // 初始化目录树
    void initTree();

    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); // 遍历改变节点标题

17.4 目录树初始化

添加顶层节点

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    // 状态栏显示文件名
    LabFileName = new QLabel("");
    ui->statusBar->addWidget(LabFileName);
    // 设置中心窗体
    this->setCentralWidget(ui->scrollArea);
    // 初始化目录树
    initTree();
}

void MainWindow::initTree()
{
    QString dataStr = "";
    ui->treeWidget->clear(); // 清空目录树
    QIcon icon;
    icon.addFile(":/icons/icons/15.ico");

    QTreeWidgetItem *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::ItemIsAutoTristate | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
    item->setCheckState(colItem,Qt::Checked); // 第一列勾选
    item->setData(MainWindow::colItem,Qt::UserRole,QVariant(dataStr)); //?
    ui->treeWidget->addTopLevelItem(item);// 添加顶层节点

}
  • QTreeWidget的每个节点都是一个QTree WidgetItem对象,添加一个节点前需先创建它,并做好相关设置。
  • setData()函数为节点的某一列设置一个角色数据,setData()函数原型为:void() TreeWidgetItem::setData(int column,int role,const QVariant &value)

item->setData(MainWindow:colItem,Qt::UserRole,QVariant (datastr));

它为节点的第1列,角色Qt:UserRole,设置了一个字符串数据dataStr.Qt:UserRole是枚举类型Qt:ItemDataRole中一个预定义的值。

17.5 添加目录节点

定义3个函数

// 获取文件名称
QString MainWindow::getFinalFolderName(const QString &fullPathName)
{
    return fullPathName.right(fullPathName.length()-fullPathName.lastIndexOf("/")-1);
}
// 添加节点函数
void MainWindow::addFolderItem(QTreeWidgetItem *parItem, QString dirName)
{
    QIcon icon(":/icons/icons/open3.bmp");
    QString NodeText = getFinalFolderName(dirName);

    QTreeWidgetItem *item = new QTreeWidgetItem(MainWindow::itGroupItem); // 传入目录的节点类型type值1001
    item->setIcon(colItem,icon);
    item->setText(colItem,NodeText);
    item->setText(colItemType,"type:itGroupItem");
    item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsAutoTristate | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
    item->setCheckState(colItem,Qt::Checked);
    item->setData(colItem,Qt::UserRole,QVariant(dirName));
    parItem->addChild(item); // 在父节点添加子节点
}
// action关联函数
void MainWindow::on_actAddFolder_triggered()
{
    QString fullname = QFileDialog::getExistingDirectory();
    if(!fullname.isEmpty()){
        QTreeWidgetItem *parItem = ui->treeWidget->currentItem();
        if(parItem){
            addFolderItem(parItem,fullname);
        }else {
            // 创建弹窗
            QMessageBox::critical(this, tr("危险弹窗"),  tr("请选择目标节点"),QMessageBox::Save | QMessageBox::Discard,  QMessageBox::Discard);
        }
    }
    else {
         return;
    }

}

17.6 添加图片节点

QFileDialog::getOpenFileNames函数可以实现添加多个文件

实现:

  1. 创建临时变量parItem和item;
  2. parItem用于最终的添加目标,item存放当前节点;
  3. 如果当前节点是文件节点或者顶层节点,则目标节点是当前节点;
  4. 如果当前节点是图片节点,则目标节点是图片节点的父节点(图片节点为末尾节点,后面不能添加子节点);
  5. 使用for循环分别获取文件的名称,并添加到目标节点下;
void MainWindow::addImageItem(QTreeWidgetItem *parItem, QString aFilename)
{
    QIcon icon(":/icons/icons/31.ico");
    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::ItemIsAutoTristate | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
    item->setData(colItem,Qt::UserRole,QVariant(aFilename));
    parItem->addChild(item); // 在父节点添加子节点
}
void MainWindow::on_actAddFiles_triggered()
{
    QStringList files = QFileDialog::getOpenFileNames(this,"选择一个或者多个文件","","Images(*.jpg)");
    if(files.isEmpty())
        return;

    QTreeWidgetItem *parItem,*item;
    item = ui->treeWidget->currentItem();
    if(item){
        if(item->type()==itImageItem) // 当前节点是图片节点
            parItem = item->parent();
        else {
            parItem=item;
        }
        for (int i = 0;i

17.7 当前节点发生变化响应

QTreeWidget会发出currentItemChanged信号

实现:

  1. 获取当前节点的类型;
  2. 判断当前选中的节点属于哪个类型;
  3. 根据类型设置添加、删除等按钮的状态;
  4. 如果为图片节点,调用图片显示函数;

代码实现:

void MainWindow::on_treeWidget_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);
            ui->actZoomFitH->setEnabled(true);
            ui->actZoomFitW->setEnabled(true);
            ui->actZoomIn->setEnabled(true);
            ui->actZoomOut->setEnabled(true);
            ui->actZoomRealSize->setEnabled(true);
            displayImage(current);
            break;
        }
}

17.8 删除节点

删除节点使用QTreeWidgetItem对象上的removeChild函数

实现:

  1. 获取当前节点;
  2. 获取当前节点的父节点;
  3. 从父节点中删除子节点;

代码实现:

void MainWindow::on_actDeleteItem_triggered()
{
    QTreeWidgetItem *item = ui->treeWidget->currentItem();
    QTreeWidgetItem *parItem = item->parent();
    parItem->removeChild(item);
    delete item; // 删除子节点的内存空间。removveChild只能从父节点中删除子节点,但不能移除子节点的内存空间。
}

17.9 遍历节点

使用递归调用

int topLevelItemCount():返回顶层节点个数。
QTree WidgetItemtopLevelItem(int index):返回序号为index的顶层节点。

int topLevelItemCount():返回顶层节点个数。
QTree WidgetItem*topLevelItem(int index):返回序号为index的顶层节点。

实现:

  1. 获取全部的顶层节点,遍历更改;
  2. 更改每个节点后,获取全部子节点并更改;

代码实现:

void MainWindow::on_actScanItems_triggered()
{
    int cnt = ui->treeWidget->topLevelItemCount();
    for(int i = 0;itreeWidget->topLevelItem(i); // 顶层节点
        changeItemCaption(item); // 调用【更改节点标题】函数
    }
}
void MainWindow::changeItemCaption(QTreeWidgetItem *item)
{
    // 节点标题前加*
    QString str = "*" + item->text(colItem);
    item->setText(colItem,str);

    if(item->childCount()>0){
        for (int i = 0;ichildCount();i++) {
            changeItemCaption(item->child(i));
        }
    }
}

17.10 显示节点的图片

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

实现:

  1. 获取存入的文件名称并在状态栏显示名称;
  2. 调用QPixmap下的load函数载入图片;
  3. 自适应高度显示图片;

这里还显示不了,还未写自适应高度显示action;

void MainWindow::displayImage(QTreeWidgetItem *item)
{
    QString filename = item->data(colItem,Qt::UserRole).toString(); // 获取文件名,之前用setData存的数据
    LabFileName->setText(filename); // 状态栏显示图片名称
    curPixmap.load(filename); // 当前图片
    on_actZoomFitH_triggered(); // 自适应高度显示
}

17.11 图片显示与缩放

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

  • QPixmap scaledToHeight(int height):返回一个缩放后的图片的副本,图片缩放到一个高度height.
  • QPixmap scaledTo Width(int width):返回一个缩放后的图片的副本,图片缩放到一个宽度width.
  • QPixmap scaled(int width,.int height):返回一个缩放后的图片的副本,图片缩放到宽度width和高度height,缺省为不保持比例。

变量curPixmap保存了图片的原始副本,要缩放只需调用curPixmap的相应函数,返回缩放后的图片副本。在界面上的一个标签LabPicture上显示图片,使用了QLabel的setPixmap(const QPixmap&)函数。

void MainWindow::on_actZoomFitH_triggered()
{
    // 自适应高度显示
    int H = ui->scrollArea->height(); // 获取当前滑动块的高度
    int realH = curPixmap.height(); // 获取当前图片的高度
    pixRatio = float(H)/realH; // 当前图片显示的比例(必须是浮点数)
    QPixmap pix = curPixmap.scaledToHeight(H-30); // 图片缩放指定高度
    ui->label->setPixmap(pix); // label标签显示图片
}

void MainWindow::on_actZoomFitW_triggered()
{
    // 自适应宽度显示
    int W = ui->scrollArea->width(); // 获取当前滑动块的高度
    int realW = curPixmap.width(); // 获取当前图片的高度
    pixRatio = float(W)/realW; // 当前图片显示的比例(必须是浮点数)
    QPixmap pix = curPixmap.scaledToWidth(W-30); // 图片缩放指定高度
    ui->label->setPixmap(pix); // label标签显示图片
}

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_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);
}

17.12 dockWidget

只写action按钮的动作,手动拖动dockWidget时按钮的状态不会改变,需要使用dockWidget上的信号;

隐藏发射信号visibilityChanged(bool)
浮动、停靠信号topLevelChanged(bool)

void MainWindow::on_actDockVisible_toggled(bool arg1)
{
    ui->dockWidget->setVisible(arg1);
}

void MainWindow::on_actDockFloat_toggled(bool arg1)
{
    ui->dockWidget->setFloating(arg1);
}

void MainWindow::on_dockWidget_topLevelChanged(bool topLevel)
{
    ui->actDockFloat->setChecked(topLevel);
}

void MainWindow::on_dockWidget_visibilityChanged(bool visible)
{
    ui->actDockVisible->setChecked(visible);
}

你可能感兴趣的:(Qt,qt,ui,c++,qt5)