Reputation: 1192
I'm using Qt 5.2 for iOS.
I'd like to mix QtQuick 1.1 or QWidgets with native iOS user interface elements in a single app.
Embedding a qml view into a UIView, having to switch to another window, embedding a UIView into a qml component, any help in that direction is welcome !
Upvotes: 4
Views: 3183
Reputation: 1025
Coming a bit late, it is possible to show a native UIView on top of the Qt universe. The technique for embedding an UIView is letting the UIView "float" over an in-hierarchy QWidget and update the UIView's geometry whenever the geometry of the in-hierarchy widgets changes. The limitation for this: you can't simply place such a widget inside a QTabWidget (then you need additional code for hiding/showing the UIView). Also QMainWindows being raised over the QMainWindow containing the UIView won't work.
class View : public QWidget
...
private:
UITextView* m_TextView;
bool m_scheduled;
implementation
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];
}
The complete sample project can be found here. Another approach is using a QML viewer and qmlRegisterType to register a QQuickItem descendant.
qmlRegisterType<MyTextView>("MyTextView", 1, 0, "MyTextView");
header
class MyTextView : public QQuickItem
...
private:UITextView* m_view;
in the implementation the geometryChanged method is overriden to compute the new rectangle in UIView coordinates
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()];
}
and in the qml file
...
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
}
}
}
}
The complete sample project can be found here.
Upvotes: 2
Reputation: 2572
It's impossible right now and in near future.
Qt doesn't support native UI for iOS and Android right now.Qt widgets are drawing in opengl context. Qt app is like full-screen game for iOS.
Upvotes: 0