Как встроить вид QML в собственное окно

У меня возникла проблема при попытке вставить представление 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 ответ

QQuickWidget объединяет его содержимое с другим содержимым виджета немного сложным образом, включая кадровый буфер и закадровое окно, что, как я подозреваю, может объяснить странные результаты, которые вы видите - я не ожидал бы, что он будет работать в ситуации с плагином.

Самый простой вариант будет использовать QQuickWindow (или же QQuickView) с createWindowContainer повернуть QWindow в QWidget Вы можете родителя к вашему QMacNativeWidget,

Тем не менее, я думаю, что наиболее надежный подход - полностью игнорировать виджеты и окна и интегрироваться на уровне кадрового буфера, используя QQuickRenderControl и NSOpenGLView, Это больше работы для кодирования, но она сохраняет иерархию NSView и должна обеспечивать максимальную производительность. Вы можете выполнить рендеринг непосредственно в собственное представление OpenGL (которое требует создания QOpenGLContext из собственного контекста, возможно начиная с Qt 5.4), или в кадровый буфер, используя текстуру, совместно используемую QtQuick и NSOpenGLContext,

Другие вопросы по тегам