PDA

View Full Version : QFuture and QtConcurrent Problem



aekilic
13th November 2014, 22:41
Dear All

I have problem about my application which is Qt 4.8.1 when using QFuture and QtConcurrent i get error code

QObject::setParent: Cannot set parent, new parent is in a different thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QObject::startTimer: timers cannot be started from another thread
QObject::setParent: Cannot set parent, new parent is in a different thread

And also my application keep crushing unexpectedly. I never know when it going to crush.

I would be so happy is someone can help me.

Here is my code
tryfuture.h


#ifndef TRYFUTURE_H
#define TRYFUTURE_H

#include <QtGui>
#include <QDialog>
#include <QMessageBox>
#include <QTime>
#include <qtconcurrentrun.h>
#include <QThread>

namespace Ui {
class tryfuture;
}

class tryfuture: public QWidget
{
Q_OBJECT
int pagenumber;
public:
explicit tryfuture(QWidget *parent = 0);
~tryfuture();
public slots:
void test1();
void test2();
void test3();
private:
Ui::tryfuture*ui;
};
#endif //


tryfuture.cpp


tryfuture::tryfuture(QWidget *parent) :
QWidget(parent),
ui(new Ui::tryfuture)
{

QTimer *changetimer= new QTimer(this);
connect(changetimer, SIGNAL(timeout()), this, SLOT(changepage()));
changetimer->start(10000);

}

void tryfuture::changepage(){

QFuture<void> future;

switch(pagenumber%3)
{
case 0:
future = QtConcurrent::run(this, &tryfuture::test1);
break;
case 1:
future = QtConcurrent::run(this, &tryfuture::test2);
break;
case 2:
future = QtConcurrent::run(this, &tryfuture::test3);
break;
}

pagenumber++;
}
void tryfuture::test1(){
QMessageBox::information(this, tr("Qt Example 1"),
tr("The function my_func has finished."));
}

void tryfuture::test2(){
QMessageBox::information(this, tr("Qt Example 2"),
tr("The function my_func has finished."));
}
void formUretimBilgiEkrani::test3(){
QMessageBox::information(this, tr("Qt Example 3"),
tr("The function my_func has finished."));
}

wysota
14th November 2014, 00:22
The messages clearly indicate what is wrong -- there are some resources in Qt (like all widget classes, pixmaps, etc.) that cannot be used from within worker threads.

anda_skoa
14th November 2014, 09:21
if you want to know if something has happened use qDebug()

Aside from threading issues logging is way less intrusive and interrupting than message boxes popping up everywhere.

Cheers,
_

aekilic
14th November 2014, 09:26
What is the solution for this?

wysota
14th November 2014, 11:23
As already said, use qDebug() instead of message boxes.

aekilic
14th November 2014, 12:35
Normally I use QSqlQuery and post them on tree in QStandardItemModel. But this operation takes time. So i use QFuture. So that would be the solution if I use QStandardItemModel or QTableModel in QFuture?

wysota
14th November 2014, 13:11
The concurrent operation should return a container with data required to build the model in the main thread.

aekilic
18th November 2014, 09:35
Ok, i have change my code like this, but i still get an error like this.

QObject::connect: Cannot connect (null)::layoutAboutToBeChanged() to ProxyTableView::beforeLayoutChange()

fromBilgiEkrani.h


#ifndef BILGIEKRANI_H
#define BILGIEKRANI_H

#include <QtGui>
#include <QtSql>
#include <QWidget>
#include <QDateTime>
#include <QSqlDatabase>
#include <qtconcurrentrun.h>

namespace Ui {
class fromBilgiEkrani;
}

class fromBilgiEkrani : public QWidget
{
Q_OBJECT
public:
explicit fromBilgiEkrani(QWidget *parent = 0);
~fromBilgiEkrani();

public slots:
bool loadSql();
void loadTable(QSqlTableModel *model);

private:
QSqlTableModel *model;

Ui::fromBilgiEkrani *ui;
};

#endif



fromBilgiEkrani.cpp



#include "fromBilgiEkrani.h"
#include "ui_fromBilgiEkrani.h"

fromBilgiEkrani::fromBilgiEkrani(QWidget *parent) :
QWidget(parent),
ui(new Ui::fromBilgiEkrani)
{

Qt::WindowFlags flags;
flags = Qt::Window;
QWidget::setWindowFlags(flags);

ui->setupUi(this);

QTimer *sayfadegistir = new QTimer(this);
connect(sayfadegistir, SIGNAL(timeout()), this, SLOT(slotSayfaDegistir()));
sayfadegistir->start(2000);
}

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

void fromBilgiEkrani::slotSayfaDegistir(){

QFuture<void> future;
future = QtConcurrent::run(this, &fromBilgiEkrani::uretimAcikIsler);
break;
loaduretimAcikIsler(model);
}

bool fromBilgiEkrani::uretimAcikIsler(){

bool success = false;

model = new QSqlTableModel(this);
model->setTable("sqlview");
model->select();

return success;
}

void fromBilgiEkrani::loaduretimAcikIsler(QSqlTableMode l *model){
ui->tableAcikIsler->setModel(isclik);
ui->tableAcikIsler->resizeColumnsToContents();
}

wysota
18th November 2014, 09:56
Hmm.... Does this code even compile? It definitely shouldn't as uretimAcikIsler isn't static. Even if it was, you'd still get errors on setting a parent from another thread (line #37).

Maybe you should start from the beginning and tell us what you are trying to achieve?

aekilic
18th November 2014, 10:20
I dont if it compiles, i try to reduce my core before sending. I have changed the class names and everything.

What i am trying to is, i want create my QSqlTableModel in my Future, and after that i want to publish them in a QTableView. Since in QFuture i cant use QTableView, so i made a separate function for this. But then i try to use that function i get an error QObject::connect: Cannot connect (null)::layoutAboutToBeChanged() to ProxyTableView::beforeLayoutChange()

wysota
18th November 2014, 10:27
In future functions you can't use QSqlTableModel as well, at least not the way you are trying to do this. As I said befor, you should gather the data in the concurrent function and then use the data in the main thread to construct the model. Also remember that if you want to connect to SQL database from a worker thread, you will have to establish a separate SQL connection for that thread and you will have to do that from within that thread.

aekilic
18th November 2014, 10:40
Is there any example for this?

wysota
18th November 2014, 11:21
I think there is a "threaded item model" example bundled with Qt. But in general I said everything that needs to be said -- the concurrent function should return data which then should be fed into the model using a custom method.