QT
QT
目录
混合 - 数种UI流
QWidgets 协同 QGraphics
关系树详见 QWidget与继承树
QWidget 与 QGraphics 都继承于 QObject、模块均为 widgets,邻近度很高
常用控件
- QWidget系列,常用控件如 QWidget、QPushButton、QFlame 等
- QGraphics系列,常用控件如 QGraphicsScene、QGraphicsItem 、
QGraphicsView (这个是QWidget)等
QWidget 嵌套 QGraphics
非常简单
核心在于:QObject > QWidget > QFrame > QAbstractScrollArea > QGraphicsView,是一个构造函数接受QGraphicsScene参数的QWidget对象
QGraphicsView(QGraphicsScene *scene, QWidget *parent = nullptr)
QGraphicsView(QWidget *parent = nullptr)
使用示例
from .node_graphics_view import QDMGraphicsView
from .node_scene import Scene
class NodeEditWidget(QWidget):
def __init__(self, parent=None):
# create graphics sence
self.scene = Scene()
self.grScene = self.scene.grScene
# create graphics view
self.view = QDMGraphicsView(self.scene.grScene, self)
self.layout.addWidget(self.view)
QGraphics 嵌套 QWidget
也非常简单(之前开发NodeEditor时用过这个操作)
核心在于:QObject > QGraphicsItem > QGraphicsObject > QGraphicsWidget > QGraphicsProxyWidget,有一个接受QWidget对象的方法
QGraphicsProxyWidget(QGraphicsItem *parent = nullptr, Qt::WindowFlags wFlags = Qt::WindowFlags())
void setWidget(QWidget *widget)
使用示例
class QDMGraphicsNode(QGraphicsItem):
def __init__(self, node, parent=None):
# ……
self.wdContent = self.node.wdContent
self.wdContent.setGeometry(self.node_padding, self.title_height + self.node_padding
, self.width - 2 * self.node_padding, self.height - 2 * self.node_padding - self.title_height)
self.grContent = QGraphicsProxyWidget(self)
self.grContent.setWidget(self.wdContent)
Qt Widget 协同 Qt Quick
main.cpp 直接 使用QML
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine; // QML引擎
const QUrl url(QStringLiteral("qrc:/main.qml")); // 需要加载的qml
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, // 将引擎结果关联到lambda上
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl) // 无法加载则退出程序
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url); // 用QML引擎加载qml文档
return app.exec(); // 消息循环
}
这种情况下,QML文件需要以Window之类的作为根节点
import QtQuick 2.6
import QtQuick.Window 2.2
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
}
简单嵌套( QQuickWidget)
QWidget界面和QML窗口相互嵌套都是需要借助 quickwidgets 这个模块中的类 这里使用的是QQuickWidget,这个类是继承QWidget的,就和 QWidget 一样使用就行
.cpp
#include <QApplication>
#include <QtQuickWidgets/QQuickWidget>
#include <QQuickView>
#include <QHBoxLayout>
#include <QLabel>
int main(int argc, char *argv[])
{
// QApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication app(argc, argv);
QWidget * widget = new QWidget;
widget->setWindowTitle("widget 主窗口");
widget->resize(800, 400);
// 设置布局
QHBoxLayout * layout = new QHBoxLayout;
layout->setContentsMargins(0, 0, 0 ,0);
widget->setLayout(layout);
// qml 界面 嵌入到 widget
QQuickWidget qmlWidget(QUrl("qrc:/main.qml"));
qmlWidget.setResizeMode(QQuickWidget::SizeRootObjectToView );
// 设置这个之后 anchor不用设置,root节点大小会根据 QQuickWidget大小改变
// 在qml里 通过 parent 获取不到 widget 窗口 !!!
layout->addWidget(&qmlWidget);
// widget 界面 嵌入到 qmlWidget里
QLabel label("QLabel", &qmlWidget);
label.move(100, 100);
// widget 界面 嵌入到 widget
QLabel nativeWidget;
nativeWidget.setText("Widget");
nativeWidget.setAlignment(Qt::AlignCenter);
layout->addWidget(&nativeWidget);
widget->show();
return app.exec();
}
.qml
- 注意:如果是用 QQuickView或者QQuickWidget 加载的qml,root节点不能是 Window 这一类类型,最好是Rectangle
- 注意:Rectangle里不能放QWidget界面,否则直接断言退出程序 ASSERT: "!d->isWidget" in file [kernel\qobject.cpp, line 1979](kernel\qobject.cpp, line 1979)
import QtQuick 2.9
Rectangle {
//visible: true
//width: 150
//height: 150
//anchors.fill: parent
//anchors.centerIn: parent
border.color: "#00ffd5"
border.width: 10
radius : 10
Text {
id : text
anchors.centerIn: parent
text: qsTr("QML Text")
antialiasing: true //抗锯齿
}
// 旋转动画
NumberAnimation {
id : numberAnimation
target: text
property: "rotation"
from: 0
to: 360
duration: 3000
running: true
loops: Animation.Infinite
}
}
QWidget 嵌套 QML 并交互
参考:
原理
使用QQuickView 类提供一个用于显示 Qt Quick 用户界面的窗口。
使用QWidget::createWindowContainer()函数,将QtQuick组件嵌入到QWidget中,该函数直接返回qwidget指针。
如果不需要交互就到此为止了。步骤 3 进行交互
使用QQmlContext 类定义 QML 引擎中的上下文。通过该类可实现C++和qml属性数据的交互,比如读取qml控件中的公开属性(成员变量)。
实现
- 通过 QQuickView 类添加qml控件代码文件:
QQuickView *mQuickView = new QQuickView();
mQuickView->setSource(QUrl("qrc:/testQml.qml"));
- 将qml控件导入QWidget中:
QWidget *mQuickWidget = QWidget::createWindowContainer(mQuickView, this);
mQuickWidget->setMinimumSize(80,30); //设置被嵌入的窗口大小和位置
mQuickWidget->move(0,0);
mQuickWidget->show(); // 显示qml
如果不需要交互就到此为止了。步骤 3 进行交互
设置qml控件成员及读取其值
QQmlContext *mQuickContext = mQuickView->rootContext();// 用于与qml交互
//首先进行读取,属性名:quickWidgetWidth、quickWidgetHeigh
int width = mQuickContext->contextProperty("quickWidgetWidth").toInt();
int hight = mQuickContext->contextProperty("quickWidgetHeigh").toInt();
qDebug()<<"width:"<<width;
qDebug()<<"hight:"<<hight;
//设置qml控件quickWidgetWidth、quickWidgetHeigh属性
mQuickContext->setContextProperty("quickWidgetWidth", 30);
mQuickContext->setContextProperty("quickWidgetHeight", 30);
//读取显示,测试是否写入成功
width = mQuickContext->contextProperty("quickWidgetWidth").toInt();
hight = mQuickContext->contextProperty("quickWidgetHeigh").toInt();
qDebug()<<"width:"<<width;
qDebug()<<"hight:"<<hight;
测试用的testQml.qml文件:
import QtQuick 2.0
Rectangle {
x: 0; // 缺省为0
y: 0; // 缺省为0
width: quickWidgetWidth; // width是宽度
height: quickWidgetHeight; // height是高度
color: "red";
}
QML 嵌套 QWidget(必要性不大?)
https://download.csdn.net/download/zs1123/13211576
https://download.csdn.net/download/weixin_40912639/10876647
.ui 混合 .qml
https://blog.csdn.net/weixin_43814837/article/details/104969474
协同 Web
QWidget 嵌入 Web
QWidget中与Web相关的主要类:
- QWebEngineView
- QWebInspector
- QWebView
QGraphics 嵌入 Web
QGraphics系列中与Web相关的主要类:
- QGraphicsItem > QGraphicsObject > QGraphicsWidget
- QGraphicsProxyWidget
- QGraphicsWebView
看到这个 QGraphicsWidget 应该也明白了,原理跟 QWidget 嵌入 Web 是一样的
QML 嵌入 Web
WebEngine QML Type