这两种方式都可以 复用已有的widget界面,不必使用qml重新开发,大大减少了开发时间。
第一种方式: qwidget界面会一直 悬浮在QML界面的上方, 代码中可控制这个widget show或者hide。 然后这个widget界面可以直接处理事件,比如说点击,长按之类的, 就是在widget里面正常写交互逻辑, 缺点就是会悬浮在QML界面上方。 我使用的场景是显示3D模型,需要手指拖动来进行交互,使用的此种方式。
实现方式如下:
1、现在QML里面留出一个位置,确定大小和坐标,这里叫widgetitem
css
Rectangle{
id: test_widget
x: 400
y: 44
width: 880
height: 597
color: "transparent"
border.color: "black"
border.width: 5
visible: false
Item{
objectName: "widgetItem"
width: 880
height: 597
}
}
2、再把widget实例化出来
cpp
navWidget = new TestWidget(":/images/robot.png",rootWidget);
auto pWidgetItem = rootWidget->rootObject()->findChild<QQuickItem*>("widgetItem");
QRectF rect = pWidgetItem->mapRectToItem(0, QRectF(pWidgetItem->x(),
pWidgetItem->y(),
pWidgetItem->width(),
pWidgetItem->height()));
navWidget->setGeometry(rect.toRect());
navWidget->hide();
3、后面在合适的时机控制 show/hide就完成了
第二种方式:
qwidget界面就像一个QML组件一样, 可以使用anchor 来控制位置和大小,解决上面一直悬浮在QML界面上方的问题, 这个的交互需要转发事件,但我嫌麻烦没有继续深究 怎么转发事件, 因为我的使用场景 是 把widget当背景 在qml界面的最下方 显示摄像头的视频数据,不需要交互。就没写事件转发。
1、先继承QQuickPaintedItem 写一个中间类,帮助后面的widget嵌入进去
cpp
#ifndef WIDGETSITEM_H
#define WIDGETSITEM_H
#include <QQuickPaintedItem>
#include <QWidget>
#include <QPainter>
class WidgetItem : public QQuickPaintedItem {
Q_OBJECT
Q_PROPERTY(QVariant thirdWidget WRITE setThirdWidget)
public:
explicit WidgetItem(QQuickItem *parent = nullptr) : QQuickPaintedItem(parent), m_widget(nullptr) {
setFlag(ItemHasContents, true);
}
void setThirdWidget(QVariant widget) {
}
protected:
void paint(QPainter *painter) override {
}
void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override {
QQuickPaintedItem::geometryChanged(newGeometry, oldGeometry);
if (m_widget) {
m_widget->setGeometry(newGeometry.toRect());
}
}
bool eventFilter(QObject *obj, QEvent *e) override {
if (obj == m_widget && e->type() == QEvent::Paint) {
update();
}
return QQuickPaintedItem::eventFilter(obj, e);
}
private:
QWidget *m_widget;
};
#endif // WIDGETSITEM_H
2、然后在main函数注册
cpp
qmlRegisterType<WidgetItem>("THWidgetItem", 1, 0, "ThirdWidgetItem");
3、示例要嵌入的widget
cpp
sceneWidget = new TestWidget(":/images/2.jpg",1020,596);
bomWidget = new TestWidget(":/images/4.jpg",1280,596);
rootWidget->engine()->rootContext()->setContextProperty("thScentWidget", sceneWidget);
rootWidget->engine()->rootContext()->setContextProperty("thBomWidget", bomWidget);
4、在qml中使用
css
ThirdWidgetItem{
id:scencbg
anchors.fill: parent
thirdWidget: thScentWidget
}