Qt - 检测QWindow何时关闭

3
我正在使用Qt制作一个游戏,并且正在创建自定义的游戏循环,以便我可以精确地控制逻辑时间步长并以最大帧率进行渲染。
通常,要创建一个QWindow,你会这样做:
...
QGuiApplication app(argc,argv);
QWindow* window = new QWindow();
window.show();
app.exec();
...

“exec()”在窗口关闭时返回。但是,我是以下方式执行的:
QGuiApplication *app = new QGuiApplication(argc,argv);
     QWindow* window = new QWindow();
     window.show();
     while (!terminate_loop) {
          app->processEvents();
          GameUpdate();
          GameRender();
     }
     app->exit();

然而,当窗口关闭时,我的循环仍然在继续。我需要检测窗口何时关闭,以便我的循环可以终止。我已经尝试了以下方法来捕获窗口关闭的情况:
connect(app,SIGNAL(lastWindowClosed()),this,SLOT(windowClosed()));

以下槽应该在窗口关闭时被触发,但它从来没有被触发。当我使用app->exec()而不是手动处理事件时,它确实被触发。
void QTEngine::windowClosed() {
    terminate_loop = true;
}

经进一步调查,Qt文档如下所述:
“[lastWindowClosed]在执行exec()时发出,当关闭最后一个可见主窗口(即没有父窗口的窗口)时会触发。”
由于我没有使用exec(),因此该信号未被发出。 有没有其他方法可以检测QWindow何时关闭?
3个回答

4
你应该使用Qt内部事件循环来设计游戏应用程序。Qt提供的"OpenGL Window" example示例展示了一个好的渲染循环实现。
但是,在QWindow上获取关闭事件也是可能的。方便的closeEvent()函数在版本5.4.1中没有提供。但是,你可以在QWindow上安装一个事件过滤器对象并获取关闭事件。以下是这种事件过滤器对象实现的示例:
class CloseEventFilter : public QObject
{
     Q_OBJECT
public:
     CloseEventFilter(QObject *parent) : QObject(parent) {}

protected: 
     bool eventFilter(QObject *obj, QEvent *event)
     {
          if (event->type() == QEvent::Close)
          { 
               // Do something interesting, emit a signal for instance.
          }

          return QObject::eventFilter(obj, event);
     }

};

要将事件过滤器附加到窗口,您只需使用任何QObject子类(包括QWindow)实现的installEventFilter()函数即可。
QGuiApplication *app = new QGuiApplication(argc,argv);
QWindow* window = new QWindow();
CloseEventFilter *closeFilter = new CloseEventFilter(window);
window->installEventFilter(closeFilter);
...

0

这是我在编程中使用QQuickItem的方法:

  connect(
    this,
    &QQuickItem::windowChanged,
    this,
    [this](QQuickWindow* const w)
    {
      if (w)
      {
        connect(
          w,
          &QWindow::visibleChanged,
          this,
          [this](bool const v)
          {
            if (!v)
            {
              // window closing
            }
          }
        );
      }
    },
    Qt::DirectConnection
  );

close() 可以隐藏或销毁您的窗口。根据它的功能,您需要连接到 &QWindow::visibleChanged&QObject::destroyed


-1

我能想到两种可能的解决方案。我没有测试过这两个解决方案。

1)您可以使用Qt::WA_DeleteOnClose标志创建您的QWindow。这样做的作用是在关闭窗口时删除对象。任何被删除的QObject都会发出destroyed()信号,这意味着您应该能够将destroyed()信号连接到您的槽上。

2)您还可以重新实现您的QWindowQWidget::closeEvent()处理程序,并发出自己的自定义信号。


据我所知,您无法在QWindow实例上设置Qt :: WA_DeleteOnClose,只能在QWidget实例上设置。 - user1095108
1
两种解决方案都不适用于QWindow,因为它不是从QWidget派生的。 - fkorsa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接