QT-检测Qwindow何时关闭

Qt - Detect when QWindow is closed

本文关键字:何时关 Qwindow 检测 QT-      更新时间:2023-10-16

我正在使用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文档说了以下内容:

[lastWindowClactosed]是从exec()发出的,当 窗口(即没有父母的窗口)已关闭。

由于我不使用exec(),因此没有发出此信号。是否有其他方法可以检测Qwindow何时关闭?

您可能应该使用QT内部事件循环来设计您的游戏应用程序。QT提供的" OpenGL窗口"示例显示了渲染循环的一个很好的例子。

但是,有可能在Qwindow上获得关闭事件。截至版本5.4.1,不提供方便的CloseEvent()函数。但是,您可以在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子类实现的InstalleventFilter()函数,包括Qwindow。

QGuiApplication *app = new QGuiApplication(argc,argv);
QWindow* window = new QWindow();
CloseEventFilter *closeFilter = new CloseEventFilter(window);
window->installEventFilter(closeFilter);
...

这是我的 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)您可以使用Qt::WA_DeleteOnClose标志创建QWindow。这是在窗口关闭时删除对象的。删除的任何QObject发出destroyed()信号,这意味着您应该能够将destroyed()信号连接到插槽。

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