日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

qml demo分析(threadedanimation-线程动画)

發布時間:2024/4/13 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 qml demo分析(threadedanimation-线程动画) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、效果預覽

  使用過qml的同學都知道,使用qml做動畫效果是非常簡單的,再也不需要像QWidget那樣,自己模擬一個動畫,費時又費力,往往還達不到效果。今天我們就來分析下qml的兩種動畫實現方式,如圖1所示,窗口底部的提示信息文本“This application shows two spinners. The one to the right is animated on the scene graph thread (when applicable) and the left one is using the normal Qt Quick animation system.”意思就是左邊的窗口使用quick animation實現,右側窗口使用opengl scene graph實現,細心的同學就會發現,當Not blocked字樣變為Blocked時,左側的旋轉動畫每過大概400ms就會停頓下,而右側窗口絲毫不受影響。好了廢話不多說,我們這就來分析下這個示例程序的源碼,這個現象就不難理解啦。

圖1 旋轉動畫

二、源碼分析

  首先我們先來分析下該示例代碼的工程目錄,如圖1所示,spinner一個C++類,其重寫了QQuickItem組件,QQuickItem其實在qml中就相當于Item組件,重寫QQuickItem是為了注冊到qml系統中,把spinner當qml的一個組件使用,在spinner的實現過程中,使用了opengl的方式來進行繪圖。

圖2 工程目錄

  該示例代碼的main.cpp文件與qml demo分析(abstractitemmodel-數據分離)文章中分析的一樣,都是注冊了一個自定義QQuickItem對象到qml上下文中,并使用QQuickView加載main.qml文件并顯示,在此就不貼代碼啦。

1、opengl scene graph

  由于這是第一次分析opengl的示例程序,這里我將會把spinner的頭文件和實現代碼都貼上。首先先來看下spinner類頭文件

1 #ifndef SPINNER_H 2 #define SPINNER_H 3 4 #include <QtQuick/QQuickItem> 5 6 class Spinner : public QQuickItem 7 { 8 Q_OBJECT 9 10 Q_PROPERTY(bool spinning READ spinning WRITE setSpinning NOTIFY spinningChanged) 11 12 public: 13 Spinner(); 14 15 bool spinning() const { return m_spinning; } 16 void setSpinning(bool spinning); 17 18 protected: 19 QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *); 20 21 signals: 22 void spinningChanged(); 23 24 private: 25 bool m_spinning; 26 };

  頭文件中聲明了一個SPinner類,繼承自QQuickItem類,重寫該類是為了使用opengl繪制旋轉效果。代碼中使用了Q_PROPERTY宏將m_spinning成員變量注冊到了qml系統中,qml代碼直接可以通過spinning:值的方式修改該變量,該宏在之前的文章中也有簡單的介紹,具體參見qml demo分析(customgeometry-貝塞爾曲線)。

1 Spinner::Spinner() 2 : m_spinning(false) 3 { 4 setSize(QSize(64, 64)); 5 setFlag(ItemHasContents); 6 } 7 8 void Spinner::setSpinning(bool spinning) 9 { 10 if (spinning == m_spinning) 11 return; 12 m_spinning = spinning; 13 emit spinningChanged(); 14 update(); 15 } 16 17 QSGNode *Spinner::updatePaintNode(QSGNode *old, UpdatePaintNodeData *) 18 { 19 SpinnerNode *n = static_cast<SpinnerNode *>(old); 20 if (!n) 21 n = new SpinnerNode(window()); 22 23 n->setSpinning(m_spinning); 24 25 return n; 26 }

  在Spinner類實現中,updatePaintNode接口中構造了一個SpinnerNode類,具體的繪制操作就是在SpinnerNode類中實現。

1 class SpinnerNode : public QObject, public QSGTransformNode 2 { 3 Q_OBJECT 4 public: 5 SpinnerNode(QQuickWindow *window) 6 : m_rotation(0) 7 , m_spinning(false) 8 , m_window(window) 9 { 10 connect(window, &QQuickWindow::beforeRendering, this, &SpinnerNode::maybeRotate); 11 connect(window, &QQuickWindow::frameSwapped, this, &SpinnerNode::maybeUpdate); 12 13 QImage image(":/scenegraph/threadedanimation/spinner.png"); 14 m_texture = window->createTextureFromImage(image);//創建一個紋理 15 QSGSimpleTextureNode *textureNode = new QSGSimpleTextureNode();//簡單紋理節點 加入場景前必須有一個紋理 16 textureNode->setTexture(m_texture);//設置紋理 17 textureNode->setRect(0, 0, image.width(), image.height()); 18 textureNode->setFiltering(QSGTexture::Linear); 19 appendChildNode(textureNode); 20 } 21 22 ~SpinnerNode() { 23 delete m_texture; 24 } 25 26 void setSpinning(bool spinning) 27 { 28 m_spinning = spinning; 29 } 30 31 public slots: 32 void maybeRotate() { 33 if (m_spinning) { 34 m_rotation += (360 / m_window->screen()->refreshRate()); 35 QMatrix4x4 matrix; 36 matrix.translate(32, 32); 37 matrix.rotate(m_rotation, 0, 0, 1);//繞z軸旋轉 38 matrix.translate(-32, -32); 39 setMatrix(matrix); 40 } 41 } 42 43 void maybeUpdate() { 44 if (m_spinning) { 45 m_window->update(); 46 } 47 } 48 49 private: 50 qreal m_rotation; 51 bool m_spinning; 52 QSGTexture *m_texture; 53 QQuickWindow *m_window; 54 };

  SpinnerNode類繼承自QSGTransformNode,構造函數中使用圖片構造了一個紋理,并將紋理設置到QSGSimpleTextureNode對象中,進而將該對象添加到場景,添加到場景的順序決定他們在場景中被繪制的順序。

  SpinnerNode類中使用maybeRotate方法將紋理進行了旋轉,代碼如上32-41行所示。

2、quick animation

  使用qml屬性動畫進行旋轉操作相對來說比較簡單,只需要使用NumberAnimation on rotation即可,具體代碼如下64-66行

1 Rectangle { 2 3 width: 320 4 height: 480 5 6 gradient: Gradient {//設置背景色 7 GradientStop { position: 0; color: "lightsteelblue" } 8 GradientStop { position: 1; color: "black" } 9 } 10 11 Rectangle {//與blockingLabel組成一個提示框 12 color: Qt.rgba(1, 1, 1, 0.7); 13 radius: 10 14 border.width: 1 15 border.color: "white" 16 anchors.fill: blockingLabel; 17 anchors.margins: -10 18 } 19 20 Text { 21 id: blockingLabel 22 color: blocker.running ? "red" : "black"//根據定時器狀態 修改提示框文本信息和字體顏色 23 text: blocker.running ? "Blocked!" : "Not blocked" 24 anchors.horizontalCenter: parent.horizontalCenter 25 anchors.top: parent.top 26 anchors.topMargin: 100 27 } 28 29 Timer { 30 id: blocker 31 interval: 357//觸發間隔 32 running: false;//默認沒有啟動 33 repeat: true 34 onTriggered: {//該槽的作用就是為了模擬一個延遲 說明opengl的渲染不在主線程進行 而quick animation在主線程進行渲染 35 var d = new Date(); 36 var x = 0; 37 var wait = 50 + Math.random() * 200; 38 while ((new Date().getTime() - d.getTime()) < 100) { 39 x += 1; 40 } 41 } 42 } 43 44 Timer { 45 id: blockerEnabler 46 interval: 4000 47 running: true 48 repeat: true 49 onTriggered: { 50 blocker.running = !blocker.running//定時器狀態修改 4s中置反 51 } 52 } 53 54 Spinner {//opengl 55 anchors.centerIn: parent 56 anchors.horizontalCenterOffset: 80 57 spinning: true//通過setSpinning接口設置該屬性值 58 } 59 60 Image {//quick animation 61 anchors.centerIn: parent 62 anchors.horizontalCenterOffset: -80 63 source: "spinner.png" 64 NumberAnimation on rotation { 65 from: 0; to: 360; duration: 1000; loops: Animation.Infinite//1s轉動一圈 66 } 67 } 68 69 Rectangle {//與label文本組成底部提示框 70 color: Qt.rgba(1, 1, 1, 0.7) 71 radius: 10 72 border.width: 1 73 border.color: "white" 74 anchors.fill: label 75 anchors.margins: -10 76 } 77 78 Text { 79 id: label 80 color: "black" 81 wrapMode: Text.WordWrap 82 text: "This application shows two spinners. The one to the right is animated on the scene graph thread (when applicable) and the left one is using the normal Qt Quick animation system." 83 anchors.right: parent.right 84 anchors.left: parent.left 85 anchors.bottom: parent.bottom 86 anchors.margins: 20 87 } 88 }

?

總結:使用qml有兩種方式實現旋轉,往大的說就是動畫,有兩種方式:opengl scene or quick animation。

opengl scene:實現比較麻煩,但是線程獨立,不會因為復雜計算而阻塞ui繪制

quick animation:使用簡單,但是是在主線程進行繪制。

超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生

總結

以上是生活随笔為你收集整理的qml demo分析(threadedanimation-线程动画)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。