Reputation: 21
I'm trying to monitor changes in a folder using QFileSystemWatcher, and whenever changes happen they will be reflected in the GUI.
The idea is that I have a folder that gets updated every second with new images, and I need to display those images in sequence
nevertheless, the changes happen very fast, and the GUI freezes.
how can I make this line run in a different thread whenever there's a change in the folder.
QObject::connect(&watcher, SIGNAL(directoryChanged(QString)), w, SLOT(showModified(QString)));
or how can I make the code that creates reflections on the GUI run in a separate thread?
Upvotes: 0
Views: 116
Reputation: 2479
To make QFileSystemWatcher
work in a separate thread you can do:
Create new thread - auto thread = new QThread;
Create new file system watcher - auto watcher = new QFileSystemWatcher;
Move watcher
to thread
- watcher->moveToThread(thread);
Make connections
connect(thread, &QThread::finished, watcher, &QObject::deleteLater);
connect(thread, &QThread::finished, thread, &QObject::deleteLater);
connect(watcher, &QFileSystemWatcher::directoryChanged, w, &<YourWidgetClassName>::showMidified, Qt::QueuedConnection);
Start thread thread->start();
Setup watcher
with addPath
or addPaths
Do not forget call thread->quit();
when it's not needed or before application exits
So about problem of bunch images rendering in GUI.
I suggest you to use QImage
to load and scale images for QPixmap
to be created and rendered in GUI. Here QtConcurrent::run
can be used per image to preform an image loading in a separate thread. It returns a QFuture
object, that can be tracked with a QFutureWatcher
object, that emits a finished
signal, when a watched future is complete. Once connected to a QFutureWatcher::finished
signal you can handle QFuture
's result to assign a loaded QImage
to QPixmap
.
So, you need a code like this for QFileSystemWatcher::directoryChanged
signal handler:
QStringList filenames = <some code to get new image filenames to render>;
auto loadImage = [](const QString &aFilename) -> QPixmap {
auto image = QImage(aFilename).scaled(200, 200, Qt::KeepAspectRatio, Qt::SmoothTransformation);
return QPixmap::fromImage(image);
};
for (auto &filename : filenames) {
auto pixmap = QPixmap(200, 200); //create empty pixmap of desired size
auto label = new QLabel;
label->setPixmap(pixmap);
m_layout->addWidget(label);
auto future = QtConcurrent::run(loadImage, filename);
auto watcher = new QFutureWatcher<QPixmap>(this);
connect(watcher, &QFutureWatcher<QPixmap>::finished, this, [watcher, label]() { label->setPixmap(watcher->result()); });
connect(watcher, &QFutureWatcher<QPixmap>::finished, watcher, &QFutureWatcher<QPixmap>::deleteLater);
watcher->setFuture(future);
}
Upvotes: 1