PDA

View Full Version : Problem with closeEvent handler implementation.



robgeek
18th February 2016, 12:58
I'm trying to reimplement a closeEvent handler but is not working as i want. I hope you can help me. I need start a python program as a last "task" of my main program. Here my first attempt.

void MainWindow::closeEvent(QCloseEvent *wd) {
QString uploaderPath = "python " + QCoreApplication::applicationDirPath( ) + "/Uploader/setter.py";

QProcess *up = new QProcess( this );
up->start( uploaderPath );

wd->accept();
}
Error message when i close my main program:

QProcess: Destroyed while process ("python") is still running.

So, i tried to create a second thread where i could run this python program. I thought this program would run regardless of my main program. I close my main program, since the second(python) will run in another thread he will do what he should and will die too. But i was wrong. Here the code.
Second attempt.

#ifndef RESETTER_H
#define RESETTER_H

#include <QtCore>

class Resetter : public QThread {
public:
Resetter( );
void run( );
};

#endif // RESETTER_H

#include "resetter.h"

Resetter::Resetter( ) { }

void Resetter::run( ) {
QString uploaderPath = "python " + QCoreApplication::applicationDirPath( ) + "/Uploader/setter.py";

QProcess *up = new QProcess( this );
up->start( uploaderPath );
}


void MainWindow::closeEvent(QCloseEvent *wd) {
Resetter rs;

rs.start( );

wd->accept();
}

Error message when i close my main program:

QThread: Destroyed while thread is still running
Segmentation fault (core dumped)


Or create that object on the heap:

void MainWindow::closeEvent(QCloseEvent *wd) {
Resetter *rs = new Resetter( );

rs->start( );

wd->accept();
}
Error message when i close my main program:

QCoreApplication::applicationDirPath: Please instantiate the QApplication object first
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QThread(0x112e700), parent's thread is QThread(0x1098e60), current thread is QThread(0x112e700)

anda_skoa
18th February 2016, 13:10
You can either make the program wait for the process or use QProcess::startDetached().

Cheers,
_

d_stranz
18th February 2016, 16:38
What is likely causing your problem (well, several things, actually) are the facts that you are creating your QProcess instances with the MainWindow instance as parent. This means the QProcess instance will be destroyed when the main window is destroyed. Secondly, QApplication's default setting is to quit when the last top-level window closed. In your case, quitting will ensure that the MainWindow instance is destroyed along with your QProcess. Creating your Resetter instance on the stack is useless, since it will be destroyed as soon as the closeEvent() exits.

You can try starting your process detached, as anda_skoa suggests, or you can set the quit on last window closed flag to false. Or, maybe you can create a second, non-visible top-level widget that can be the parent of your QProcess. You can connect the QProcess::finished() signal to that widget's close() slot. Other possibilities as well - turn the quit flag off, keep the QProcess as a child of MainWindow, but connect the finished() signal to the app's quit() slot.

robgeek
18th February 2016, 17:20
You can either make the program wait for the process or use QProcess::startDetached().

Cheers,
_
Its working as i want. Thanks!
But what's the difference between use QProcess::startDetached() and QThreads as i tried?

jefftee
18th February 2016, 23:34
When using QProcess::startDetached(), an external process that is then detached from the parent process, so that it can persist after the parent process has ended.