示例程序
代码上传至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();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
最后一句启动了主线程的事件循环。而要退出程序,就是要退出这个事件循环,使main函数返回。
因此退出应用程序就需要退出应用程序QApplication
exit && quit
退出的方法简单来说有两种,我们分别来说
一般来说,正确的退出方式如下
QCoreApplication::exit(int);
- 1
- 1
还有另外一个马甲
QCoreApplication::quit(); <==> exit(0);
- 1
- 1
我们可以很容易在官方的帮助文档中,找到quit和exit之间的区别和联系
closeAllWindows
对于QApplication来说,它有一个常用的属性quitOnLastWindowClosed
默认是true
,所以,当最后一个窗口关闭时,它可以自动调用前面的exit()
因此关闭程序我们只需要关闭所有程序,并且保证quitOnLastWindowClosed = true
即可.
因此我们还可以使用
QApplication::closeAllWindows()
- 1
- 1
注:一般来说,对于多个窗口的程序,调用这个会比直接调用quit要好。因为这样窗口可以接受到Close事件。
重新启动一个进程
在Qt中, 可以使用QProcess::startDetached开启一个新的进程
要启动当前程序的另一个进程,有要使二者没有”父子”关系就可以使用QProcess
QProcess类的作用是启动一个外部的程序并与之交互。
QProcess::startDetached(qApp->applicationFilePath(), QStringList());
- 1
- 1
可是,为什么不写成下面这样?
QProcess::startDetached(qApp->applicationFilePath());
- 1
- 1
当然,如果路径中不包含空格,这个也可以工作。
通过进程控制实现重启
/// 使用进程控制实现重启
/// 执行如下操作
/// ① 退出当前程序 (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());
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
使用事件循环
自己观察前面的qt主函数,我们看到最后一行a.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);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
然后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;
}
转载:http://blog.csdn.net/gatieme/article/details/50374563