QThread中的QTimer触发信号,但GUI线程未更新

时间:2014-11-07 11:33:41

标签: c++ multithreading qt user-interface

我有两个QMainWindows,其中一个我想隐藏一段时间,同时加载它需要的东西,然后显示另一个。虽然显示了另一个,但它应该定期(通过QTimer)更改它显示的图像。我设法做了大部分工作,但即使正在调用更新图像的插槽,第二个QMainWindow也没有更新。

这是加载窗口类标题:

#ifndef LOADINGWINDOW_H
#define LOADINGWINDOW_H

#include <QMainWindow>
#include <QLabel>
#include <QTimer>
#include <QImage>
#include <QVector>
#include <QDebug>
#include <QVBoxLayout>

class LoadingWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit LoadingWindow(QWidget *parent = 0);

public slots:
    void startLoading();
    void stopLoading();

private slots:
    void loadingTimerExpired();

private:
    QLabel *m_loadingLabel;
    QVector<QPixmap> m_loadingPixmaps;
    QTimer *m_loadingTimer;
    int m_currentLoadingImage;
    QThread* m_loadingThread;

};

#endif // LOADINGWINDOW_H

.cpp文件:

#include "loadingwindow.h"
#include <QApplication>
#include <QDesktopWidget>
#include <QSettings>
#include <QFile>
#include <QThread>

LoadingWindow::LoadingWindow(QWidget *parent)
    : QMainWindow(parent, Qt::WindowStaysOnTopHint | Qt::CustomizeWindowHint | Qt::FramelessWindowHint)
{

    QSettings appSettings("app.ini",  QSettings::IniFormat);
    QString appPath = appSettings.value("appSettings/appPath").toString();
    QFile file(appPath + "/style.qss");
    file.open(QFile::ReadOnly | QFile::Text);
    QTextStream ts(&file);
    qApp->setStyleSheet(ts.readAll());


    m_loadingLabel = new QLabel();
    m_loadingPixmaps = QVector<QPixmap>(N_IMAGES);
    for (int i=0; i<m_loadingImgs.size(); i++)
    {
        m_loadingImgs[i] = QPixmap::fromImage(QImage(":/loadingImg" +
                                  QString::number(i) + ".png").scaled(QSize(800,500), Qt::KeepAspectRatio));
    }

    m_currentLoadingImage = 0;

    m_currentLoadingImage++;
    m_loadingLabel->setUpdatesEnabled(true);
    m_loadingLabel->setAttribute(Qt::WA_TranslucentBackground);
    m_loadingLabel->setPixmap(m_loadingPixmaps[0]);
    m_loadingLabel->adjustSize();
    m_loadingLabel->move(QApplication::desktop()->screen()->rect().center() - m_loadingLabel->rect().center());

    this->setCentralWidget(m_loadingLabel);
    this->adjustSize();
    this->move(QApplication::desktop()->screen()->rect().center() - m_loadingLabel->rect().center());


    m_loadingTimer = new QTimer();
    m_loadingTimer->setInterval(70);
    m_loadingThread = new QThread(this);
    m_loadingTimer->moveToThread(m_loadingThread);
    QObject::connect(m_loadingTimer,
                     SIGNAL(timeout()),
                     this,
                     SLOT(loadingTimerExpired())
                     , Qt::DirectConnection);

    QObject::connect(m_loadingThread,
                     SIGNAL(started()),
                     m_loadingTimer,
                     SLOT(start()));

    QObject::connect(m_loadingThread,
                     SIGNAL(finished()),
                     m_loadingTimer,
                     SLOT(stop()));

}

void LoadingWindow::startLoading()
{
    m_loadingThread->start();
    this->show();
    QApplication::processEvents();
}

void LoadingWindow::stopLoading()
{
    this->hide();
    m_loadingThread->exit();
}


void LoadingWindow::loadingTimerExpired()
{


    m_loadingLabel->setPixmap(m_loadingPixmaps[m_currentLoadingImage]);
    m_loadingLabel->update();
    QApplication::processEvents();

    m_currentLoadingImage++;
    if (m_currentLoadingImage == m_loadingPixmaps.size())
        m_currentLoadingImage=0;
}

从我的第一个qmainwindow开始,我只需通过调用startLoading()来启动加载窗口(并设置另一个mainwindow.setVisible(false))

事情是显示加载窗口,但它不会改变其图像。我知道loadingTimerExpired()每70毫秒被触发,正如预期的那样,因为我从那里打印了一些调试消息。我的猜测就是那个

m_loadingLabel->update();
QApplication::processEvents();

句子没有像我期望的那样工作,并且GUI线程以某种方式被阻止。有人知道如何解决这个问题吗?

0 个答案:

没有答案