2016-08-05 19 views
9

Mam problem podczas próby wstawienia widoku QML do macierzystego okna OSX. Wiem, że to możliwe, ale nie wiem, co robię źle.Jak osadzić widok QML w macierzystym oknie

Zasadniczo moim celem jest, biorąc pod uwagę natywny NSView *, aby osadzić widget oparty na QML. Problem polega na tym, że dostaję go do punktu, w którym rzeczywiście renderuje qml wewnątrz widoku, ale tworzy dodatkowe przezroczyste okno z boku i nie wydaje się, aby poprawnie odrysowywać widok QML.

Oto kod, który używam (prosimy zignorować wszelkie przecieki pamięci):

@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 

A oto prosty 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'; 
      } 
     } 
    } 
} 

Odpowiedz

1

QQuickWidget composities jego treść z innej zawartości widget to nieco skomplikowany sposób, obejmujący framebuffer i okno poza ekranem, które, jak podejrzewam, mogą wyjaśnić dziwne wyniki, jakie widzisz - nie oczekiwałbym, że zadziała w sytuacji wtyczki.

Najprostszym rozwiązaniem byłoby użyć QQuickWindow (lub QQuickView) z createWindowContainer obrócić QWindow w QWidget możesz rodzica na swojej QMacNativeWidget.

Myślę jednak, że najbardziej solidne podejście byłoby zignorować widżety i okna całkowicie i zintegrować na poziomie bufora ramki, używając QQuickRenderControl oraz NSOpenGLView. To jest więcej pracy do kodowania, ale utrzymuje hierarchię NSView prostą i powinna dać najlepszą możliwą wydajność. Możesz renderować bezpośrednio do natywnego widoku OpenGL (który wymaga utworzenia QOpenGLContext z natywnego kontekstu, możliwego od Qt 5.4), lub do bufora ramki używającego tekstury współdzielonej między QtQuick i NSOpenGLContext.

+0

Dziękuję bardzo za poświęcenie czasu na odpowiedź. Zbadam te opcje i zobaczę, czy działają. W międzyczasie, czy byłbyś w stanie wskazać mi przykład gdzieś zrealizowany? – bitwise

+0

Dla 'createWindowContainer' wystarczy spojrzeć na dokumenty - zajmie to' QQuickWindow' i zawinie go w widgecie. To będzie działać lepiej w scenariuszu wtyczki niż QQuickWidget, ze względu na różne opcje implementacji. –

+0

Dla QQuickRenderControl, zobacz przykład 'QQuickRenderControl' dostarczany z Qt - powinieneś zamienić' WindowSingleThreaded' w tym przykładzie na 'NSOpenGLView' i opakować skojarzony' openGLContext' w 'QOpenGLContext' aby użyć go z renderowaniem kontrola. –