从不同的线程更新QProgressbar

时间:2012-07-02 14:33:04

标签: file qt cryptography qthread qprogressbar

我已经开发了自己的混合流密码,对于GUI,我使用的是Qt。最初我是在单个线程上编写的,但它是一个流密码,当在大文件上运行时,GUI功能失调。所以我将加密/解密转移到单独的Qthread。为了显示进度,我在GUI上包含了一个标准的QProgressbar。但是当我运行文件I / O时,加密/解密工作完美但进度条没有正确更新。整个操作完成后,进度条突然从0%变为100%,表明在操作过程中没有机会更新。对于代码,我将完成的百分比从FileCrypto发送到主GUI线程到QProgressbar的setValue(int)插槽。由于它不起作用,我还尝试将一个int poitner发送到FileCrypto线程,同时用百分比更新指针并在GUI线程上使用QTimer在本地检查int值的值并更新进度条但仍然我得到了完全相同的结果。

这是我的代码:

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 ....

这里非常感谢任何形式的帮助.......

1 个答案:

答案 0 :(得分:7)

问题不在于你是从另一个线程调用的。它位于:

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

由于donelength是int类型,done <= lengthdone/length == 0。所以改成它:

emit completed(100 * done / length);

(如果可能导致算术溢出)。

相关问题