Qt 6平台的特有API

2023-03-17 14:19:13 浏览数 (3)

本文摘录自:https://www.qt.io/blog/platform-apis-in-qt-6

  虽然Qt解决了编写应用程序的许多特有任务,但始终存在Qt无法解决的极端情况,或者在特定于平台的API或其他工具包之上构建功能更有意义的情况。我们要为Qt 6解决的任务之一是清理和协调访问平台特定功能所需的各种机制

  现在,我们将在Qt 6中查看这项工作的结果。完整的文档可在文档快照中找到,这是新的Platform Integration部分的一部分。

1. 类型转换

  Qt的许多基本数据类型,例如QString,QPoint或QImage,都提供与本机之间等效类型的转换。

例如,要在Apple平台上获取当前用户的用户名:

代码语言:javascript复制
NSProcessInfo *processInfo = NSProcessInfo.processInfo;
QString userName = QString::fromNSString(processInfo.userName)

  有关所有转换类型的完整列表,请参见"类型转换"概述。

2. 窗口嵌入

  由基础平台API创建的Windows既可以用作Qt窗口的父容器,也可以作为子窗口嵌入到Qt窗口中。

  如果应用程序主要使用本机平台API编写,但是应用程序的某些部分使用Qt(例如绘制专用UI)时,前者很有用。要将Qt嵌入到本机应用程序的窗口层次结构中,请使用QWindow::winId()获取Qt窗口的本机句柄,然后使用本机API将窗口重新纳入本机UI。

  如果本机平台或其他工具包将专用控件公开为本机窗口,则后者很有用。通过使用QWindow::fromWinId()将本机窗口句柄包装在QWindow中,然后可以像其他任何QWindow一样将窗口重新父级到Qt窗口层次结构中。要将这个QWindow重新父化为基于Qt Widget的UI,请使用特定于Widget的QWidget::createWindowContainer()函数。

3. 事件处理

  Qt中的大多数事件处理用例已通过跨平台事件传递( 通过QWindow::event()和友元,或通过QObject::installEventFilter() )得到了充分覆盖。

&emsp 上面做法还是不够的,Qt还提供对本机事件传递的访问。可以使用QCoreApplication::installNativeEventFilter()安装接收所有本地事件的全局事件过滤器,而可以在QWindow::nativeEvent()中处理每个窗口的本地事件。

  注意:干扰本机事件流可能会使Qt处于不一致状态。这些API应该主要用于增强Qt的现有事件处理,例如,Qt尚未处理的事件。

4. 本机接口

  上面提到的API未涵盖的平台特定功能由新的通用本机接口机制处理。该机制替代了平台面向用户的API以及QPA级别(QPlatformNativeInterface)的API。这些接口提供对它们扩展的类的本机或特定于平台的API的访问。

  这些接口位于QNativeInterface命名空间中,并涵盖了一些用例,例如访问基础本机句柄,采用现有的本机句柄或提供平台特定的API。

  大多数旧平台API可以在QNativeInterface::Private名称空间中找到,因为这些API大部分被其他内部代码使用。随着时间的流逝,我们将基于反馈和用例公开更多这些API。

4.1 访问基础本机句柄

  在Qt中未公开本机平台的功能的情况下,访问由Qt维护的本机句柄,并使用这些句柄调用本机API可能会有所帮助。

  例如,在MacOS为了访问底层的NSOpenGLContext QOpenGLContext,经由QNativeInterface::QCocoaGLContext本地接口:

代码语言:javascript复制
using namespace QNativeInterface;
if (auto *cocoaGLContext = glContext->nativeInterface<QCocoaGLContext>())
    [cocoaGLContext->nativeContext() makeCurrentContext];

  上面代码中,通过QOpenGLContext::nativeInterface()访问器访问本机接口,该访问器确保请求的接口可用,否则返回空指针。然后,可以通过nativeContext()访问到NSOpenGLContext。

4.2 采用现有的本机句柄

  与窗口嵌入用例类似,在某些情况下,本机平台或其他工具包已创建要传递给Qt的本机句柄-包装现有的句柄而不是创建新的句柄。

  例如,采用现有的NSOpenGLContext,并使用它与Qt创建的上下文共享资源:

代码语言:javascript复制
using namespace QNativeInterface;
QOpenGLContext *adoptedContext = QCocoaGLContext::fromNativeContext(nsOpenGLContext);
anotherContext->setShareContext(adoptedContext);

  上下文是由QNativeInterface::QCocoaGLContext特定于平台的工厂方法创建。

4.3 访问平台特定的API

  在某些情况下,虽然API特定于平台而不能包含在跨平台Qt类中,但是仍然有用。这些API的访问方式与通过nativeInterface()访问本机句柄的方式相同,也可以作为本机接口中的静态函数直接使用。

  例如,要在Windows上获取OpenGL模块句柄:

代码语言:javascript复制
using namespace QNativeInterface;
HMODULE moduleHandle = QWGLContext::openGLModuleHandle();

  或通过其平台窗口句柄来调整Windows窗口的边框行为:

代码语言:javascript复制
using namespace QNativeInterface::Private;
if (auto *windowsWindow = dynamic_cast<QWindowsWindow*>(window->handle()))
    windowsWindow->setHasBorderInFullScreen(true);

4.4 源和二进制兼容性

  需要注意的是,本机接口API没有源或二进制兼容性保证,这意味着使用这些接口的应用程序只能保证与其开发的Qt版本一起使用。这使我们能够根据需要调整和添加这些API,从而使它们在跟踪基础本机功能方面更加灵活。

5. 附加模块

  "extras"模块已在Qt 6.0中剔除。

0 人点赞