如何在单个 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 用户界面元素?的主要内容,如果未能解决你的问题,请参考以下文章

如何辨别app是原生开发的还是h5开发的 或是混合开发

混合app开发,h5页面调用ios原生APP的接口

什么是混合app开发

原生项目如何从零开始集成 React Native

教你如何使用Flutter和原生App混合开发

ios&h5混合开发项目仿app页面跳转优化