GUI Freeze in loop
-
Hello.
I have a loop in my code for reading a .txt file. When reading that file the GUI freezes, i tried
QCoreApplication::processEvents();
But it still freezes. Can someone give me a tip on how to run this on a separate thread or something like this?
if (!file.open(QIODevice::ReadOnly)) { qDebug() << file.errorString(); ui->textBrowser->append(file.errorString()); } while (!file.atEnd()) { QByteArray line = file.readLine(); wordList.append(line.split(',').first()); // QCoreApplication::processEvents(); }
Thanks.
-
Hi
Im a bit surprised it still lagged with processEvents()Anyway, you can use a worker object and run that in a thread.
It can then emit signal to tell main its finished. -
@jemazter Yea you definitely want your heavy non GUI operations in their own threads. This will keep your GUI responsive even under load.
Qt makes this quite easy (well as easy as threading ever can be) and mrjj sent ya a link to that.
If you need help with the threading or don't understand the docs, let me know and I can show you an example.
-
Hi. If you can show some examples i would appreciate it, i read the documentation but still didn't understand it quite well.
-
@jemazter Ok here is a fully working example... Please note that the thread will create a 1GB file in order to cause enough delay so you can see the GUI is still responsive. It is called deleteme.txt. Make sure to clean it up. :)
TEMPLATE = app TARGET = tmp INCLUDEPATH += . QT += gui widgets # Input HEADERS += window.h worker.h SOURCES += main.cpp window.cpp worker.cpp
main.cpp:
#include <QApplication> #include "window.h" int main(int ac, char **av) { QApplication app(ac, av); Window w; w.show(); return app.exec(); }
window.h:
#ifndef window_h #define window_h #include <QWidget> class QProgressBar; class QPushButton; class Window : public QWidget { Q_OBJECT public: Window(QWidget *parent=0); virtual ~Window(); private: void startProgress(); QProgressBar *pb_; QPushButton *button_; private slots: void threadDone(bool success); }; #endif
window.cpp:
#include "window.h" #include <QPushButton> #include <QTextEdit> #include <QVBoxLayout> #include <QThread> #include <QProgressBar> #include <QMessageBox> #include "worker.h" Window::Window(QWidget *parent) : QWidget(parent) { // set up our gui auto layout = new QVBoxLayout(); button_ = new QPushButton("Start Thread"); auto textEdit = new QTextEdit(); // this is here to type in while the thread run s to test responsiveness pb_ = new QProgressBar(); layout->addWidget(textEdit); layout->addWidget(pb_); layout->addWidget(button_); setLayout(layout); // set up the thread for our worker and move it to the thread auto worker = new Worker(); auto thread = new QThread(); worker->moveToThread(thread); // starts writing a file when start thread is clicked connect(button_, &QPushButton::clicked, worker, &Worker::doSomething); // starts a progress bar and disables start thread button connect(button_, &QPushButton::clicked, this, &Window::startProgress); // tells our window here that our thread is done connect(worker, &Worker::finished, this, &Window::threadDone); // cleans up memory connect(worker, &Worker::finished, thread, &QThread::quit); connect(worker, &Worker::finished, worker, &Worker::deleteLater); connect(worker, &Worker::finished, thread, &QThread::deleteLater); thread->start(); } Window::~Window() { } void Window::threadDone(bool success) { // stop progress bar pb_->setMaximum(100); pb_->setValue(100); if (success) QMessageBox::information(this, "Result", "Success!"); else QMessageBox::information(this, "Result", "Failure!"); } void Window::startProgress() { // disable our start button button_->setEnabled(false); // set our progress bar to "busy" mode pb_->setMinimum(0); pb_->setMaximum(0); }
worker.h:
#ifndef worker_h #define worker_h #include <QObject> class Worker : public QObject { Q_OBJECT public: Worker(); public slots: void doSomething(); signals: void finished(bool success); }; #endif
worker.cpp:
#include "worker.h" #include <QFile> Worker::Worker() { } void Worker::doSomething() { // write a 1000MB file byte by byte // that should take long enough to test this QFile f("deleteme.txt"); if (!f.open(QIODevice::Text | QIODevice::WriteOnly)) { // we failed.. emit finished(false); } auto size = 1024*1000000; for (auto i=0;i<size;++i) { f.write("1"); } f.close(); emit finished(true); }
Hope that helps, let me know if you need any part explained. :)
-
@ambershark said in GUI Freeze in loop:
Hi, i am facing same problem..i tried ur example but startProgress() is not getting emitted on clicked() ? any suggestion