如何从任何地方完成 Qt 程序?
Posted
技术标签:
【中文标题】如何从任何地方完成 Qt 程序?【英文标题】:How to finish Qt programm from any place? 【发布时间】:2014-04-07 01:12:47 【问题描述】:我的例子:
main.cpp:
QApplication a(argc, argv);
MainWindow w;
w.start();
return a.exec();
w.start():
if (cf.exec())
this->show();
else
qDebug()<<"Need exit";
//here should be exit
在评论处,我尝试这样做:qApp->exit() 和 qApp->quit() 和 this->close() (但“this”未显示,并且当然 close() 不起作用)。如何从任何代码位置完成应用程序?
完整代码: main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
QApplication a(argc, argv);
MainWindow w;
w.start();
return a.exec();
主窗口.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "CadrForm.h"
#include "TeacherForm.h"
#include "DepartmentForm.h"
#include "CategoriesForm.h"
#include "PostForm.h"
#include "RanksAndDegreesForm.h"
#include "TeachersRankAndDegreeForm.h"
#include "ConnectionForm.h"
namespace Ui
class MainWindow;
class MainWindow : public QMainWindow
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
void start();
~MainWindow();
signals:
void widgetChanged(QWidget*);
private slots:
void on_actionCadr_triggered();
void resetMainLayout(QWidget* w);
void on_actionTeacher_triggered();
void on_actionDepartment_triggered();
void on_actionPost_triggered();
void on_actionCategories_triggered();
void on_actionRanksAndDegrees_triggered();
void on_actionTeachersRD_triggered();
private:
ConnectionForm cf;
CadrForm *cadrForm;
TeacherForm *teacherForm;
DepartmentForm *departmentForm;
CategoriesForm *categoriesForm;
PostForm *postForm;
RanksAndDegreesForm *ranksAndDegreesForm;
TeachersRankAndDegreeForm *teachersRankAndDegreeForm;
QWidget *current;
Ui::MainWindow *ui;
void addWidgetToMainLayout(QWidget *w);
;
#endif // MAINWINDOW_H
主窗口.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
connect(this, SIGNAL(widgetChanged(QWidget*)), this, SLOT(resetMainLayout(QWidget*)));
ui->setupUi(this);
cadrForm = new CadrForm(this);
teacherForm = new TeacherForm(this);
departmentForm = new DepartmentForm(this);
categoriesForm = new CategoriesForm(this);
postForm = new PostForm(this);
ranksAndDegreesForm = new RanksAndDegreesForm(this);
teachersRankAndDegreeForm = new TeachersRankAndDegreeForm(this);
addWidgetToMainLayout(cadrForm);
addWidgetToMainLayout(teacherForm);
addWidgetToMainLayout(departmentForm);
addWidgetToMainLayout(categoriesForm);
addWidgetToMainLayout(postForm);
addWidgetToMainLayout(ranksAndDegreesForm);
addWidgetToMainLayout(teachersRankAndDegreeForm);
void MainWindow::start()
if (cf.exec())
this->show();
else
qDebug()<<"Need exit";
qApp->quit();
qDebug()<<"still working";
void MainWindow::addWidgetToMainLayout(QWidget *w)
ui->mainLayout->insertWidget(0, w);
ui->mainLayout->itemAt(0)->widget()->hide();
MainWindow::~MainWindow()
delete ui;
void MainWindow::resetMainLayout(QWidget *w)
int index;
if (current)
index = ui->mainLayout->indexOf(current);
ui->mainLayout->itemAt(index)->widget()->hide();
index = ui->mainLayout->indexOf(w);
if (index != -1) ui->mainLayout->itemAt(index)->widget()->show();
else
addWidgetToMainLayout(w);
resetMainLayout(w);
current = w;
setWindowTitle(current->windowTitle());
void MainWindow::on_actionCadr_triggered()
emit widgetChanged(cadrForm);
void MainWindow::on_actionTeacher_triggered()
emit widgetChanged(teacherForm);
void MainWindow::on_actionDepartment_triggered()
emit widgetChanged(departmentForm);
void MainWindow::on_actionPost_triggered()
emit widgetChanged(postForm);
void MainWindow::on_actionCategories_triggered()
emit widgetChanged(categoriesForm);
void MainWindow::on_actionRanksAndDegrees_triggered()
emit widgetChanged(ranksAndDegreesForm);
void MainWindow::on_actionTeachersRD_triggered()
emit widgetChanged(teachersRankAndDegreeForm);
还有 ConnectionForm - 它只是一个带有一些 GUI 且没有任何额外代码的 QDialog。
【问题讨论】:
什么是cf
?您是否至少打印了“需要退出”?
qApp->exit()
或 qApp->quit()
应该可以工作。当你尝试这些时究竟发生了什么?
@AndrewMedico,应用程序仍在运行。根据上面的代码,我有这个 qDebug 输出:调用 aApp-quit() 后“需要退出”和“仍在工作”
@LaszloPapp,shure,我收到消息“需要退出”。 cf 它的我的 QDialog 没有任何特定的逻辑。
我不关注。 cf.exec() 是一个阻塞调用,所以很明显你没有得到 else 分支,但是为什么你会得到打印呢?您是否明确关闭对话框,然后您希望应用退出?
【参考方案1】:
看起来问题是在 QApplication 事件循环实际开始之前,不允许您调用 QApplication::quit()
或 QApplication::exit()
。事件循环由QApplication::exec()
启动,所以你调用quit()
/exit()
太快了,它不会生效。
您可以通过移动 quit()
/exit()
调用使其处于事件循环中来解决此问题(例如,通过将您的 MainWindow::start()
代码移动到 QMainWindow::showEvent()
插槽),或者通过更改您的 MainWindow::start()
要返回一个值,请检查 main
中的该值,如果该值指示您的进程应提前退出,则退出(不调用 QApplication::exec()`)。
【讨论】:
好吧,让它成为你的。谢谢大家。 第一段是正确的。第二段提供了一种处理问题的相当复杂的方法。执行此操作的惯用方法是通过QMetaObject::invokeMethod
对方法调用进行排队。就是这样。【参考方案2】:
由于您“提前”启动对话框事件循环(即阻塞),因此您无法进入应用程序的事件循环。
如果这是有意设计,您最好调用 exit(3) 并移除应用程序事件循环。
如果您想让应用程序事件循环运行,那么您需要确保它在在您到达对话框执行点之前运行。
快速解决方法是在应用程序事件循环开始之前启动单次射击QTimer
,这将触发您的“开始”方法调用。
int main(int argc, char *argv[])
QApplication a(argc, argv);
MainWindow w;
w.start();
QTimer::singleShot(200, w, SLOT(start()));
return a.exec();
并将起点分别更改为插槽。
不过,从长远来看,您可能希望考虑使用按钮等来弹出对话框。
【讨论】:
感谢您对我所有问题的回答) 没有理由使用非零值计时器,因为应该在事件循环开始后立即执行start
调用。请注意,零持续时间单发计时器只是引用排队元调用的一种奇怪方式。所以,这样做的意图是最清楚的:QMetaObject::invokeMethod(&w, "start", Qt::QueuedConnection)
.
@KubaOber:该值来自文档,并且按照书面说明,它是一种快速解决方法。事实上,对于一个好的设计,这些都不是必需的。 invokeMethod 或 timer... 两者都很丑陋,但是带有 TODO 项的实用解决方法。 :-)
"该值来自文档" 这只是一般如何使用计时器的一个示例,并不意味着特别是任何人都应该编写看起来像它的代码。这就像平均值(总体平均值):仅仅因为您可以计算平均值并不意味着它是存在于总体中的值。
@KubaOber:我认为不值得争论哪种解决方法更丑陋。我将专注于主要的设计问题。丑陋的解决方法对我来说只是切线,真的,我永远不会使用的东西:正确,甚至不是invokeMethod。此外,如果您没有选择正确的连接类型,它将无法与 invokeMethod 等一起正常工作。我建议您将更多的精力放在实际重要的东西上。【参考方案3】:
将方法调用排队直到事件循环有机会运行的惯用方式是:
QMetaObject::invokeMethod(&w, "start", Qt::QueuedConnection);
因此,您的main
将变为:
int main(int argc, char *argv[])
QApplication a(argc, argv);
MainWindow w;
QMetaObject::invokeMethod(&w, "start", Qt::QueuedConnection);
return a.exec();
【讨论】:
以上是关于如何从任何地方完成 Qt 程序?的主要内容,如果未能解决你的问题,请参考以下文章