QWidget嵌入QML窗口中

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/r5014/article/details/72528418

<!- 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驱动。

猜你喜欢

转载自blog.csdn.net/r5014/article/details/72528418