本文摘录自: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中剔除。