我已经编写了这段代码,以在线方式查看示例,这些示例说明了我应该如何运行一个控制台程序,该程序不仅可以运行并退出,而且可以运行。基于Qt控制台应用程序。在这里,我希望它退出。除QTimer::singleShot
行外,我几乎了解所有内容。如果该行被注释掉,则该应用程序将运行但不会退出。如果保留,应用程序将按预期运行并退出。谁能向我解释为什么?
dostuff.h
#ifndef DOSTUFF_H
#define DOSTUFF_H
#include <QObject>
#include <iostream>
class DoStuff: public QObject
{
Q_OBJECT
public :
DoStuff(QObject *parent = 0);
public slots:
void run();
signals:
void finished();
};
#endif // DOSTUFF_H
执行dostuff.cpp
#include "dostuff.h"
DoStuff::DoStuff(QObject *parent):QObject(parent)
{
}
void DoStuff::run(){
for (int i = 0; i < 10000; i++){
std::cout << "Processing " << i << std::endl;
}
emit(finished());
}
我的main.cpp
#include <QCoreApplication>
#include <QTimer>
#include "dostuff.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
DoStuff *dostuff = new DoStuff(&a);
QObject::connect(dostuff,SIGNAL(finished()),&a,SLOT(quit()));
dostuff->run();
// WHY THIS??
QTimer::singleShot(10,dostuff,SLOT(run()));
return a.exec();
}
答案 0 :(得分:1)
QTimer
不需要正确退出;您只需要提供一种方法使您的应用程序在某个时候中断事件循环。在GUI应用程序中,当最后一个窗口关闭时,Qt does that automatically。
在控制台应用程序中,您可以:
在没有事件循环的情况下运行您的应用程序(如果您的应用程序中有直接的简单控制流)。
或者(如果您需要事件循环来处理某些事件或跨线程信号/插槽),则需要有一些事件使您的应用程序中断事件循环并退出。该事件仅应在应用程序完成其工作时触发。
问题中的代码示例非常简单,不需要事件循环即可正常运行。 QTimer
在您的代码中的唯一作用是将执行延迟10毫秒。这是不运行事件循环的相同代码示例:
#include <QtCore>
class DoStuff: public QObject
{
Q_OBJECT
public :
DoStuff(QObject *parent = 0) : QObject(parent) {}
public slots:
void run() {
for (int i = 0; i < 10000; i++){
qInfo() << "Processing " << i;
}
emit finished();
}
signals:
void finished();
};
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
DoStuff dostuff;
QObject::connect(&dostuff, &DoStuff::finished,
&a, &QCoreApplication::quit);
dostuff.run();
return 0; //no event loop required
}
#include "main.moc"
如果启动事件循环,则可能会注意到在不使用QTimer::singleShot
时退出槽不起作用。这样做的原因是,quit
在事件循环甚至尚未开始之前就已被调用(并且该调用完全无效)。因此,根据docs,建议使用排队连接连接到quit
:
优良作法是始终使用
QueuedConnection
将信号连接到此插槽。如果在控制进入主事件循环之前(例如在“ int main”调用exec()
之前)发出了连接到该插槽的信号(未排队),则该插槽无效,并且应用程序永不退出。使用排队连接可确保直到控制权进入主事件循环后才调用该插槽。
因此,如果您想在上面的代码中有一个事件循环,则只需使用connect
Qt::QueuedConnection
:
#include <QtCore>
class DoStuff: public QObject
{
Q_OBJECT
public :
DoStuff(QObject *parent = 0) : QObject(parent) {}
public slots:
void run() {
for (int i = 0; i < 10000; i++){
qInfo() << "Processing " << i;
}
emit finished();
}
signals:
void finished();
};
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
DoStuff dostuff;
QObject::connect(&dostuff, &DoStuff::finished,
&a, &QCoreApplication::quit,
Qt::QueuedConnection);
// ^^^^^^^^^^^^^^^^
// use a queued connection
dostuff.run();
return a.exec(); //start an event loop
}
#include "main.moc"