I'm having a problem trying to insert a QML view into a native OSX window. I know it's possible, but I don't know what I'm doing wrong.
Basically, my goal is, given a native NSView* to then embed a QML based widget. The problem is that I get it to point where it does indeed renderer the qml inside the view but it creates an extra transparent window to the side and it doesn't seem to redraw the QML view properly.
Here's the code that I'm using (please disregard all the memory leaks):
@interface AppDelegate ()
-(void)processEvents;
@property(nonatomic) NSTimer* timer;
@property(nonatomic) QApplication* qt;
@end
@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
NSWindow* window = [[[NSApplication sharedApplication] windows] objectAtIndex:0];
NSView *view = [window contentView];
assert(view);
char* test[0];
int count = 0;
QApplication::instance()->setAttribute(Qt::AA_MacPluginApplication);
_qt = new QApplication(count, test);
QMacNativeWidget* native = new QMacNativeWidget(view);
assert(native);
QQuickWidget* qml = new QQuickWidget(native);
qml->setSource(QUrl(QStringLiteral("main.qml")));
QVBoxLayout* layout = new QVBoxLayout();
layout->addWidget(qml);
native->setLayout(layout);
qml->show();
native->show();
NSView* qmlView = (NSView*)native->winId();
[view addSubview:qmlView];
_timer = [NSTimer scheduledTimerWithTimeInterval:0.03 target:self selector:@selector(processEvents) userInfo:nil repeats:YES];
}
- (void)applicationWillTerminate:(NSNotification *)aNotification
{
// Insert code here to tear down your application
[_timer invalidate];
_qt->quit();
}
-(void)processEvents
{
_qt->processEvents();
_qt->sendPostedEvents(0,-1);
}
@end
And here's the simple qml:
import QtQuick 2.7
Item
{
visible: true
x: 0;
y: 0;
width: 100
height: 100
Rectangle
{
anchors.fill: parent
color: 'blue'
MouseArea
{
anchors.fill: parent
onClicked:
{
console.log(parent.color);
if(parent.color == '#0000ff')
parent.color = 'green';
else
parent.color = 'blue';
}
}
}
}
QQuickWidget
composities its content with other widget content in a slightly complex way, involving a framebuffer and offscreen window, which I suspect might explain the odd results you see - I would not expect it to work in a plugin situation.
The easiest option would be use a QQuickWindow
(or QQuickView
) with createWindowContainer
to turn the QWindow
into a QWidget
you can parent to your QMacNativeWidget
.
However, I think the most robust approach would be to ignore widgets and windows entirely, and integrate at the framebuffer level, using QQuickRenderControl
and an NSOpenGLView
. This is more work to code up but keeps the NSView hierarchy straightforward, and should give the best possible performance. You can either render directly into the native OpenGL view (which requires creating a QOpenGLContext
from the native context, possible since Qt 5.4), or into a framebuffer using a texture shared between the QtQuick and NSOpenGLContext
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With