为什么close()只能在一种方法中工作而不能在另一种方法中工作?

时间:2013-04-26 17:53:15

标签: c++ qt qt5

mainwindow.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    void test();

private slots:
    void on_pushButton_clicked();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

mainwindow.cpp:

#include "mainwindow.h"
#include "ui_mainwindow.h"

void MainWindow::test()
{
    close(); // Line 1
}

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_clicked()
{
    close(); // Line 2
}

main.cpp中:

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    w.test();

    return a.exec();
}

如果我注释掉第2行中的close(),第1行中的close()将关闭窗口并使应用程序继续运行。

如果我注释掉第1行中的close(),则第2行中的close()会关闭窗口并结束应用程序。

为什么这种行为存在差异?

1 个答案:

答案 0 :(得分:0)

原因是在启动事件循环(w.test())之前调用a.exec()调用,因此不会导致任何其他事件发生,这可能与close()有关操作QMainWindow

在第二种方法中,您的close()函数将在事件循环开始后调用,更好地说,在您的事件循环中(当您单击按钮时,您将被分派到on_pushButton_clicked()方法,close()将通知您的应用程序需要结束。

为了在事件循环中运行test()函数,请使用单次定时器:

//Qt 4 - in Qt 5, you can work this out without helper slot:

class MainWindow: public QMainWindow{
    //...   
    void test();
    //...
public slots:
    void testHelper(){ test(); }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    QTimer::singleShot(0, &w, SLOT(testHelper()));

    return a.exec();
}

修改

似乎Qt5的新connect语法无法帮助您避免额外的广告位[1]

  

Qt5有一个新的连接语法允许使用lambdas和QtConcurrent已经能够使用lambdas QTimer或更具体的QTimer :: singleShot()缺乏这两者。   为QTimer :: singleShot()提供函数指针语法和lambda支持也很方便(也是一致的)。

修改2

更准确地说,当您调用QMainWindow::close()时,会引发QMainWindow::closeEvent(QCloseEvent *)事件,通常应该在当前事件循环中处理它。由于在调用close时没有事件循环,因此不会捕获此事件,也不会导致应用程序退出。