如何在单个 App 中混合 Qt 和原生 iOS 用户界面元素?
Posted
技术标签:
【中文标题】如何在单个 App 中混合 Qt 和原生 iOS 用户界面元素?【英文标题】:How to mix Qt and native iOS user interface elements in a single App? 【发布时间】:2013-11-21 15:21:23 【问题描述】:我正在使用适用于 ios 的 Qt 5.2。
我想将 QtQuick 1.1 或 QWidgets 与原生 iOS 用户界面元素混合在一个应用程序中。
将 qml 视图嵌入到 UIView 中,必须切换到另一个窗口,将 UIView 嵌入到 qml 组件中,欢迎这方面的任何帮助!
【问题讨论】:
【参考方案1】:来晚了,可以在 Qt 宇宙之上显示一个原生 UIView。 嵌入 UIView 的技术是让 UIView “浮动”在层次内 QWidget 上,并在层次内小部件的几何形状发生变化时更新 UIView 的几何形状。对此的限制:您不能简单地将这样的小部件放置在 QTabWidget 内(然后您需要额外的代码来隐藏/显示 UIView)。此外,在包含 UIView 的 QMainWindow 上引发的 QMainWindows 也不起作用。
class View : public QWidget
...
private:
UITextView* m_TextView;
bool m_scheduled;
实现
View::View(QWidget* parent):QWidget(parent),m_Scheduled(false)
m_TextView=[[UITextView alloc] init];
QWidget* w= window();
UIView *parentView = reinterpret_cast<UIView *>(w->winId());
[parentView addSubview:m_TextView];
View::~View()
[m_TextView removeFromSuperview];
m_TextView=nil;
bool View::event(QEvent* e)
if (e->type()==QEvent::Move || e->type()==QEvent::Resize)
if (!m_scheduled)
m_scheduled=true;
QTimer::singleShot( 0, this, SLOT( updateGeo() ) );
return QWidget::event(e);
static inline QRect globalRect(QWidget* widget)
return QRect((widget)->mapToGlobal(QPoint(0,0)), (widget)->size());
void View::updateGeo()
m_scheduled=false;
QRect rg=globalRect(this);
QRect rw=globalRect(window());
CGRect cg=CGRectMake(rg.x(), rg.y()-rw.y(), rg.width(), rg.height());
[m_TextView setFrame:cg];
完整的示例项目可以在here找到。 另一种方法是使用 QML 查看器和 qmlRegisterType 来注册 QQuickItem 后代。
qmlRegisterType<MyTextView>("MyTextView", 1, 0, "MyTextView");
标题
class MyTextView : public QQuickItem
...
private:UITextView* m_view;
在实现中,geometryChanged 方法被覆盖以计算 UIView 坐标中的新矩形
static inline CGRect toCGRect(const QRectF &rect)
return CGRectMake(rect.x(), rect.y(), rect.width(), rect.height());
MyTextView::MyTextView(QQuickItem *parent /*= 0*/)
: QQuickItem(parent)
, m_view(0)
connect(this, SIGNAL(windowChanged(QQuickWindow*)), this, SLOT(onWindowChanged(QQuickWindow*)));
connect(this, SIGNAL(visibleChanged()), this, SLOT(onVisibleChanged()));
MyTextView::~MyTextView()
[m_view release];
void MyTextView::onWindowChanged(QQuickWindow* window)
if(!m_view)
m_view = [[UITextView alloc] init];
if (window != 0)
UIView *parentView = reinterpret_cast<UIView *>(window->winId());
[parentView addSubview:m_view];
else
[m_view removeFromSuperView];
void MyTextView::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
QQuickItem::geometryChanged(newGeometry, oldGeometry);
CGRect rc = toCGRect(mapRectToScene(newGeometry).toRect());
rc.size.width -= 2;
rc.size.height -= 2;
[m_view setFrame:rc];
void MyTextView::onVisibleChanged()
[m_view setHidden:isVisible()];
在 qml 文件中
...
import MyTextView 1.0
Window
visible: true
Column
anchors.fill: parent
anchors.margins: 5
spacing: 5
Rectangle
anchors.left: parent.left
anchors.right: parent.right
height: 100
border.width: 1
border.color: "red"
color: "#cccccc"
MyTextView
anchors.fill: parent
anchors.margins: 1
完整的示例项目可以在here找到。
【讨论】:
嗨,里奥!我刚开始玩Qt。有一个已经在其中完成的桌面应用程序,我想知道是否有办法重用 Qt 中为 iOS 应用程序构建的一些 UI 元素。是否有可能以某种方式提取在 QML 或纯 C++ 中完成的 UI 控件并在 iOS 应用程序中使用它们? @matthewfx 你的问题有点含糊。我的理解是您要求在原生 IOS 小部件中嵌入 Qt 小部件(层次结构)。我无法真正回答这个问题,也许有可能。无论如何,这需要对 Qt 的 IOS 内部实现有深入的了解。我不相信有官方 IOS 相当于 QMacNativeWidget doc.qt.io/qt-5/qmacnativewidget.html(见***.com/questions/41867731/…)。 感谢@Leo,看起来我们团队中另一位具有更多 C++ 经验的开发人员已经解决了问题。 @mattewfx 有趣!如果您不介意分享您的知识,您可以将您的问题作为一个单独的新 *** 问题提出,您的队友可以获得一些积分...:-)【参考方案2】:现在和不久的将来都是不可能的。
Qt 目前不支持 iOS 和 android 的原生 UI。Qt 小部件在 opengl 上下文中绘制。 Qt 应用就像 iOS 的全屏游戏。
More info.
【讨论】:
以上是关于如何在单个 App 中混合 Qt 和原生 iOS 用户界面元素?的主要内容,如果未能解决你的问题,请参考以下文章