以上是效果图, 整个窗口是 qml 窗口
核心代码
#ifndef WIDGETANCHOR_H
#define WIDGETANCHOR_H#include <QObject>
#include <QQuickItem>
#include <QWidget>
#include <QQmlApplicationEngine>
#include <QQmlContext>class WgtAnchorMgr: public QObject
{QWidget * _p_wgt = nullptr;QQuickItem* _p_quick_item =nullptr;
public:WgtAnchorMgr();WgtAnchorMgr(QWidget* pWidget, QQuickItem* pItem);bool init_info(QWidget* pWidget, QQuickItem* pItem);bool init_info(QQmlApplicationEngine &engine, const QString &object_name, QWidget* pWidget);bool init_info(QQmlApplicationEngine &engine, const QString &object_name, std::function<QWidget *()> fun);void init_connect();~WgtAnchorMgr();private:void updateGeometry();
};#endif // WIDGETANCHOR_H
#include "WgtAnchorMgr.h"#include <QQuickItem>
#include "WgtAnchorMgr.h"
#include <QQuickWidget>
#include <QQmlContext>WgtAnchorMgr::WgtAnchorMgr()
{}WgtAnchorMgr::WgtAnchorMgr(QWidget* pWidget, QQuickItem* pItem): QObject(pWidget), _p_wgt(pWidget), _p_quick_item(pItem)
{connect(_p_quick_item, &QQuickItem::xChanged, this, &WgtAnchorMgr::updateGeometry);connect(_p_quick_item, &QQuickItem::yChanged, this, &WgtAnchorMgr::updateGeometry);connect(_p_quick_item, &QQuickItem::widthChanged, this, &WgtAnchorMgr::updateGeometry);connect(_p_quick_item, &QQuickItem::heightChanged, this, &WgtAnchorMgr::updateGeometry);updateGeometry();
}bool WgtAnchorMgr::init_info(QWidget *pWidget, QQuickItem *pItem)
{if(nullptr == pWidget || nullptr == pItem)return false;_p_wgt = pWidget;_p_quick_item = pItem;return true;
}bool WgtAnchorMgr::init_info(QQmlApplicationEngine &engine, const QString &object_name, QWidget *pWidget)
{if(nullptr == pWidget)return false;for(auto obj : engine.rootObjects()){if(obj->findChild<QQuickItem*>("widgetItem")){_p_quick_item = obj->findChild<QQuickItem*>(object_name);if(nullptr == _p_quick_item)continue;QWindow * mainWindow = qobject_cast<QWindow*>(obj);WId proc2Window_HWND = mainWindow->winId();_p_wgt = pWidget;_p_wgt->setProperty("_q_embedded_native_parent_handle", QVariant(proc2Window_HWND));_p_wgt->setWindowFlags(Qt::Widget|Qt::FramelessWindowHint);_p_wgt->winId();_p_wgt->windowHandle()->setParent(mainWindow);engine.rootContext()->setContextProperty("WidgetAnchor", this);return true;}}return false;
}bool WgtAnchorMgr::init_info(QQmlApplicationEngine &engine, const QString &object_name, std::function<QWidget *()> fun)
{for(auto obj : engine.rootObjects()){if(obj->findChild<QQuickItem*>("widgetItem")){_p_quick_item = obj->findChild<QQuickItem*>(object_name);if(nullptr == _p_quick_item)continue;QWindow * mainWindow = qobject_cast<QWindow*>(obj);WId proc2Window_HWND = mainWindow->winId();_p_wgt = fun();if(nullptr == _p_wgt)return false;_p_wgt->setProperty("_q_embedded_native_parent_handle", QVariant(proc2Window_HWND));_p_wgt->setWindowFlags(Qt::Widget|Qt::FramelessWindowHint);_p_wgt->winId();_p_wgt->windowHandle()->setParent(mainWindow);engine.rootContext()->setContextProperty("WidgetAnchor", this);return true;}}return false;
}void WgtAnchorMgr::init_connect()
{connect(_p_quick_item, &QQuickItem::xChanged, this, &WgtAnchorMgr::updateGeometry);connect(_p_quick_item, &QQuickItem::yChanged, this, &WgtAnchorMgr::updateGeometry);connect(_p_quick_item, &QQuickItem::widthChanged, this, &WgtAnchorMgr::updateGeometry);connect(_p_quick_item, &QQuickItem::heightChanged, this, &WgtAnchorMgr::updateGeometry);updateGeometry();
}WgtAnchorMgr::~WgtAnchorMgr()
{disconnect(_p_quick_item, 0, 0, 0);delete _p_wgt;qDebug()<<"=============~WgtAnchorMgr==============";}void WgtAnchorMgr::updateGeometry()
{if (_p_quick_item){QRectF r = _p_quick_item->mapRectToItem(0, QRectF(_p_quick_item->x(), _p_quick_item->y(), _p_quick_item->width(), _p_quick_item->height()));qDebug()<<" r ===="<<r;_p_wgt->setGeometry(r.toRect());}_p_wgt->show();
}
使用
#include <QApplication>
#include <QQmlApplicationEngine>
#include "mywgt.h"
#include <QQuickItem>
#include "WgtAnchorMgr.h"
#include <QQuickWidget>
#include <QQmlContext>
int main(int argc, char *argv[])
{
#if defined(Q_OS_WIN)QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endifQApplication app(argc, argv);QQmlApplicationEngine engine;engine.load(QUrl(QStringLiteral("qrc:/main.qml")));if (engine.rootObjects().isEmpty())return -1;// auto pqw = new QQuickWidget;
// pqw->setSource(QUrl(QStringLiteral("qrc:/main.qml")));
// pqw->setResizeMode(QQuickWidget::SizeRootObjectToView);
// pqw->setAttribute(Qt::WA_DeleteOnClose);// auto pOwt = new MyWgt(pqw); // 自定义 widget窗体
// auto pOverlayItem = pqw->rootObject()->findChild<QQuickItem*>("widgetItem");// if (nullptr != pOverlayItem)
// {
// qDebug()<<"===="<<pOverlayItem;
// new WidgetAnchor(pOwt, pOverlayItem);
// }// pqw->show();WgtAnchorMgr wgt_anchor;
// if(wgt_anchor.init_info(engine, "widgetItem", []()->QWidget*{return new MyWgt;}))
// wgt_anchor.init_connect();for(auto obj : engine.rootObjects()){if(obj->findChild<QQuickItem*>("widgetItem")){auto pOverlayItem = obj->findChild<QQuickItem*>("widgetItem");qDebug()<<"===="<<pOverlayItem;QWindow * mainWindow = qobject_cast<QWindow*>(obj);WId proc2Window_HWND = mainWindow->winId();auto pOwt = new MyWgt;pOwt->setProperty("_q_embedded_native_parent_handle", QVariant(proc2Window_HWND));pOwt->setWindowFlags(Qt::Widget|Qt::FramelessWindowHint);pOwt->winId();pOwt->windowHandle()->setParent(mainWindow);//WidgetAnchor anchor(pOwt, pOverlayItem);//pwgt_anchor = new WidgetAnchor(pOwt, pOverlayItem);if(wgt_anchor.init_info(pOwt, pOverlayItem))wgt_anchor.init_connect();engine.rootContext()->setContextProperty("WidgetAnchor", &wgt_anchor);break;}}// QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [pwgt_anchor](QObject* obj, const QUrl& objUrl)
// {
// qDebug()<<"=============~WidgetAnchor==============";
// delete pwgt_anchor;
// //if (!obj && url == objUrl) QCoreApplication::exit(-1);
// }, Qt::QueuedConnection);return app.exec();
}