В mainwindow.ui
я создал QProgressBar
с именем progressBar
и QPushButton
с именем speckle
, который запускает тяжелые вычисления.
Внутри mainwindow.h
у меня есть соответствующий private slot
для кнопки и частная функция, которая представляет тяжелые вычисления. mainwindow.h
:
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_speckle_clicked();
...
private:
Ui::MainWindow *ui;
QFutureWatcher<std::vector<cv::Mat>> futureWatcher;
std::vector<cv::Mat> progressSpecle();//heavy computation
};
Предполагается, что futureWatcher
отслеживает объект QFuture
, возвращаемый QtConcurrent
:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
...
connect(&this->futureWatcher, SIGNAL(progressValueChanged(int)), ui->progressBar, SLOT(setValue(int)));
...
}
...
void MainWindow::on_speckle_clicked()
{
//Start the computation.
QFuture<std::vector<cv::Mat>> future;
future = QtConcurrent::run(this, &MainWindow::progressSpecle);
this->futureWatcher.setFuture(future);
QThreadPool::globalInstance()->waitForDone();
vector<cv::Mat> result = future.result();
specklevisualization *s = new specklevisualization;
s-> setAttribute(Qt::WA_DeleteOnClose);
s-> start(result);
s-> show();
}
Но приложение так не работает. После компиляции и нажатия пятна mainwindow
не отвечает. Вот функция-член progressSpecle
, в которой создается x потоков:
void MainWindow::progressSpecle(){
vector<cv::Mat> input;
...//do something with input
vector<cv::Mat> result;
vector<cv::Mat> *all;
all = &result;
QThreadPool *threadPool = QThreadPool::globalInstance();
for(unsigned int i = 1; i<input.size(); i++) {
cv_speckle_algorithm *work = new cv_speckle_algorithm(input.at(i-1), input.at(i), all, i-1);
work->setAutoDelete(false);
threadPool->start(work);
}
while(true){
if(threadPool->activeThreadCount() == 1) return result;
}
}
Приложение работает без ошибок, но mainWindow не виноват, потому что (я думаю) while(true)
. Но я не понимаю, почему это должно блокировать mainWindow, потому что вся функция progressSpecle
работает в отдельном потоке, созданном и начатом с QtConcurrent
.
Почему функция progressSpecle
блокирует mainWindow? Итак, как я могу заставить progressBar
работать?
specklevisualization
каким-либо образом наследуется отQWidget
, вы не можете создать его экземпляр в потоке без графического интерфейса. - person G.M.   schedule 20.02.2017progressSpecle
, чтобы она возвращала векторresult
. - person goulashsoup   schedule 20.02.2017QApplication a(argc, argv);
доMainWindow m; m.show();
? Тогда да. НетQObject::connect()
не печатает ошибки. Почему? Ошибки нет, но mainWindow не отвечает... Я обновил вопрос, чтобы стало ясно, какая у меня проблема.... - person goulashsoup   schedule 20.02.2017on_speckle_clicked
вызывается в потоке GUI, но блокируется при вызовеQThreadPool::waitForDone
— это не сработает. Также каждому вновь созданномуcv_speckle_algorithm
передается ссылка наresults
, намекая на то, что несколько потоков будут одновременно писать вresults
. Это, безусловно, проблема. Могу ли я предложить вам сначала забыть оQThreadPool
и заставить базовые алгоритмы работать в однопоточном режиме, а затем посмотреть на использование `QThreadPool. - person G.M.   schedule 20.02.2017cv_speckle_algorithm
, но ваше опасение, что несколько потоков будут одновременно записывать результаты, верно, и я думаю, что иногда это приводит к ошибке, поэтому я обязательно вернусь к этой проблеме... Спасибо - person goulashsoup   schedule 20.02.2017