Как встроить вид 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
,