如何将QML视图嵌入到本机窗口中

时间:2016-08-05 15:00:08

标签: qt cocoa qml qquickview qquickwidget

我在尝试将QML视图插入本机OSX窗口时遇到问题。我知道这是可能的,但我不知道自己做错了什么。

基本上,我的目标是,给定一个原生的NSView *然后嵌入一个基于QML的小部件。问题是,我确定它确实在视图中渲染了qml,但它创建了一个额外的透明窗口,它似乎没有正确地重绘QML视图。

这是我使用的代码(请忽略所有内存泄漏):

@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

这是简单的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';
            }
        }
    }
}

1 个答案:

答案 0 :(得分:1)

QQuickWidget以稍微复杂的方式将其内容与其他窗口小部件内容相结合,涉及帧缓冲和屏幕外窗口,我怀疑这可能会解释您看到的奇怪结果 - 我不希望它在插件情况下工作

最简单的选择是使用QQuickWindow(或QQuickViewcreateWindowContainerQWindow转换为您QWidget父母的QMacNativeWidget { {1}}。

但是,我认为最强大的方法是完全忽略小部件和窗口,并使用QQuickRenderControlNSOpenGLView在帧缓冲级别进行集成。这是编写代码的更多工作,但保持NSView层次结构简单明了,并且应该提供最佳性能。您可以直接渲染到本机OpenGL视图(这需要从本机上下文创建QOpenGLContext,可能从Qt 5.4开始),或者使用在QtQuick和NSOpenGLContext之间共享的纹理进入帧缓冲区。 / p>