QML视频示例
转换视频和相机取景器内容。
QML视频演示了可以应用于QML VideoOutput 和 Camera 类型的各种转换(移动;调整大小;旋转;改变宽高比)。
它还展示了如何将本地代码与QML结合以实现更高级的功能 - 在这种情况下,使用C++代码计算QML帧率。此值在QML中以半透明项的形式渲染在视频内容上。
以下图像显示了应用程序执行视频叠加场景,该场景创建了一个虚拟叠加项(只是一个半透明的Rectangle),它在VideoOutput项中移动。
运行示例
要从Qt Creator运行示例,请打开欢迎模式并从示例中选择示例。有关更多信息,请访问构建和运行示例。
应用结构
Main.qml
文件创建了一个包含以下项目的UI:
- 两个
Button
实例,每个实例显示一个文件名,并且可以用来启动FileDialog
。 - 一个退出
Button
。 - 一个
SceneSelectionPanel
,它是一个可翻页的列表,显示可用的场景。 - 在左下角,一个显示QML重绘速率的项 - 上面的数字是瞬间帧率,下面的数字是过去一秒的平均值。
目录列表中的每个场景都由自己的QML文件实现 - 例如视频基本场景(仅显示屏幕中央的静态VideoOutput)由VideoBasic.qml
文件实现。从代码中可以看出,这种类型使用了一种继承方式;一个VideoBasic
项 ...
SceneBasic { contentType: "video" }
... 是SceneBasic
类型 ...
import QtQuick import QtQuick.Controls Scene { id: root property string contentType ... Content { id: content ... } Label { anchors { horizontalCenter: parent.horizontalCenter bottom: parent.bottom margins: 20 } text: content.started ? qsTr("Tap the screen to stop content") : qsTr("Tap the screen to start content") z: 2.0 } MouseArea { anchors.fill: parent onClicked: { if (content.started) content.stop() else content.start() } } Component.onCompleted: root.content = content }
... 它本身又是一个Scene
。
import QtQuick import QtQuick.Controls Rectangle { id: root ... property QtObject content ... Button { id: closeButton anchors { top: parent.top right: parent.right margins: root.margins } z: 2.0 text: qsTr("Back") onClicked: root.close() } }
SceneBasic
描述了场景的结构和行为,但对要显示的内容类型不做任何假设 - 这通过Content
进行了抽象。
这种模式允许我们定义一个特定的用例(在这种情况下,简单地显示一个静态的内容),然后为视频内容(VideoBasic
)和摄像头内容({CameraBasic}
)实例化该用例。这种方法被用来实现许多其他场景 - 例如,“反复从左到右滑动内容再返回”是由SceneMove
实现的,VideoMove
和CameraMove
都基于它。
根据顶层场景实例中contentType属性值,嵌入的内容
项会创建一个< Popup>或一个MediaPlayer项。
计算和显示 QML 绘制速率
QML 绘制速率由 FrequencyMonitor 类计算,该类将事件流(通过 notify() 插槽接收)转换为瞬时频率和平均频率
class FrequencyMonitor : public QObject { Q_OBJECT Q_PROPERTY(qreal instantaneousFrequency READ instantaneousFrequency NOTIFY instantaneousFrequencyChanged) Q_PROPERTY(qreal averageFrequency READ averageFrequency NOTIFY averageFrequencyChanged) public: ... static void qmlRegisterType(); public slots: Q_INVOKABLE void notify(); };
FrequencyMonitor 类如以下所示公开给 QML:
void FrequencyMonitor::qmlRegisterType() { ::qmlRegisterType<FrequencyMonitor>("FrequencyMonitor", 1, 0, "FrequencyMonitor"); }
然后通过定义一个名为 FrequencyItem 的 QML 元素来显示其数据,如下所示:
import FrequencyMonitor 1.0 Rectangle { id: root ... function notify() { monitor.notify() } FrequencyMonitor { id: monitor onAverageFrequencyChanged: { averageFrequencyText.text = monitor.averageFrequency.toFixed(2) } } Text { id: labelText anchors { left: parent.left top: parent.top margins: 10 } color: root.textColor font.pixelSize: 0.6 * root.textSize text: root.label width: root.width - 2*anchors.margins elide: Text.ElideRight } Text { id: averageFrequencyText anchors { right: parent.right bottom: parent.bottom margins: 10 } color: root.textColor font.pixelSize: root.textSize } }
结果如下所示
接下来就是将QQuickView对象的 afterRendering() 信号连接到一个 JavaScript 函数,该函数最终调用
int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); ... QQuickView viewer; ... QQuickItem *rootObject = viewer.rootObject(); ... QObject::connect(&viewer, SIGNAL(afterRendering()), rootObject, SLOT(qmlFramePainted()));
© 2024 Qt 公司有限公司. 本文件中包含的文档贡献权属于各自的所有者。本文件中提供的文档根据自由软件基金会发布的 GNU 自由文档许可协议第 1.3 版 的条款进行许可。Qt 和相关徽标是芬兰及/或世界其他地区的 The Qt Company Ltd. 的商标。所有其他商标均为各自所有者的财产。