How to use the threads to create the images thumbnail

梦想的初衷 提交于 2019-12-22 08:53:07

问题


I'm use QTreeView to get the images path, then I'm use QListView to display the images that in specific path as thumbnail.

The problem in the period, create and display the thumbnail images.
The previous process, take a long time to done, depend on the number of images.
And for that reason I decided to use the threads, maybe helps to prevent the hung up which occur in application and increase the speed of create and display the thumbnail images.

void mainWidget::on_treeView_clicked(const QModelIndex &index){
    filesModel->clear();
    QFileSystemModel *sysModel = qobject_cast<QFileSystemModel*>(ui->treeView->model());
    QDir dir(sysModel->filePath(ui->treeView->currentIndex()));
    QFileInfoList filesList = dir.entryInfoList(QStringList() << "*.jpg" << "*.jpeg" << "*.tif" << "*.png" << "*.gif" << "*.bmp" ,QDir::Files);
    int filesCount = filesList.size();
    for(int i=0;i<filesCount;i++){
        QPixmap originalImage(filesList[i].filePath());
        if(!originalImage.isNull()){
            QPixmap scaledImage = originalImage.scaled(150, 120);    
            filesModel->setItem(i, new QStandardItem(QIcon(scaledImage), filesList[i].baseName()));
        }
    }
}

How can I use threads with the previous code ?


回答1:


I believe that a simple and correct approach is using QtConcurrent as the following:

Note: If you are using Qt 5 you will need to add QT += concurrent to the .pro file.

Header:

#include <QtCore>
#include <QtGui>
#include <QtWidgets>
#include <QtConcurrent>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

signals:
    void UpdateItem(int, QImage);

private slots:
    void on_treeView_clicked(const QModelIndex &);
    void List(QFileInfoList filesList, QSize size);
    void setThumbs(int index, QImage img);

private:
    Ui::MainWindow *ui;
    QFileSystemModel *model;
    QStandardItemModel *filesmodel;
    QFuture<void> thread;
    bool running;
};

CPP file:

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

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QThreadPool::globalInstance()->setMaxThreadCount(1);

    model = new QFileSystemModel(this);
    model->setRootPath("\\");

    filesmodel = new QStandardItemModel(this);

    ui->treeView->setModel(model);
    ui->listView->setModel(filesmodel);

    connect(this, SIGNAL(UpdateItem(int,QImage)), SLOT(setThumbs(int,QImage)));

    ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);

    running = false;
}

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

void MainWindow::on_treeView_clicked(const QModelIndex&)
{
    filesmodel->clear();

    running = false;

    thread.waitForFinished();

    QDir dir(model->filePath(ui->treeView->currentIndex()));

    QFileInfoList filesList = dir.entryInfoList(QStringList() << "*.jpg" << "*.jpeg" << "*.tif" << "*.png" << "*.gif" << "*.bmp", QDir::Files);

    int filesCount = filesList.size();

    QPixmap placeholder = QPixmap(ui->listView->iconSize());
    placeholder.fill(Qt::gray);

    for (int i = 0; i < filesCount; i++)
        filesmodel->setItem(i, new QStandardItem(QIcon(placeholder), filesList[i].baseName()));

    running = true;

    thread = QtConcurrent::run(this, &MainWindow::List, filesList, ui->listView->iconSize());
}

void MainWindow::List(QFileInfoList filesList, QSize size)
{
    int filesCount = filesList.size();

    for (int i = 0; running && i < filesCount; i++)
    {
        QImage originalImage(filesList[i].filePath());
        if (!originalImage.isNull())
        {
            QImage scaledImage = originalImage.scaled(size);
            if (!running) return;
            emit UpdateItem(i, scaledImage);
        }
    }
}

void MainWindow::setThumbs(int index, QImage img)
{
    QIcon icon = QIcon(QPixmap::fromImage(img));
    QStandardItem *item = filesmodel->item(index);
    filesmodel->setItem(index, new QStandardItem(icon, item->text()));
}



回答2:


You don't have to use threads to keep your application responsive in this case. Use QCoreApplication::processEvents() in the loop to keep the application responsive. QCoreApplication::processEvents() will process all the events in the event queue of the thread which calls it.




回答3:


This is an older thread, but still comes up in Google. Check out the answer to this related question. I found the use of QIdentityProxyModel to be a bit more elegant, as it allowed QFileSystemModel to be used as the list view's model.



来源:https://stackoverflow.com/questions/26829754/how-to-use-the-threads-to-create-the-images-thumbnail

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!