Код ответа находится здесь (https://stackoverflow.com/a/50550471/4962676):
https://github.com/eyllanesc/stackoverflow/tree/master/50550089
Ответ был более простым, чем приведенный ниже код - в приведенном выше коде используется QPropertyAnimation вместо использования для циклов с QThread, как показано ниже -это экономит тонны пространства в коде и является более эффективным.
Оригинальный вопрос ниже:
Я пишу приложение в Qt, и у меня возникла проблема с закрытием приложения и потоков.
По сути, окно приложения закрывается, однако процесс остается в фоновом режиме и никогда не закрывается.
мой основной заголовок (только что включен класс, так как имеется много включений):
class ChatUI : public QWidget
{
Q_OBJECT
public:
explicit ChatUI(QWidget *parent = 0);
~ChatUI();
private:
// The UI itself
Ui::ChatUI * ui;
// Current appliation startup directory
QString applicationStartupDir = QDir::currentPath() + "/";
// Typing indicator stuff
QFrame * typingIndicator = nullptr;
QImage circleImage;
ThreadController * typingIndicatorThread = new ThreadController(false);
bool currentlyFadingTypingIndicator = false;
// The calm before the storm
bool closing = false;
void showTypingIndicator();
void hideTypingIndicator();
signals:
void WidgetClosed();
protected:
void closeEvent(QCloseEvent*);
};
мой контроллер (заголовок):
#ifndef THREADCONTROLLER_H
#define THREADCONTROLLER_H
#include <QObject>
#include <QThread>
#include <QImage>
#include <QFrame>
#include "typingindicatorthread.h"
class ThreadController : public QObject
{
Q_OBJECT
QThread * workerThread = nullptr;
TypingIndicatorThread * worker = nullptr;
signals:
void startWork(QFrame*, QImage);
//void killThread();
public slots:
void killThread();
public:
ThreadController(bool);
};
#endif // THREADCONTROLLER_H
мой контроллер (источник):
#include "threadcontroller.h"
#include <QDebug>
ThreadController::ThreadController(bool asd)
{
if (asd == true){
workerThread = new QThread();
worker = new TypingIndicatorThread;
worker->moveToThread(workerThread);
workerThread->start();
connect(this, &ThreadController::startWork, worker, &TypingIndicatorThread::startWorker);
} else {
workerThread = new QThread();
workerThread->quit();
workerThread->wait();
delete workerThread;
}
}
void ThreadController::killThread() {
emit worker->killSignal();
workerThread->quit();
workerThread->wait();
}
Мой поток (заголовок):
#ifndef TYPINGINDICATORTHREAD_H
#define TYPINGINDICATORTHREAD_H
#include <QObject>
#include <QLabel>
#include <QPixmap>
#include <QImage>
#include <QEventLoop>
#include <QTimer>
#include <QMetaObject>
#include <QPropertyAnimation>
class TypingIndicatorThread : public QObject
{
Q_OBJECT
public:
~TypingIndicatorThread();
private:
bool kill = false;
public slots:
void startWorker(QFrame*, QImage);
void killSignal();
};
#endif // TYPINGINDICATORTHREAD_H
мой поток (источник):
#include "typingindicatorthread.h"
#include <QDebug>
inline void delay(int millisecondsWait)
{
QEventLoop loop;
QTimer t;
t.connect(&t, &QTimer::timeout, &loop, &QEventLoop::quit);
t.start(millisecondsWait);
loop.exec();
}
void TypingIndicatorThread::startWorker(QFrame * typingIndicator, QImage circleImage) {
int max = 30;
int min = 5;
int waitTime = 5;
QMetaObject::invokeMethod(typingIndicator, [=]() {
QLabel * circle1 = new QLabel(typingIndicator);
circle1->setGeometry(0,0, 50, 50);
circle1->setAlignment(Qt::AlignCenter);
circle1->show();
QLabel * circle2 = new QLabel(typingIndicator);
circle2->setGeometry(40,0, 50, 50);
circle2->setAlignment(Qt::AlignCenter);
circle2->show();
QLabel * circle3 = new QLabel(typingIndicator);
circle3->setGeometry(80,0, 50, 50);
circle3->setAlignment(Qt::AlignCenter);
circle3->show();
forever {
if (kill) {
qDebug() << "Killing thread";
return;
}
// Circle1
for (int i=min; i < max; i++) {
delay(waitTime);
QPixmap circlePixmap = QPixmap::fromImage(circleImage).scaled(QSize(i, i), Qt::KeepAspectRatio, Qt::SmoothTransformation);
circle1->setPixmap(circlePixmap);
}
for (int i=max; i > min; i--) {
delay(waitTime);
QPixmap circlePixmap = QPixmap::fromImage(circleImage).scaled(QSize(i, i), Qt::KeepAspectRatio, Qt::SmoothTransformation);
circle1->setPixmap(circlePixmap);
}
// Circle2
for (int i=min; i < max; i++) {
delay(waitTime);
QPixmap circlePixmap = QPixmap::fromImage(circleImage).scaled(QSize(i, i), Qt::KeepAspectRatio, Qt::SmoothTransformation);
circle2->setPixmap(circlePixmap);
}
for (int i=max; i > min; i--) {
delay(waitTime);
QPixmap circlePixmap = QPixmap::fromImage(circleImage).scaled(QSize(i, i), Qt::KeepAspectRatio, Qt::SmoothTransformation);
circle2->setPixmap(circlePixmap);
}
// Circle3
for (int i=min; i < max; i++) {
delay(waitTime);
QPixmap circlePixmap = QPixmap::fromImage(circleImage).scaled(QSize(i, i), Qt::KeepAspectRatio, Qt::SmoothTransformation);
circle3->setPixmap(circlePixmap);
}
for (int i=max; i > min; i--) {
delay(waitTime);
QPixmap circlePixmap = QPixmap::fromImage(circleImage).scaled(QSize(i, i), Qt::KeepAspectRatio, Qt::SmoothTransformation);
circle3->setPixmap(circlePixmap);
}
}
});
}
void TypingIndicatorThread::killSignal() {
qDebug() << "oh no we are going to the shadow realm";
kill = true;
}
TypingIndicatorThread::~TypingIndicatorThread() {
emit killSignal();
}
Единственная причина, по которой я использую беспорядочные циклы for для своей анимации, заключается в том, что я как можно больше исследовал анимацию изображений, однако создать анимацию не из чего.outsidQML и приложение на C ++.
Если возможно, было бы здорово использовать QPropertyAnimation в качестве альтернативы, но я не могу анимировать размер пузырьков (кругов), в то же времяОбновление отображаемого размера.
Я извиняюсь, если кода много, я просто хотел дать как можно больше контекста (и это важно), чтобы помочь решить эту проблему.