1

主窗口.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

主窗口.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
}

主.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() 将关闭窗口并结束应用程序。

为什么会有这种行为差异?

4

1 回答 1

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 具有允许使用 lambda 的新连接语法,而 QtConcurrent 已经能够使用 lambda QTimer 或更具体地说 QTimer::singleShot() 两者都缺乏。为 QTimer::singleShot() 提供函数指针语法和 lambda 支持会很方便(并且一致)。

编辑 2

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

于 2013-04-26T18:22:07.747 回答