0

My mainwindow have a side GUI with a QGraphicsView in the center, there is a logic class which make different calculations which triggered by the GUI and effects the QGraphicsView. Some of the calculations are heavy which make the GUI go to sleep, there is a QProgressBar and some other Qt items which provides some data while the calculations are been made, so when the GUI process goes to sleep those items show there updated result only when the process has finished. I understand that it because the logic class and the UI are under the same process,

I was trying to correct this by doing: My old question and Maya's Programming Blog

But I came to understanding that both are not sufficient to my code as I have several methods that run heavy calculations and some of them returning values. Both talking about doing something like this: connect(thread, SIGNAL(started()), worker, SLOT(process()));... than thread->start();, but in my code there is no single main process, so if I want to work in that way, from what I understand I need to create a thread before each process method, move the logic class to this thread and than connect the process method with the thread start method, which not sounds to me as the proper way to do this.

So I ask for a way to fully separate the logic layer from the view layer, so any method which invoked the logic layer will run on a different process (which is the same for all logic class methods), so the view layer won't go to sleep.

Note: there is no problems of synchronicity, when a calculation been made it's the only one which work at a time.

An example of my problem:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "Logic/worker.h"

namespace Ui {
class MainWindow;
#define MAXLOOP 1000000
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

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


signals:


private slots:

    void startProcessing1();

    void processing1Done();

    void on_pushButton_exit_clicked();

private:
    Ui::MainWindow *ui;

};

#endif // MAINWINDOW_H

/////////////////////////////////////////////////////////////////////////////////

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

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

    ui->progressBar_1->setVisible(false);
    ui->progressBar_1->setMaximum(MAXLOOP);
    ui->progressBar_1->setMinimum(0);

    connect(ui->pushButton_1, SIGNAL(clicked()), this, SLOT(startProcessing1()));
}

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

void MainWindow::startProcessing1()
{
    ui->progressBar_1->setVisible(true);

    Worker *worker = new Worker(MAXLOOP);
    QThread* thread = new QThread;
    worker->moveToThread(thread);
    connect(worker, SIGNAL(finished1Hide()), this, SLOT(processing1Done()));
    connect(worker, SIGNAL(changePbar1(int)), ui->progressBar_1, SLOT(setValue(int)));

    connect(thread, SIGNAL(started()), worker, SLOT(process1()));

    connect(worker, SIGNAL(finished1()), thread, SLOT(quit()));
    connect(worker, SIGNAL(finished1()), worker, SLOT(deleteLater()));
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));

    thread->start();
}

void MainWindow::processing1Done()
{
    ui->progressBar_1->setVisible(false);
}

void MainWindow::on_pushButton_exit_clicked()
{
    this->close();
}

/////////////////////////////////////////////////////////////////////////////////

#ifndef WORKER_H
#define WORKER_H

#include <QObject>

class Worker : public QObject
{
    Q_OBJECT
public:
    explicit Worker(int maxLoop, QObject *parent = 0);

signals:

    void finished1();
    void finished1Hide();
    void changePbar1(int val);

public slots:

    void process1();

private:

    int m_maxLoop;
};

#endif // WORKER_H

/////////////////////////////////////////////////////////////////////////////////

#include "worker.h"

Worker::Worker(int maxLoop, QObject *parent) :
    QObject(parent)
{
    m_maxLoop = maxLoop;
}

void Worker::process1()
{
    int sum = 0;
    for(int i = 0; i < m_maxLoop; ++i)
    {
        emit changePbar1(i);
        sum += i;
    }
    emit finished1();
    emit finished1Hide();
}
Community
  • 1
  • 1
GoldenAxe
  • 838
  • 3
  • 9
  • 26
  • You have an answer in tags (the third))) – borisbn Mar 16 '13 at 10:22
  • But I have tried qthread, it didn't worked because I don't have one main process but many – GoldenAxe Mar 16 '13 at 12:16
  • I have changed my example to a real one, which show that even with one thread and only one connected process the mainwindow (GUI) go to sleep – GoldenAxe Mar 16 '13 at 16:43
  • `m_worker->moveToThread(thread);` doesn't force worker's code to run in separate thread. You should subclass QThread and call worker's function in overloaded `run` method – borisbn Mar 16 '13 at 21:36
  • I read subclass QThread is not the way to do this, I could connect the thread start signal to process1 slot but I think it will have to be done for each process(1,2...) and it's sounds messy – GoldenAxe Mar 16 '13 at 22:07
  • You're right. Connecting to thread start signal is more proper way, but I can't see it in your code – borisbn Mar 17 '13 at 06:13
  • I change the example to a minimum example including using of thread start signal, and the GUI is still sleeping, although from my understanding the worker thread is in a different thread from the mainwindow – GoldenAxe Mar 17 '13 at 14:49

0 Answers0