2012-07-02 6 views
2

Я разработал собственный гибридный потоковый шифр, а для графического интерфейса я использую Qt. Первоначально я написал это в одном потоке, но это был потоковый шифр, который делал GUI дисфункциональным при работе с большими файлами. Поэтому я переключил шифрование/дешифрование на отдельный Qthread. Также, чтобы показать прогресс, я включил стандартный QProgressbar в графический интерфейс. Но когда я запускаю File I/O, шифрование/дешифрование работает отлично, но индикатор выполнения не обновляется должным образом. По завершении всей операции индикатор выполнения переходит от 0% до 100%, показывая, что во время операции он не смог обновиться. Для кода я испустил заполненный процент от FileCrypto к основному потоку GUI в слот setValue (int) QProgressbar. Так как это не сработало, я также попытался отправить int poitner в поток FileCrypto, обновив указатель с процентом и используя QTimer в потоке GUI, чтобы проверить значение значения int локально и обновить индикатор выполнения, но все же Я получил тот же результат.Обновление QProgressbar из другой темы

Вот мой код:

Класс FileCrypto:

#include <QThread> 
#include <QFile> 
#include <PolyVernam.h> //my algo header 

class FileCrypto : public QThread 
{ 
    Q_OBJECT 

public: 
    FileCrypto(QString, QString, int); 
    bool stopIt; 

protected: 
    void run(); 

signals: 
    void completed(int); 
    void msg(QString); 
    void pathMsg1(QString); 
    void pathMsg2(QString); 
    void keyMsg(QString); 

private: 
    QFile src, dest; 
    QString tag; 
    int mode; 
    qint64 length; 
    PolyVernam pv; 
}; 

Кодекс:

#include <FileCrypto.h> 

FileCrypto::FileCrypto(QString input, QString keyFile, int mode) 
{ 
    stopIt = false; 
    this->mode = mode; 
    src.setFileName(input); 

    if(mode == 1) 
    { 
     emit msg("Current Encryption/Decryption status: Encrypting file... :D:D"); 
     tag = "-encrypted"; 
     pv.setMode("encrypt", ""); 
    } 
    else 
    { 
     emit msg("Current Encryption/Decryption status: Decrypting file... :D:D"); 
     tag = "-decrypted"; 
     pv.setMode("decrypt", keyFile); 
    } 

    dest.setFileName(QFileInfo(src).absolutePath() + "/" + QFileInfo(src).baseName() 
        + tag + "." + QFileInfo(src).completeSuffix()); 

    length = src.bytesAvailable(); 
} 

void FileCrypto::run() 
{ 
    qint64 done = 0; 
    quint8 r, outChar; 
    char ch; 

    QDataStream in(&src); 
    in.setVersion(QDataStream::Qt_4_7); 
    src.open(QIODevice::ReadOnly); 

    QDataStream out(&dest); 
    out.setVersion(QDataStream::Qt_4_7); 
    dest.open(QIODevice::WriteOnly); 

    while(!in.atEnd() && !stopIt) 
    { 
     done++; 

     in >> r; 
     ch = char(r); 

     if(mode == 1) 
      outChar = pv.encrypt(QString(ch)).at(0).toAscii(); 
     else 
      outChar = pv.decrypt(QString(ch)).at(0).toAscii(); 

     out << outChar; 

     emit completed(int((done/length) * 100)); 
    } 

    src.close(); 
    dest.close(); 

    if(stopIt) 
     this->exit(0); 

    if(mode == 1) 
    { 
     emit pathMsg1(QFileInfo(src).absoluteFilePath()); 
     emit pathMsg2(QFileInfo(dest).absoluteFilePath()); 
    } 
    else 
    { 
     emit pathMsg1(QFileInfo(dest).absoluteFilePath()); 
     emit pathMsg2(QFileInfo(src).absoluteFilePath()); 
    } 

    emit keyMsg(pv.keyFilePath); 
    emit msg("Current Encryption/Decryption status: Idle... :'("); 
} 

Это, как я делаю нить и подключить его на главной GUI потоке :

FileCrypto *fc = new FileCrypto(ui->lineEdit_4->text(), "", 1); 

connect(fc, SIGNAL(completed(int)), ui->progressBar, SLOT(setValue(int))); 
connect(fc, SIGNAL(msg(QString)), ui->statusBar, SLOT(showMessage(QString))); 
connect(fc, SIGNAL(pathMsg1(QString)), ui->lineEdit_4, SLOT(setText(QString))); 
connect(fc, SIGNAL(pathMsg2(QString)), ui->lineEdit_5, SLOT(setText(QString))); 
connect(fc, SIGNAL(keyMsg(QString)), ui->lineEdit_2, SLOT(setText(QString))); 
connect(fc, SIGNAL(keyMsg(QString)), this, SLOT(done())); 

Если я не обновляю индикатор выполнения, то есть не излучаю процент, процесс происходит намного быстрее. Я также попробовал распечатать процент. Это замедляет его, как черт, но все в порядке. Кроме того, вы можете предложить способ изменить его забуференное IO ....

Любого вид помощи является высоко ценится здесь .......

+0

Слоты IIRC Qt синхронны. См. Http://stackoverflow.com/questions/1264887/qt-4-5-is-emitting-signal-a-function-call-or-a-thread-and-does-it-blocks и даже лучше http://cdumez.blogspot.de/2011/03/worker-thread-in-qt-using-signals-slots.html – RedX

+0

обычный способ ... после вышеуказанных соединений, fc-> start(); thats it ... –

+0

У вас есть вызов 'moveToThread()' в конструкторе 'FileCrypto'? – Chris

ответ

7

Проблема не лежит в том, что вы вызов из другого потока. Он расположен в:

emit completed(int((done/length) * 100)); 

С done и length являются ИНТ типы и done <= length, done/length == 0. Поэтому измените его на:

emit completed(100 * done/length); 

(если это может привести к арифметическому переполнению).

+0

Изменено -1 до +1 :) – houbysoft

+0

Кто-то должен сменить постановку задачи :) – KCiebiera

+0

Это работало !!!! Спасибо тонну KCiebiera и houbysoft! –

 Смежные вопросы

  • Нет связанных вопросов^_^