Зависает GUI при изменении QProgressBar из QThread с помощью сигналов.
Код:
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QFileDialog>
#include <QThread>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
public slots:
private slots:
void on_pushButton_1_clicked();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
#include "widget.h"
#include "worker.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButton_1_clicked()
{
QString filename = QFileDialog::getOpenFileName(
this,
"Открыть файл",
"",
"Все файлы (*.*)",
nullptr,
QFileDialog::DontUseNativeDialog
);
if (filename != QString("")) {
ui->label_2->setText(filename);
QThread *thread = new QThread;
Worker *worker = new Worker(filename);
worker->moveToThread(thread);
connect(thread, &QThread::started, worker, &Worker::process);
connect(worker, &Worker::finished, thread, &QThread::quit);
connect(worker, &Worker::finished, worker, &QObject::deleteLater);
connect(thread, &QThread::finished, thread, &QObject::deleteLater);
connect(worker, &Worker::progressRangeChanged, ui->progressBar, &QProgressBar::setRange);
connect(worker, &Worker::progressValueChanged, ui->progressBar, &QProgressBar::setValue);
thread->start();
}
}
#ifndef WORKER_H
#define WORKER_H
#include <QObject>
#include <QDebug>
#include <QFile>
#include <QThread>
class Worker : public QObject
{
Q_OBJECT
QString workerFilename;
public:
explicit Worker(QString filename, QObject *parent = nullptr);
virtual ~Worker();
signals:
void finished();
void error(QString err);
void progressRangeChanged(int min,int max);
void progressValueChanged(int progress);
public slots:
void process();
};
#endif // WORKER_H
#include "worker.h"
Worker::Worker(QString filename, QObject *parent) : QObject(parent)
{
workerFilename = filename;
}
Worker::~Worker()
{
}
void Worker::process()
{
// qDebug()<<workerFilename;
QFile file(workerFilename);
int fileSize = file.size();
emit progressRangeChanged(0, fileSize);
for (int i = 0; i <= fileSize; i++) {
emit progressValueChanged(i);
}
emit finished();
}
QProgressBar обновляется. GUI виджета зависают, окно нельзя переместить.
Подскажите, пожалуйста, в чем ошибка.
Эта задача достаточно типичная. Давайте представим, что в файле миллион строк (а иначе зачем вообще нужно было бы отображать прогресс?) И на каждую строку будет делать обновление прогресса (что бы пользователь его видел). Самые ходовые мониторы сейчас - это fullhd и им подобные, которые имеют 1920 точек по ширине. Так как полоса прогресса вряд ли будет занимать весь экран, я думаю, 1000 пикселей удобное число и вполне реальное для ширины самого прогресса.
А теперь вопрос. Увидит ли пользователь разницу между 9000 и 9500 итеррацией цикла? Нет, не увидит. Потому что обе будут занимать 9 (или 10) пикселей ширины полосы. Если посидеть помедитировать, то станет ясно, что обновлять чаще, чем раз в 1000 итерраций нет смысла (1000 это 1000000 строк файле на 1000 пикселей ширины экрана).
По собственному опыту скажу, что на самом деле можно обновлять раз в 5-10 пикселей и пользователь будет счастлив.
Как это исправить самым простым способом?
Вместо
emit progressValueChanged(i);
написать строку вот так
if (i % 1000 == 0) {
emit progressValueChanged(i);
}
вместо 1000 лучше подставить свою константу, которая должна быть не меньше, чем fileSize деленный на ширину прогресса (а оптимально - ещё и умножить на 5-10).
И самое главное, не забыть в самом конце добавить строку, которая подвинет прогресс в самый конец (на 100%). А то тут как повезет (если кол-во записей будет кратно 1000, то добежит, а иначе нет).
Виртуальный выделенный сервер (VDS) становится отличным выбором
Здравствуйте! Пытаюсь установить YouCompleteMe для подсказок в Vim
На веб странице имеется JQuery sortable списокТакже добавил на страницу jQuery UI Touch Punch для поддержки сенсорных экранов
Как посредством JS/jQuery преобразовать число в элементе? Например, 350 умножить на 057 и заменить $ на руб