Qt 实现的简易本地图片浏览器

在做项目的时候,记录一些小功能模块,这是在开发视频平台的时候,需要写的一个模块(本地图片浏览)

需要用的技术点:

1、文件过滤(支持模糊搜索),使用Qt内置正则

2、图片加载显示

3、信号和槽

 

将文件模糊搜索列表和显示图像分别封装成各自的widget类

直接上代码:

searchfilter.h

#ifndef SEARCHFILTER_H
#define SEARCHFILTER_H

#include <QWidget>

class QLineEdit;
class QListView;
class QStringListModel;
class QSortFilterProxyModel;
class QItemSelection;

class SearchFilter : public QWidget
{
    Q_OBJECT
public:
    explicit SearchFilter(QWidget *parent = 0);
    void Init(const QString &dir_str, const QStringList &filter_list);
    void SetCurrentSelectFile_Prev();
    void SetCurrentSelectFile_Next();
    
signals:
    //发送当前选中的文件名
    void signal_current_select_file(const QString& file_name);
    
private slots:
    void textChanged_input_edit(const QString& text);
    void onDoubleClick_listView(const QModelIndex& index);
    void selectChanged_listView(const QItemSelection& selection);
    
private:
    QString m_dir_str;
    QLineEdit* m_input_edit;
    QListView* m_file_list_view;
    QStringListModel* m_string_list_model;
    QSortFilterProxyModel* m_proxy_model;
};

#endif // SEARCHFILTER_H

searchfilter.cpp

#include "searchfilter.h"
#include <QVBoxLayout>
#include <QLineEdit>
#include <QListView>
#include <QDir>
#include <QStringListModel>
#include <QSortFilterProxyModel>
#include <QMessageBox>
#include <QDebug>

SearchFilter::SearchFilter(QWidget *parent) : QWidget(parent)
{
    //输入框
    m_input_edit = new QLineEdit();
    m_input_edit->setMinimumHeight(35);
    //文件列表
    m_file_list_view = new QListView();
    
    m_string_list_model = new QStringListModel();
    m_proxy_model = new QSortFilterProxyModel();
    
    QVBoxLayout* main_layout = new QVBoxLayout();
    main_layout->addWidget(m_input_edit);
    main_layout->addWidget(m_file_list_view);
    
    this->setLayout(main_layout);
    
    connect(m_input_edit, SIGNAL(textChanged(QString)), this, SLOT(textChanged_input_edit(QString)));
    connect(m_file_list_view, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(onDoubleClick_listView(QModelIndex)));
    
//这里绑定了选中变化时发生事件 connect(m_file_list_view
->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(selectChanged_listView(QItemSelection))); } //设置搜索过滤目录和文件后缀 void SearchFilter::Init(const QString &dir_str, const QStringList &filter_list) { m_dir_str = dir_str; QDir* dir = new QDir(dir_str); dir->setNameFilters(filter_list); QStringList file_list = dir->entryList(); m_string_list_model->setStringList(file_list); m_proxy_model->setSourceModel(m_string_list_model); m_file_list_view->setModel(m_proxy_model); m_file_list_view->setEditTriggers(QAbstractItemView::NoEditTriggers); //设置当前选中行 0行 0列 QModelIndex index = m_proxy_model->index(0, 0); m_file_list_view->setCurrentIndex(index); } //选上一个 void SearchFilter::SetCurrentSelectFile_Prev() { QModelIndex curr_index = m_file_list_view->currentIndex(); int curr_row = curr_index.row(); if (curr_row == 0) { QMessageBox::information(this, tr("提示"), tr("前面没有了"), QMessageBox::Ok); return ; } curr_row = curr_row - 1; curr_index = m_proxy_model->index(curr_row, 0); m_file_list_view->setCurrentIndex(curr_index); //当前选中 curr_index = m_file_list_view->currentIndex(); QString picture_name = curr_index.data().toString(); QString picture_path = m_dir_str + picture_name; emit signal_current_select_file(picture_path); } //选中下一个 void SearchFilter::SetCurrentSelectFile_Next() { QModelIndex curr_index = m_file_list_view->currentIndex(); int curr_row = curr_index.row(); int rows = m_proxy_model->rowCount(); if (curr_row == (rows - 1)) { QMessageBox::information(this, tr("提示"), tr("后面没有了"), QMessageBox::Ok); return ; } curr_row = curr_row + 1; curr_index = m_proxy_model->index(curr_row, 0); m_file_list_view->setCurrentIndex(curr_index); //当前选中 curr_index = m_file_list_view->currentIndex(); QString picture_name = curr_index.data().toString(); QString picture_path = m_dir_str + picture_name; emit signal_current_select_file(picture_path); } //QLineEdit输入发生变化事件 void SearchFilter::textChanged_input_edit(const QString &text) { //正则方式 QRegExp::PatternSyntax syntax = QRegExp::PatternSyntax( QRegExp::FixedString); QRegExp regExp(text, Qt::CaseInsensitive, syntax); m_proxy_model->setFilterRegExp(regExp); } //listview双击事件 void SearchFilter::onDoubleClick_listView(const QModelIndex &index) { QString picture_name = index.data().toString(); QString picture_path = m_dir_str + picture_name; emit signal_current_select_file(picture_path); } //选中发生变化时 不知道为什么这里没有触发(如果哪位前辈知道原因,指导一下) void SearchFilter::selectChanged_listView(const QItemSelection &selection) { QModelIndex index = m_file_list_view->currentIndex(); QString picture_name = index.data().toString(); QString picture_path = m_dir_str + picture_name;
  emit signal_current_select_file(picture_path);
}

图片显示类:

imageviewer.h

#ifndef IMAGEVIEWER_H
#define IMAGEVIEWER_H

#include <QWidget>
#include <QImage>

class QLabel;
class QScrollArea;
class QPushButton;
class QHBoxLayout;
class QVBoxLayout;
class QScrollArea;

class ImageViewer : public QWidget
{
    Q_OBJECT
public:
    explicit ImageViewer(QWidget *parent = 0);
    
    bool loadFile(const QString& fileName);
    
private:
    void setImage(const QImage &newImage);
    
signals:
    void signal_prev();
    void signal_next();
    
private slots:
    void on_click_btn_zoom_out();
    void on_click_btn_zoom_in();
    void on_click_btn_prev();
    void on_click_btn_next();
    
private:
    void zoomOut();
    void zoomIn();
    void scaleImage(double factor);
    
private:
    double scaleFactor;
    QImage image;
    QLabel* image_label; //显示图片
    QScrollArea* scrollArea;
    
    //主界面layout
    QVBoxLayout* main_layout;
    
    //按钮工具
    QHBoxLayout* tool_layout;
    QPushButton* btn_prev;
    QPushButton* btn_next;
};

#endif // IMAGEVIEWER_H

imageviewer.cpp

#include "imageviewer.h"
#include <QPushButton>
#include <QLabel>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QSpacerItem>
#include <QScrollArea>
#include <QImageReader>

ImageViewer::ImageViewer(QWidget *parent) : QWidget(parent)
{
    image_label = new QLabel();
    image_label->setBackgroundRole(QPalette::Base);
    image_label->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
    image_label->setScaledContents(true);
    
    //scrollArea = new QScrollArea();
    //scrollArea->setBackgroundRole(QPalette::Dark);
    //scrollArea->setWidget(image_label);
    //scrollArea->setVisible(false);
    
    main_layout = new QVBoxLayout(this);
    main_layout->addWidget(image_label);
    
    btn_prev = new QPushButton("上一张");
    //QPushButton* btn_zoom_out = new QPushButton("-");
    //QPushButton* btn_zoom_in = new QPushButton("+");
    btn_next = new QPushButton("下一张");
    
    QSpacerItem* item_left = new QSpacerItem(75, 40, QSizePolicy::Expanding, QSizePolicy::Minimum);
    QSpacerItem* item_right = new QSpacerItem(75, 40, QSizePolicy::Expanding, QSizePolicy::Minimum);
    
    tool_layout = new QHBoxLayout();
    tool_layout->addSpacerItem(item_left);
    tool_layout->addWidget(btn_prev);
    //tool_layout->addWidget(btn_zoom_out);
    //tool_layout->addWidget(btn_zoom_in);
    tool_layout->addWidget(btn_next);
    tool_layout->addSpacerItem(item_right);
    
    main_layout->addLayout(tool_layout);
    
    this->setLayout(main_layout);
    this->setStyleSheet("background-color: rgb(167, 175, 159);");
    
    //connect(btn_zoom_out, SIGNAL(clicked(bool)), this, SLOT(on_click_btn_zoom_out()));
    //connect(btn_zoom_in, SIGNAL(clicked(bool)), this, SLOT(on_click_btn_zoom_in()));
    connect(btn_prev, SIGNAL(clicked(bool)), this, SLOT(on_click_btn_prev()));
    connect(btn_next, SIGNAL(clicked(bool)), this, SLOT(on_click_btn_next()));
}

bool ImageViewer::loadFile(const QString &fileName)
{
    QImageReader reader(fileName);
    reader.setAutoTransform(true);
    const QImage newImage = reader.read();
    
    setImage(newImage);
    
    return true;
}

void ImageViewer::setImage(const QImage &newImage)
{
    image = newImage;
    image_label->setPixmap(QPixmap::fromImage(image));
    
    scaleFactor = 1.0;
}

void ImageViewer::on_click_btn_zoom_out()
{
    zoomOut();
}

void ImageViewer::on_click_btn_zoom_in()
{
    zoomIn();
}

void ImageViewer::on_click_btn_prev()
{
    emit signal_prev();
}

void ImageViewer::on_click_btn_next()
{
    emit signal_next();
}

void ImageViewer::zoomOut()
{
    scaleImage(0.8);
}

void ImageViewer::zoomIn()
{
    scaleImage(1.2);
}

void ImageViewer::scaleImage(double factor)
{
    Q_ASSERT(image_label->pixmap());
    scaleFactor *= factor;
    image_label->resize(scaleFactor * image_label->pixmap()->size());
}

主界面类:

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class ImageViewer;
class SearchFilter;

class MainWindow : public QMainWindow
{
    Q_OBJECT
    
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    
private slots:
    void on_signal_next();
    void on_signal_prev();
    void on_signal_show_image(const QString& picture_path);
    
private:
    Ui::MainWindow *ui;
    
    QString dir_str;  //目录
    
    SearchFilter* m_widget_search_filter;
    ImageViewer* m_widget_image_viewr;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QSortFilterProxyModel>
#include <QStringListModel>
#include <QDir>
#include <QDebug>
#include <QPainter>
#include "searchfilter.h"
#include "imageviewer.h"
#include <QHBoxLayout>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    
    dir_str = "D:\\UserData\\";
    
    QStringList filters;
    filters << "*.bmp";
    
    m_widget_search_filter = new SearchFilter();  //文件浏览
    m_widget_image_viewr = new ImageViewer();  //图片浏览
    
    m_widget_search_filter->setMinimumWidth(421);
    m_widget_search_filter->setMaximumWidth(421);
    
    QHBoxLayout* main_layout = new QHBoxLayout();
    main_layout->addWidget(m_widget_search_filter);
    main_layout->addWidget(m_widget_image_viewr);
    
    QWidget* main_widget = new QWidget(this);
    main_widget->setLayout(main_layout);
    
    this->setCentralWidget(main_widget);
    
    m_widget_search_filter->Init(dir_str, filters);
    
    connect(m_widget_search_filter, SIGNAL(signal_current_select_file(QString)), this, SLOT(on_signal_show_image(QString)));
    connect(m_widget_image_viewr, SIGNAL(signal_next()), this, SLOT(on_signal_next()));
    connect(m_widget_image_viewr, SIGNAL(signal_prev()), this, SLOT(on_signal_prev()));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_signal_next()
{
    m_widget_search_filter->SetCurrentSelectFile_Next();
}

void MainWindow::on_signal_prev()
{
    m_widget_search_filter->SetCurrentSelectFile_Prev();
}

void MainWindow::on_signal_show_image(const QString &picture_path)
{
    m_widget_image_viewr->loadFile(picture_path);
}

 

虽然没有太多文字描述实现思路,但是代码中展示的思路还是比较清晰的,唯一一个地方比较难理解的就是使用正则表达式的那个地方

 

运行效果图

 

希望你也能分享你的知识,谢

posted @ 2017-03-29 16:36  工控之家-Shrek  阅读(9257)  评论(1编辑  收藏  举报