<!- 2018年2月26日修改:由于很多小伙伴没看懂所以在结尾加入另外一个示例来说明>
<!- 2018年9月5日修改:评论有人提到可能显卡驱动原因导致程序崩溃,结尾处例举了一个可能的处理方案>
--------------------------------------------------------------------------------------------
由于QWidget和QML窗口的渲染方式不一样,所以他们不能互相嵌入。
但有时候就是有这种需求:QML窗口需要嵌入到QWiget窗口中,或则是QWiget窗口需要嵌入到QML窗口中。
这个时候该怎么办呢?
我这里先记录如何将QWidget窗口嵌入到QML窗口中!
(原理:QML窗口其实是QWindow窗口,为了互通,需要把QWidget转换为QWindow)
先用Qt创建一个非常简单的QWiget窗口,界面如下:
我把这个界面类叫做Form类。
然后我们再创建一个QML文件,代码如下:
Window
{
id: mainWindow
width: 600
height: 300
property alias titleBar: title
Rectangle
{
id:title
width: parent.width
height:25
color: "gray"
Text
{
anchors.centerIn: parent
text: "title: hello widget"
font.bold: true
}
}
}
这段代码的运行结果如下:
接下来,将QWidget类型的Form对象添加到QML窗口中的空白区域:
Form fm;
fm.setAttribute(Qt::WA_NativeWindow);
fm.windowHandle()->setParent(mainWindow);
fm.show();
fm.move(0,25);
我们为Form创建了一个QWindow对象,并且把父窗口设置成了QML窗口,然后将窗口坐标设置成了(0,25)<因为标题栏高25px,如果不这样那么Form会挡住标题栏>
运行之后的效果如图:
这样就完成了QWiget到QML窗口的添加,但我们发现QWidget的没有和QML窗口尺寸相适应,
这个问题我们只需要重载Form的eventFilter函数,并且调用QML窗口的installEventFilter(Form*)然后在里面处理resize事件就好了!
以上就是QWidget嵌入QML窗口的示例!
<!2月26日添加的示例>
随便新建一个QML项目,记得pro文件里面QT += croe gui widgets
默认新建的QML项目main.qml:
import QtQuick 2.3
import QtQuick.Window 2.2
Window {
visible: true
MouseArea {
anchors.fill: parent
onClicked: {
Qt.quit();
}
}
Text {
text: qsTr("Hello World")
anchors.centerIn: parent
}
}
main.cpp:
//#include <QGuiApplication>
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QQmlComponent>
#include <QQmlEngine>
#include <QWindow>
#include <QDebug>
#include <QPushButton>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// QQmlApplicationEngine engine;
// engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
QQmlEngine* engine = new QQmlEngine;
QQmlComponent* component = new QQmlComponent(engine);
component->loadUrl(QUrl(QStringLiteral("qrc:/main.qml")));
if(component->isReady())
{
//TODO: root 即为qml窗口
QWindow* root = qobject_cast<QWindow*>(component->create());
if(root)
{
root->show();
//TODO: 构造一个红色的pushButton嵌入root
//** 这一步就是关键一步,要嵌入到QML窗口中的widgets都可以这样参考
QPushButton* btn = new QPushButton;
btn->setStyleSheet("background-color:red;");
btn->setAttribute(Qt::WA_NativeWindow);
btn->windowHandle()->setParent(root);
btn->show();
}
else
{
qDebug() << component->errorString();
}
}
else
{
qDebug() << component->errorString();
}
return app.exec();
}
运行之后就看到红色按钮被嵌入到qml窗口中了。
————————————————————————————————————————————————
<!- 2018年9月5日添加:评论有人提到可能显卡驱动原因导致程序崩溃,此处例举了一个可能的处理方案>
QApplication::setAttribute(Qt::AA_UseSoftwareOpenGL, true);
程序启用软件渲染,不过会降低运行效率。如果在意运行效率则可以尝试更新OPENGL驱动。
<!- 如果本示例还不能满足你的需求,那么可以参考以下我的另一篇文章>