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); }
虽然没有太多文字描述实现思路,但是代码中展示的思路还是比较清晰的,唯一一个地方比较难理解的就是使用正则表达式的那个地方
运行效果图
希望你也能分享你的知识,谢