以上是效果图, 整个窗口是 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);
#endif
QApplication 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();
}