Question

I'm trying to create a fading effect on one of my QLabel when the user saves their game.

So, i thought using a QThread would be perfect for the job but the only problem is QThread::msleep(); freezes the program.

I've used this technique many times before to slow down a loop but, now it just decided to freezes my program until the loop is over.

Does anyone have any ideas about what's going on here?

I removed all the unrelated stuff cause this program is huge.

saved.h

#ifndef SAVED_H
#define SAVED_H

#include <QThread>

class Saved : public QThread
{
    Q_OBJECT
public:
    explicit Saved(QObject *parent = 0);
    void run();
signals:
    void reduceVisibility(unsigned short);
public slots:

};

#endif // SAVED_H

saved.cpp

#include "saved.h"

Saved::Saved(QObject *parent) :
    QThread(parent)
{

}

void Saved::run(){
    unsigned short alpha = 250;
    for(unsigned short i = 0; i <= 5; i++){
        emit reduceVisibility(alpha);
        alpha -= 50;
        QThread::msleep(250);
    }
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

// QThread
#include "saved.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

    Saved *saving;

private slots:

public slots:
    void animateSave(unsigned short);
private:
    Ui::MainWindow *ui;
};

main.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QApplication>
#include <QFile>
#include <QTextStream>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // QThread
    saving = new Saved(this);
    connect(saving, SIGNAL(reduceVisibility(unsigned short)), this, SLOT(animateSave(unsigned short)));
}

MainWindow::~MainWindow()
{
    delete ui;
}

// Buttons
void MainWindow::on_Btn_Save_clicked(){
    QFile saveFile("save.txt");
    saveFile.open(QIODevice::WriteOnly | QIODevice::Text);
    QTextStream out(&saveFile);
    out << user.getUsername() + "\n" + user.getLevel();
    saveFile.close();

    saving->run();
    saving->quit();
}

// Slots
void MainWindow::animateSave(unsigned short Visibility){
    QString visible = QString::number(Visibility);
    ui->Lbl_Saved->setStyleSheet("color:rgb(0,255,255, " + visible + ");");
}
Was it helpful?

Solution 2

Does anyone have any ideas about what's going on here?

This is intended (see QThread: QObject). The receiver MainWindow is in another thread. Since the default connection is AutoConnection, Qt will use a QueuedConnection and run the slot animateSave in the same thread as your MainWindow object.

However, you shouldn't use QThread at all. You don't want to do things at the same time, instead, you want something to happen at (or after) a given time. QTimer is what you want.

MainWindow::MainWindow(QWidget *parent)
{
    /* ... */
    myTimer = new QTimer(this);
    connect(myTimer, SIGNAL(timeout(), this, SLOT(decreaseAlphaOrStop()));
}

void MainWindow::on_Btn_Save_clicked(){
    /* .. snip .. */
    alpha = 250;
    myTimer->start(250);    
}

// new slot
void MainWindow::decreaseAlphaOrStop(){
    alpha -= 50;
    if( alpha < 0){
        alpha = 0;
        myTimer->stop();
    }
    animateSave(alpha);
}

OTHER TIPS

You may also lookup the documentation of QPropertyAnimation and hook it on the QWidget::windowOpacity. this is may be the most fitting thing for your problem.

for example:

void MyWidget::buttonClicked() // SLOT when button is clicked
{
    QPropertyAnimation* anim = new QPropertyAnimation(ui->Lbl_Saved, "windowOpacity"); // new animation, hooked on the labels window opacity
    anim->setDuration(2500); // use 2.5 seconds for disapearing
    anim->setStartValue(1.0f); // from full visible
    anim->setEndValue(0.0f); // to invisible
    connect(anim, SIGNAL(finished()), anim, SLOT(deleteLater())); // delete object when animation done
    anim->start();
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top