2016-04-04 15 views
0

Ich habe versucht, Signal finished() aus meiner Klasse zu emittieren. Aber wenn ich das Signal an meinen Steckplatz anschließe, hat es nichts bewirkt.Emittiertes Signal wird nicht erkannt

Der Name meiner Klasse ist blend_install, ich habe es als blendinstaller deklariert und habe versucht, das mit dem QEventLoop zu verbinden.

.... 
QEventLoop ac; 
connect(&blendinstaller, SIGNAL(finished()), &ac, SLOT(quit())); 

blendinstaller.show_progress(); 
blendinstaller.download(); // this will execute everything and in the end emit finished() 

ac.exec(); 
.... 

Die download() Funktion:

current_prog = BLEND_INSTALL_NONE; 
emit progress_changed(current_prog); 

manager = new QNetworkAccessManager; 

file_handler = new QFile(downloadTo); 

file_handler->open(QFile::WriteOnly); 
.... handle error .... // each of this (error handling) will emit finished() signal and return; 

.... // each of this will represent the process of reporting event changes (for logging), emit a SIGNAL() 

QNetworkRequest request; 
request.setUrl(QUrl(downloadFrom)); 

reply = manager->get(request); 
event = new QEventLoop; 
connect(reply,SIGNAL(finished()),event,SLOT(quit())); 
connect(reply,SIGNAL(error(QNetworkReply::NetworkError)),this,SLOT(downloadError(QNetworkReply::NetworkError))); 
connect(reply,SIGNAL(downloadProgress(qint64,qint64)),this,SLOT(downloadProgressL(qint64,qint64))); 


event->exec(); 

.... handle error .... 

.... write reply.readAll() to file .... 

.... 

// these are instruction for a custom QProcess instance 
proc.setProgram(extractWith); 
proc.setArguments(ar); 
proc.setWorkingDirectory(downloadIn); 

event = new QEventLoop; 
connect(&proc,SIGNAL(finished(int)),event,SLOT(quit())); 
connect(&proc,SIGNAL(error(QProcess::ProcessError)),this,SLOT(extractError(QProcess::ProcessError))); 
connect(&proc,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(extractFinished(int,QProcess::ExitStatus))); 

proc.start(); 
proc.open_console(); 

event->exec(); 

.... handle error .... 

.... 

.... attempt to find output of QProcess (extract an archive) .... 

.... handle error, output of QProcess not found .... 

.... 

emit installed(installOn); 
emit finished(); // the SIGNAL I want to get. 

qDebug("It's finished installing!"); 

So, TL; DR jeweils Fehler Handhabung aus der Funktion zurück, sondern auch finished() und am Ende der Funktion emittieren (vorausgesetzt, kein Fehler vorhanden ist) Es wird finished() emittieren.

Die Schleife wird nicht beendet.

Irgendeine Idee?

+2

Es fein sieht. Können Sie Ihre 'download()' Implementierung posten? Ich kann mir nur vorstellen, dass Ihre 'download()' Methode das 'finished()' Signal zu früh abgibt. Besser gesagt: Es sollte überhaupt nicht aufgerufen werden. Normalerweise würde irgendeine Art von privatem Slot 'onDownloadComplete()' das 'finished() 'Signal ausgeben. – mfreiholz

+0

@mfreiholz ​​Ich habe das hochgeladen, und ich werde Ihren Vorschlag versuchen ... –

+0

Es ist immer print, dass "es fertig ist zu installieren!" Nachricht, sendet aber immer noch nicht das 'finished()' Signal. –

Antwort

1

Das Problem mit Ihrer download() Methode ist, dass es bereits eine synchrone Methode ist. Sie benötigen diese Ereignisschleife nicht. Sie machen bereits alles in Ereignisschleifen innerhalb Ihrer download() Methode.

Seitennotiz: Und Sie scheinen einige Speicherlecks zu haben, da Sie QEventLoop ohne Eltern erstellen und nie löschen.

UPDATE # 1: Ihr finished() Ereignis wird von der äußeren QEventLoop gehandhabt wird (ac), weil das finished() Signal ausgesendet wird, bevor die QEventLoop auch Ereignisse zu behandeln mit exec() beginnen. Als eine hässliche Workarround konnten Sie download() nach exec() mit einer Warteschlange QMetaObject::invokeMethod() (Qt :: QueuedConnection) Aufruf aufrufen (aber ich würde es nicht empfehlen).

Update # 2 Hier ist ein kleines Beispiel, das nicht perfekt ist, natürlich: P

class BlendDownloader 
{ 
    Q_OBJECT 

public: 
    BlenDownloader() : 
    _file(NULL) 
    { 
    } 

    void download() 
    { 
    _file = new QFile("C:/myfile.blubb"); 

    QNetworkRequest req("your url here"); 
    QNetworkReply* reply = _mgr.get(req); 
    QObject::connect(reply, SIGNAL(finished()), this, SLOT(onDownloadFinished())); 
    // TODO: Also handle error callback here 
    } 

private slots: 
    void onDownloadFinished() 
    { 
    QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender()); 
    reply->deleteLater(); 

    // Write response data to file. 
    // Note: You might get problems with big files, 
    // since this buffers the entire response of QNetworkReply 
    // in internal buffer. It's better to use the "readyRead()" 
    // signal and write incrementally. 
    _file->write(reply->readAll()); 

    // Do your parsing stuff now and emit "finished()" at the end. 
    // ... parsing, validation here ... 

    // Clean up 
    _file->close(); 
    delete _file; 
    _file = NULL; 

    emit finished(); 
    } 

private: 
    QNetworkManager _mgr; 
    QFile* _file; 
}; 
+0

Es ist eine Reihe von ' QEventLoop in einem 'QEventLoop', weil ich darauf warten muss, bis alles fertig ist. Aber es könnte wegen des Speicherlecks sein. Ich habe den QEventLoop auf der privaten Sektion meiner Klasse erklärt, ist das so schlimm? –

+0

@TitoNovelianto Warum müssen Sie warten, bis alles fertig ist, wenn Sie ein "fertiges" Signal ausgeben? Schließen Sie einfach dieses 'fertige' Signal an einen Slot an, wo Sie tun, was Sie nach' loop-> exec 'tun (was fast so aussieht, als ob Sie es ohnehin schon tun). – thuga

+0

Ich habe meine Antwort mit einem kleinen Beispiel aktualisiert (Update # 2) – mfreiholz