Qt for iOS,Qt 与Objective C混合编程

2023-05-16

因为我写了一系列Qt的博文以及一本书《Qt on Android核心编程》,最近有好几个使用Qt的朋友问起 Qt for iOS 的事情,因为我在这方面的经验特别少,写不出系统的文章来,非常抱歉,不能给出令人满意的答复,推荐大家去看 Jason’s Home ,在我博客左侧边栏的友情链接里也有,他提供了 Qt for iOS 的一些非常有意义的文章,而且是基于实践的,他的 App 已经在 App Store 中上线。

至于我呢,在这篇文章里,简单介绍一些如何混合 Qt 与 OC 编程。

我要说的内容呢,大部分在 Qt 帮助里都有,请大家到索引模式下,键入”Qt for iOS”,找到 Qt for iOS 这篇文章来看。它介绍了搭建开发环境编译应用混合OC编程这三个方面,已经非常详细了。

如果你不想啃英文,那可以接着我的文章往下看。

项目设置

既然要聊 Qt 混合 OC 编程,首先要简单介绍一下 Objective C 。我只有一句话:Go,问搜索引擎去。因为我所知实在有限,怕误导了您。当然如果您不怕,往下看吧。

OC源文件介绍

首先我要说一下 Objective C 的源文件,后缀是.m 或 .mm ,在 .mm 文件里,可以直接使用 C++ 代码。所以,我们要混合 Qt 代码与 OC 代码,就需要在 Qt 项目里加入 mm 文件。

pro 文件配置

Qt SDK for Mac ,安装之后, Qt Creator 会使用 XCode 提供的编译工具链来编译代码,能够正确编译 mm 文件,也可以链接 iOS 的库文件。

而要混合 OC 代码,需要更改一下 pro 文件。一个是添加 mm 文件,一个是连接针对 iOS 的库文件。

添加源文件,使用 OBJECTIVE_SOURCES 这个变量,比如酱紫:


<code class="hljs fix has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-attribute" style="box-sizing: border-box;">OBJECTIVE_SOURCES +</span>=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;"> ocview.mm</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>  

链接库 XCode 提供的库,则需要使用 QMAKE_LFLAGS ,类似酱紫:


<code class="hljs lasso has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">ios {
    QMAKE_LFLAGS    <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">+=</span> <span class="hljs-attribute" style="box-sizing: border-box;">-framework</span> OpenGLES
    QMAKE_LFLAGS    <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">+=</span> <span class="hljs-attribute" style="box-sizing: border-box;">-framework</span> GLKit
    QMAKE_LFLAGS    <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">+=</span> <span class="hljs-attribute" style="box-sizing: border-box;">-framework</span> QuartzCore
    QMAKE_LFLAGS    <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">+=</span> <span class="hljs-attribute" style="box-sizing: border-box;">-framework</span> CoreVideo
    QMAKE_LFLAGS    <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">+=</span> <span class="hljs-attribute" style="box-sizing: border-box;">-framework</span> CoreAudio
    QMAKE_LFLAGS    <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">+=</span> <span class="hljs-attribute" style="box-sizing: border-box;">-framework</span> CoreImage
    QMAKE_LFLAGS    <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">+=</span> <span class="hljs-attribute" style="box-sizing: border-box;">-framework</span> CoreMedia
    QMAKE_LFLAGS    <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">+=</span> <span class="hljs-attribute" style="box-sizing: border-box;">-framework</span> AVFoundation
    QMAKE_LFLAGS    <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">+=</span> <span class="hljs-attribute" style="box-sizing: border-box;">-framework</span> AudioToolbox
    QMAKE_LFLAGS    <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">+=</span> <span class="hljs-attribute" style="box-sizing: border-box;">-framework</span> CoreGraphics
    QMAKE_LFLAGS    <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">+=</span> <span class="hljs-attribute" style="box-sizing: border-box;">-framework</span> UIKit
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li></ul>  

上面是我使用 Qt 针对 iOS 编程的配置。我使用了很多针对 iOS 的库,所以添加了很多 framework 。

“ -framework UIKit ”这种参数,是经由 Makefile 传递给 Clang 的参数,-framework 是用来指示要链接某个框架(或者说库)的关键字,它后面跟的是框架(库)名。

需要注意的是,我们使用针对 iOS 的库,不是通过“ LIBS += ”这种方式来引入哦。当然,你自己通过 Qt 实现的 .a 库,依然需要使用“ LIBS += ”这种方式。

指定plist文件

有时你需要为你的项目指定 plist 文件, plist 文件全名是 Property List ,后缀是 .plist 。它用来定义 iOS 应用的属性,比如 Bundle(iOS上的一个应用被称为一个 Bundle ) 的显示名字、可执行文件名字、签名、证书等等,当然也可以保存一些配置数据。具体的介绍参考 iOS 开发的文档吧。

要在 pro 文件里添加 plist ,要使用 QMAKE_INFO_PLIST 关键字。如下面酱紫:


<code class="hljs fix has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-attribute" style="box-sizing: border-box;">QMAKE_INFO_PLIST +</span>=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;"> MultiWindow.plist</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>  

好啦,关于 pro 文件中与混合使用 OC 相关的配置项,大体就这些了。接下来我们看如何写 Objective C 代码啦。

混合使用Objective C 代码

乖乖,很惶恐啊,这是我的弱项,没写过多少 OC 代码。所以,请不要问我 OC 有关的问题,我真不知道……

背景

我的示例,是在 QML 的界面上叠加iOS原生的界面,即 UIView、UIWindow之类的。因为 OC 是 C 的近亲,和 C++ 有着天然的血缘,混合起来特别方便哈,比 Android 上使用 JNI 编程好用多了。

不过有一点, OC 都适用 [] 这种语法来调用函数,使用 XCode 的话,语法提示和自动完成功能非常强大,基本不用思考的就能找到你要用的函数。而 Qt Creator 么,嘿嘿,就没这么好相与了,纯粹要手写哦。我当时都是开着 XCode 看 API 文档找的,比较痛苦。

QQuickView 是什么

我测试时的示例,用的是 Qt Quick App 项目模板,使用 QQuickView 来加载 QML 文档。这里也以此为例来说明。关于Qt Quick,可以看我博客的专栏,也可以看我的书《Qt Quick核心编程》,书里系统详细的介绍了Qt Quick的基本概念并提供了丰富的示例。

首先要说 QQuickView 到底是什么。

QQuickView 呢,其实是一个 UIView 。UIView 则是 iOS 开发框架里很多界面元素的根儿,比如 UIWindow 就是 UIView 的子类。

Qt 的 QQuickView 是一个 UIView ,创建了 QQuickView 实例后,就有了一个 UIView ,然后 Qt 玩了一些魔法,拿到了 UIView 的 OpenGL Context ,跑起了 Qt 的事件循环,在这个 OpenGL Context 上从零开始绘制了自己的场景和 UI 系统。

就这么简单,你可以查阅 Qt 源码来进一步了解。

需要注意的是, QML 界面元素的渲染,与 UIView 这种原生界面的渲染,不在一个线程中。而且 iOS 对 OpenGL ES 的支持很好,你可以同时使用多个 OpenGL Context 。更好的是,你可以窗口模式来创建一个 OpenGL Context 。不像 Android 版本哦, Qt 使用 OpenGL 的时候都是全屏模式,局部更新不支持,所以我们在 Android 上使用 QML 里的 Camera 和 VideoOutput 来开发拍照应用时, VideoOutput 必须是全屏模式(必须fill_parent)。而在 iOS 上,则没有这个限制了。看来 iOS 还是很美好的啦。

我靠,扯得有点儿远,最近写技术文章少了,越来越罗嗦了。言归正传吧。

因为 QQuickView 实际上就是一个 UIView ,所以可以强制转换为 UIView ,然后使用 OC 的方法来创建新的 UIView 或者 UIWindow ,这样就有了原生的 UI 组件了,你可以在这个原生的 UI 组件上使用 OpenGL 绘制自己的东西或者添加其它原生的控件,非常美好。

不过要说明的是,通过这种方法创建出来的 iOS 原生界面元素,会始终在 QML 界面之上,把 QML 场景里的界面元素给盖住。

混合代码

要使用 OC 的类库,需要在 mm 文件内包含相关的头文件,又有几部分工作要做。一个是在 pro 文件里加入 SDK 路径,使用 INCLUDEPATH 变量即可,不多说了。另外一点是在 mm 文件内包含 OC 的头文件,与 C++ 头文件一个理儿,不过要使用 #import 哦。类似酱紫:


<code class="hljs vala has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#import <UIKit/UIKit.h></span>
<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#import <GLKit/GLKit.h></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>  

包含了头文件,就可以使用 OC 类库了。比如我要在 QQuickView 上面创建一个新的 iOS 原生的 UIView ,.mm 文件里可以这样:


<code class="hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> addOCView(QQuickWindow *w)
{
    UIView *view = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">reinterpret_cast</span><UIView *>(w->winId());

    CGRect  viewRect = CGRectMake(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>);
    UIView* myView = [[UIView alloc] initWithFrame:viewRect];
    [myView setBackgroundColor:[UIColor colorWithRed:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1.0</span> green:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0.0</span> blue:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0.0</span> alpha:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1.0</span>]];
    [view addSubview: myView];
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>  

如你所见,我写了一个 addOCView 方法,它的参数是 QQuickView 。在 addOCView 方法里,我把 QQuickView 强制转换为 UIView 来使用。

我创建了一个新的 UIView ,设置了它的背景颜色,然后把它添加为 QQuickView 的子窗口。诺,就这么简单了。

说下 main.cpp ,看它如何使用 addOCView() 方法。代码如下:


<code class="hljs perl has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> main(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> argc, char <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*argv</span>[])
{
    QGuiApplication app(argc, argv);

    QQuickView viewer;
    viewer.setResizeMode(QQuickView::SizeRootObjectToView);
    viewer.setSource(QUrl(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"qrc:/main.qml"</span>));
    viewer.show();

    addOCView(&viewer);

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> app.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">exec</span>();
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li></ul>  

一点儿都不惊喜是吧,就是直接调用了 addOCView 哦。哈哈,确实如此了。

iOS 原生界面与 QML 元素的位置映射

混合使用 iOS 原生界面时,也可以达到原生界面与 QML 界面的无缝集成。关键就在于计算 QML 界面元素的位置,然后根据 QML 界面元素的位置来设置原生界面的位置。

QML元素位置换算

QML 提供了换算元素位置的方法,Item 有个方法,叫作 mapToItem() ,它可以把一个相对于 Qt Quick Item 的区域映射到另一个 Item 上,得到坐标了。比如你的 qml 文件是下面的样子:


<code class="hljs r has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">Rectangle {

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>

    Rectangle {
        id: videoLayer;
        anchors.margins: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8</span>;
        anchors.left: parent.left;
        anchors.right: parent.right;
        anchors.top: parent.top;
        anchors.bottom: actionBar.top;
        color: <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"green"</span>;
    }

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>

}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li></ul>  

你想把原生的 UIView 定位到 id 为 videoLayer 的元素内部,可以类似下面换算一个坐标并使用它:


<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">var coordinate = videoLayer<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.mapToItem</span>(null, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8</span>, videoLayer<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.width</span> - <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">16</span>, videoLayer<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.height</span> - <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">16</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
winUtil<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.addUIView</span>(coordinate<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.x</span>, coordinate<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.y</span>, coordinate<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.width</span>, coordinate<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.height</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>  

换算出的coordinate有 x 、 y 、 width 、 height 属性。当 mapToItem 的第一个参数为 null 时,换算的结果就是相对于 QQuickView 的。那我们在添加 UIView 时,就可以用这个换算结果来构造一个 CGRect 对象,用这个 CGRect 来初始化 UIView 的位置。

设置 UIView 的位置

前面示例代码中的 winUtil 是我在 C++ 内实现的一个辅助类,导出到了 QML 环境中。它的 addUIView 方法根据传入的坐标来设置原生 UIView 的位置。参考代码如下:


<code class="hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">    UIView *v = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">reinterpret_cast</span><UIView*>(view->winId());
    uiw = [[UIWindow alloc] initWithFrame:CGRectMake(x, y, width, height)];
    [v addSubview: uiw];</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>  

上面代码中,view 是 QQuickView 。这次我们创建 UIView 时使用了传入的 x 、 y 、 width 、 height,这样新建的 UIView 就和 QML 元素整合在一起了,看起来好像是一体的。


OK,这就是全部了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Qt for iOS,Qt 与Objective C混合编程 的相关文章

  • iOS SDK - 在蒙版图像上添加阴影

    如何在上面添加阴影UIImageView哪个有蒙版图像 我不是指矩形阴影 我也想对阴影应用相同的遮罩效果 给 UIImageView 提供阴影效果尝试下面的代码 1 import
  • 在同一个情节提要中重用另一个表 VC 中的单元格[重复]

    这个问题在这里已经有答案了 假设在情节提要中我有两个表视图控制器 A 和 B 在 A 控制器中 我确实创建了带有标识符的单元原型 VIENS 和 DU 在 B 控制器中 我需要使用带有标识符 DU 的单元 我不想再次在 B 控制器中创建相同
  • 从 UIButton 调用类外部的函数

    我有一个函数 我想在按下按钮时调用它 但与我迄今为止所做的任何事情不同 我希望能够从多个 ViewController 中的任何一个访问它 我不想在每个 ViewController 中重复相同的代码块 我尝试在 ViewControlle
  • 如何在iPhone真机上打开数据库sqlite文件?

    我正在通过电缆在我的真实设备中调试应用程序 我有一部 iPhone 6 我想检查我的数据库并使用 sqlite3 操作来查询我的结果 其他问题和教程解释了只能在模拟器中执行此操作 但我使用的是真正的 iPhone 在AppDelegate中
  • 是否包括触摸事件客户端X/Y 滚动?

    我正在尝试获取相对于的触摸坐标viewport来自触摸事件的浏览器 例如触摸启动 我尝试从 clientX Y 属性获取它们 但两者实际上都返回包括滚动在内的值 这是违反规范的 因为它说 clientX Y 应该返回坐标而不滚动 我尝试添加
  • Phonegap 之类的 Mac App Store 平台? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在使用phonegap 在iOS 本机应用程序中运行我的HTML JS 代码 有没有办法在 Mac
  • 应用程序在后台时远程推送通知 swift 3

    我有一个可以接收远程推送通知的应用程序 我已经实施了didReceiveRemoteNotification这样 func application application UIApplication didReceiveRemoteNoti
  • SwiftUI - 方向更改后,NavigationView 标题和后退按钮被夹在状态栏下

    每当我将设备旋转到横向并再次返回时 顶部NavigationView 包括标题和后退按钮 被剪切在状态栏下方 最小可重现示例 struct ContentView View var body some View NavigationView
  • Swift 尝试呈现 UIAlertController,其视图不在窗口层次结构中(在 TWTRShareEmailViewController 之后呈现)

    我在应用程序的注册过程中使用 Twitter 登录 我正在询问用户的电子邮件 一旦我得到它 我想展示一个 UIAlertController 这是我的代码 func askForTWMail if Twitter sharedInstanc
  • 如何快速使用 CoreLocation?

    我尝试过将 CoreLocation 与我的 Swift 应用程序一起使用 但没有运气 我有以下非常简单的代码 我已经链接了 CoreLocation 库 import UIKit import CoreLocation UIApplica
  • 使用 Swift 获取 UITableViewCell 中 UITextField 的 indexPath

    因此 我正在构建一个详细视图控制器应用程序 它显示一个包含两部分单元格的表格 标签和文本字段 我正在尝试检索文本字段值并将其添加到数组中 我尝试使用 textField superview superview 技术 但没有成功 func t
  • 在 iPad 上使用 OpenCV 避免碰撞

    我正在开展一个项目 需要使用 OpenCV 实现碰撞避免 这是在 iOS 上完成的 iOS 5 及以上版本即可 项目目标 这个想法是将 iPad 安装在汽车仪表板上并启动应用程序 应用程序应该从相机中抓取帧并进行处理 以检测汽车是否会与任何
  • iOS 9 的 UIAlertView 的替代方案?

    UAlertView在 iOS 9 及更高版本中已弃用 有什么替代方案吗 UIAlertView new UIAlertView alloc initWithTitle Success message Your InApp Purchase
  • 检测wifi是否启用(无论是否连接)

    对于 GPS 跟踪应用程序来说 在打开 WIFI 的情况下记录位置信号会导致数据非常不精确或存在间隙 在开始跟踪之前 我已使用可达性查询来检测 wifi 是否可用 问题是 如果进行该查询时 wifi 已启用但未连接到网络 则表明无法通过 w
  • 无法读取未定义的属性“messageHandlers”

    我想将 JavaScript 变量传递给 Swift 我在 JavaScript 中遇到错误并进行了搜索 但没有得到任何结果 错误是 类型错误 无法读取未定义的属性 messageHandlers 任何人都可以帮忙吗 我在 Xcode 中的
  • IQKeyboardManager 从 UITextField 导航到 UITextView

    IQKeyboardManager在键盘上方的工具栏中提供箭头以从一个跳转UITextField到另一个 但我正在寻找是否可以在混合之间跳转UITextFields and UITextViews 我知道完成此任务的正常程序 但我有兴趣知道
  • 将设备 3D 方向与太阳位置进行比较

    我正在开发一款应用程序 要求用户将 iPhone 对准太阳才能触发特殊事件 我可以基于陀螺仪和 CoreMotion 框架检索设备 3D 方向四元数 从中我可以获得偏航角 滚动角和俯仰角 我还可以根据当前日期和时间 GMT 以及纬度和经度计
  • 另一个 - “无法识别的选择器发送到实例”问题

    我查看了有关该主题的每个已发布问题 但没有一个给我解决方案 我的项目在很大程度上复制了开发库中的 AVPlayer 演示应用程序 减去清理功能 我有一个复制和粘贴AVPlayerDemoPlaybackView类 重命名为YOPlaybac
  • iOS 中的设备兼容性问题

    我们上传了一个应用程序 在第一个版本中 我们添加了设备功能 电话 以限制信息 plist 中的 iPhone 设备 在第二个版本中 我们忘记添加 电话 并提交给了应用商店 我们计划上传第三个版本 其中设备功能为 电话 但在提交到 App S
  • SpriteKit 中的攻击按钮

    我对 Xcode 有点陌生 一直在为我的班级制作 2d 游戏 我已经有一段时间遇到按钮问题了 我刚刚找到了为什么我的跳跃按钮不起作用的解决方案 但我还有一个攻击按钮 我设置了代码 使按钮显示在屏幕上并在按下时更改其图像 但是 我不知道要放入

随机推荐

  • jsp学习(一)

    jsp java 服务器页面 作用 xff1a 将内容的生成和信息的展示相分离 运行在服务端 xff0c 本质上就是一个servlet xff0c 产生的java文件和class保留在tomcat的word目录下 jsp脚本 xff1a l
  • jsp学习(二)

    jsp注释 xff1a html注释 lt gt 注释的内容只在页面上看不到 xff0c Java代码和html源代码都有 java注释 只在java代码中存在 jsp注释 lt gt 只在jsp页面中存在 xff0c 翻译成java文件之
  • 数据结构 _ PAT练习 _ 1064 Complete Binary Search Tree

    1064 Complete Binary Search Tree 原题基本分析代码 原题 点此链接1 基本分析 参考陈越姥姥的解题2 xff0c 主要的难点在于在何处插入新元素使得满足完全搜索二叉树的条件 猜测还有一种更通用的动态插入算法
  • 数据结构 _ 基础练习 _ 7-10 公路村村通

    原题 点此链接1 题目分析 可参考课本 xff08 高等教育出版社 陈越 数据结构 xff09 P225中关于prim算法的描述解题 本题相对于课本描述的算法来说 xff0c 不需要考虑 父节点 xff08 parent xff09 xff
  • KEIL问题二[function的内容空没有显示(占用CPU过高)][报错Error: Encountered an improper argument]

    function的内容空没有显示 不知道怎么回事也没有任何复现的办法 装了各个版本的KEIL都不能够接解决这个问题 最终无意中新建立了一个代码分组彻底解决这个问题 KEIL Functions Bug 当出现 function的bug的时候
  • 数据结构 _ 基础练习 _7-11 关键活动 _ 非递归解法

    1 原题 点此链接1 2 解题思路 写在前面 xff0c 参考博文2 本题其实考察的就是课本 xff08 高等教育出版社 陈越 数据结构 xff09 6 8节 关键路径的内容 课本中给出了三个公式 xff0c 以分别计算三个要素 xff1a
  • 数据结构 _ PAT练习 _ 7-13 Insert or Merge

    原题 点此链接1 解题思路 参考课本 xff1a 高等教育出版社 陈越主编 数据结构 参考视频 xff1a MOOC 浙江大学 数据结构与算法 本题主要考察的是简单插入排序 xff08 课本P268 xff09 以及归并排序的非递归算法 x
  • 数据结构 _ 基础练习 _ 7-14 Insertion or Heap Sort

    原题 点此链接1 题目分析 与前一题 Insert or Merge 相同2 xff0c 同样考察的是插入排序算法以及堆排序算法 算法如下 xff1a 首先需要判断是插入排序还是堆排序 xff0c 由于插入必然是 有序序列 43 相同的序列
  • Matlab v_findpeaks代码

    这里写自定义目录标题 Matlab v findpeaks代码写在前面代码 Matlab v findpeaks代码 写在前面 本函数主要用于寻找数据的上下极值点 xff0c 可以用于求取包络 参考链接 xff1a http www ee
  • Android实现MP4边下边播(边缓存边播放、在线播放)原理与代码

    推荐一款全平台广告聚合SDK ADEasy https blog csdn net u013640004 article details 105416193 对于这套方法我已经封装成库 xff0c 可以直接下载使用 MP4Info1 0 2
  • 如何实现PCB走线开窗上锡

    特别说明 xff1a 电路中需要驱动8路继电器 xff0c 当多路继电器闭合导通时电流大增 xff0c 为保证实际效果 xff0c 在加宽电流线的同时 xff0c 希望去掉电流线上的阻焊层 绿油层 xff0c 板子做出来以后 xff0c 就
  • sqlite3无法使用方向键解决方法

    Question xff1a sqlite3打开数据库后无法使用方向键 xff0c 没有命令回滚功能 Answer xff1a 缺少插件形成 xff0c 解决办法是安装libreadline dev sudo apt get install
  • 关于笔记本linux亮度调节

    Laptop安装linux 系统后 xff0c 开机默认亮度是最大 xff0c 每次开机都很刺眼 xff0c 开机后调节好亮度后 xff0c 重启又恢复了 现在介绍可以永久设置屏幕亮度的方法 xff0c 这样就不用每次开机都设置亮度那么麻烦
  • LINUX下挂载exfat格式u盘或移动硬盘

    我的u盘本来是ntfs格式的 xff0c 本来在linux系统下可以读 xff0c 但由于我双系统 xff0c u盘经常在windows和linux中插来插去 xff0c 后来经常导致u盘在linux中无法挂载 xff0c 提示说未知文件系
  • C语言 消息队列

    消息队列 xff08 也叫做报文队列 xff09 能够克服早期unix通信机制的一些缺点 作为早期unix通信机制之一的信号能够传送的信息量有限 xff0c 后来虽然POSIX 1003 1b在信号的实时性方面作了拓广 xff0c 使得信号
  • Norder软件[FDS和fstorage]

    FDS和fstorage 本文摘录于 xff1a https www cnblogs com iini p 9338169 html只是做学习备份之用 xff0c 绝无抄袭之意 xff0c 有疑惑请联系本人 xff01 这里摘抄重点 根据有
  • C语言 select函数使用

    在编程的过程中 xff0c 经常会遇到许多阻塞的函数 xff0c 好像read和网络编程时使用的recv recvfrom函数都是阻塞的函数 xff0c 当函数不能成功执行的时候 xff0c 程序就会一直阻塞在这里 xff0c 无法执行下面
  • linux 开机grub rescue修复

    安装linux系统后 系统的引导就会变成grub引导 假如对硬盘进行分区管理或一些其它操作后 开机进不去grub引导 界面显示黑屏 然后显示grub rescue gt 的字样时 就需要自己手动修复grub了 1 使用ls命令 ls执行命令
  • Qt5编译时出现<QtGui/QApplication> ---> No such file or directory错误解决办法

    Qt5的更新把目录结构都改变了 然后一些类也去掉了功能 本来我在qt4上写的程序放到qt5编译 马上弹出 lt QtGui QApplication gt gt No such file or directory错误 解决办法 安装libq
  • Qt for iOS,Qt 与Objective C混合编程

    因为我写了一系列Qt的博文以及一本书 Qt on Android核心编程 xff0c 最近有好几个使用Qt的朋友问起 Qt for iOS 的事情 xff0c 因为我在这方面的经验特别少 xff0c 写不出系统的文章来 xff0c 非常抱歉