示例程序


这里写图片描述

代码上传至https://github.com/gatieme/AderXCoding/tree/master/qt/restart

问题描述


有时候写的程序在运行中有时候出现问题,期望能够通过重启来解决,但是在我们的Qt中并没有内置实现这样功能的接口,这就不得不需要自己实现。

重启,无非就是关闭当前应用程序,然后再启动一个新的进程执行当前应用程序

实现重启的方法


目前常用的有两种方式实现重启

方法描述
进程控制退出当前进程,再通过QProcess启动一个新的进程
事件循环退出应用程序,然后通过Application事件循环控制程序启动

使用进程控制实现重启


首先来看qt程序如何退出

Qt程序退出

Qt程序的一般结构如下:

int main(int argc, char** argv)
{
    QApplication app(argc, argv);
    Widget w;
    w.show()
    return app.exec();
}

最后一句启动了主线程的事件循环。而要退出程序,就是要退出这个事件循环,使main函数返回。

因此退出应用程序就需要退出应用程序QApplication

exit && quit

退出的方法简单来说有两种,我们分别来说
一般来说,正确的退出方式如下

QCoreApplication::exit(int);

还有另外一个马甲

QCoreApplication::quit(); <==> exit(0);

我们可以很容易在官方的帮助文档中,找到quit和exit之间的区别和联系

这里写图片描述

closeAllWindows

对于QApplication来说,它有一个常用的属性quitOnLastWindowClosed 默认是true,所以,当最后一个窗口关闭时,它可以自动调用前面的exit()

这里写图片描述

因此关闭程序我们只需要关闭所有程序,并且保证quitOnLastWindowClosed = true即可.

因此我们还可以使用

QApplication::closeAllWindows()

注:一般来说,对于多个窗口的程序,调用这个会比直接调用quit要好。因为这样窗口可以接受到Close事件。

重新启动一个进程


在Qt中, 可以使用QProcess::startDetached开启一个新的进程
要启动当前程序的另一个进程,有要使二者没有”父子”关系就可以使用QProcess

QProcess类的作用是启动一个外部的程序并与之交互。

QProcess::startDetached(qApp->applicationFilePath(), QStringList());

可是,为什么不写成下面这样?

QProcess::startDetached(qApp->applicationFilePath());

当然,如果路径中不包含空格,这个也可以工作。

通过进程控制实现重启


///  使用进程控制实现重启
/// 执行如下操作
/// ①  退出当前程序  (QT下有6种方式实现)
/// ②  开启新的进程启动当前程序  (使用QProcess::startDetached)
///
/// ①  种方式实现退出
///
//  方式一: QCoreApplication::exit(0);0是状态还可以是其他的值。
//         QCoreApplication::quit();
//         QApplication::exit(0);
//         QApplication是继承QCoreApplication的。
//         QApplication::quit();
//  方式二: close();QApplicatio有个常用属性qApp->quitOnLastWindowClosed(true);当最后一个窗口关闭时自动调用前面的exit()。
//         QApplication::closeAllWindows();关闭多个窗口,比调用quit好,因为窗口可以接受到close事件。
///
/// ②  开启新的进程启动当前程序
///
//  在Qt中, 可以使用QProcess::startDetached开启一个新的进程
//  要启动当前程序的另一个进程,有要使二者没有"父子"关系
//  使用QProcess::startDetached(qApp->applicationFilePath(), QStringList());
//  其中QStringList()为参数列表
//  特别的, 如果程序的路径中没有空格也可以使用QProcess::startDetached(qApp->applicationFilePath());
void RestartWidget::slotProceeRestart()
{
    qApp->closeAllWindows();
    //qApp->quit();

    //  如果是在嵌入式arm板子上,需要加入 -qws 的参数
    //QStringList args;
    //args.append("-qws");        //  参数信息
    //args.append("&");           //  后台运行
    QProcess::startDetached(qApp->applicationFilePath(), QStringList());
}

使用事件循环


自己观察前面的qt主函数,我们看到最后一行a.exec();

exec

这个函数使qt的gui进入了事件循环,并且返回了程序exit的值,
因此我们可以在这个地方做些手脚。

最简单的办法,就是创建一个循环,当函数正常退出时,不做处理,而程序期望程序时,返回一个我们可以识别的EXIT_CODE,并且不真正退出,而是重新启动一个新的窗体进入事件循环
尽管没什么好处,但有时候,我似乎更喜欢这样写:

///  使用事件循环进行重启
void RestartWidget::soltExitRestart()
{
    //  773 = 'r'+'e'+'s'+'t'+'a'+'r'+'t'
    //  ==>restart
    //#define EXIT_RESTART  773
    qApp->exit(773);

}

然后main函数改成

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    int ret = -1;
    do
    {
        RestartWidget w;
        w.show();

        ret = a.exec();

    }while(ret != 0);

    return ret;
}
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐