2016-04-04 35 views
0

Sınıfımdan finished() sinyali göndermeye çalıştım. Ama sinyali yuvama bağladığımda, hiçbir şey yapmadı.Yayılan Sinyal Algılanmadı

Sınıfımın adı blend_install, ben blendinstaller olarak bildirdim ve bunu QEventLoop'a bağlamaya çalıştım.

.... 
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(); 
.... 

download() fonksiyonu:

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!"); 

Yani, TL; DR taşıma hataların her işlevinden dönmek değil, aynı zamanda finished() yayarlar ve fonksiyon sonunda (hiçbir hata yoktur varsayarak olacak) finished() yayar.

Döngüden çıkmaz.

Herhangi bir fikrin var mı?

+2

Bu ince görünüyor:

İşte Güncelleme 2. elbette mükemmel değil, küçük bir örnek vardır. İndirme() 'uygulamanızı yayınlayabilir misiniz? Sadece 'download()' yönteminin 'bitmiş()' sinyalin çok erken yayıldığını hayal edebiliyorum. Daha iyi dedi ki: Bu hiç denilmemelidir. Genellikle bir tür özel yuva 'onDownloadComplete()' bitmiş() 'sinyalini yayar. – mfreiholz

+0

@mfreiholz ​​Bunu yükledim ve önerinizi deneyeceğim ... –

+0

Her zaman "Yüklemeyi bitirmiş!" mesaj, ama hala bitmiş() 'sinyalini yaymaz. –

cevap

1

download() yönteminizle olan sorun, zaten bir senkronizasyon yöntemidir. Bu etkinlik döngüsüne ihtiyacınız yok. Zaten download() yönteminizin içindeki olay döngülerinde her şeyi yapıyorsunuz.

Yan not: Ve QEventLoop'u ebeveynsiz oluşturduğunuzdan ve hiçbir zaman silmediğinizden, bazı bellek sızıntılarına sahip görünüyorsunuz.

GÜNCELLEME # 1: QEventLoop bile exec() ile olayları işlemek için başlamadan önce finished() sinyal yaydığı alır çünkü finished() olay, dış QEventLoop (ac) tarafından işlenen varlık değildir. Çirkin bir iş ortamı olarak, exec()'dan sonra QMetaObject::invokeMethod() (Qt :: QueuedConnection) çağrısı ile download()'u çağırabilirsiniz (ancak bunu önermem). 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

Bu bir sürü QEventLoop'un içinde bir “QEventLoop” var çünkü her şey bitene kadar beklemem gerekiyor. Ancak bellek sızıntısı yüzünden olabilir. QEventLoop'umu sınıfımın özel bölümünde ilan ettim, bu kötü mü? –

+0

@TitoNovelianto Niçin 'bitmiş' sinyal gönderdiğinde her şey bitene kadar beklemeniz gerekiyor? Sadece bu 'bitmiş' sinyalini, 'loop-> exec' sonra yaptığınız şeyi yaptığınız bir yuvaya bağlayın (ki neredeyse her durumda yapıyormuşsunuz gibi görünüyor). – thuga

+0

Cevabımı küçük bir örnekle güncelledim (Update # 2) – mfreiholz