2017-07-14 84 views
0

我有一個ListView,其代表是一個紅色按鈕。當按鈕的顏色發生變化時,我希望程序動態創建一個定時器(特定於該代表),該定時器在5秒後再次將顏色設置爲紅色。然後我想讓程序銷燬計時器。我該怎麼做?QML - 發生事件時動態創建定時器

這裏是我的實際代碼:

ListView { 
    id: myListView 
    model: myListModel 
    anchors.fill: parent 
    anchors.leftMargin: 20; anchors.rightMargin: 20 
    orientation: Qt.Vertical 
    clip: true 
    spacing: 8 
    delegate: Button { 
     id: myDelegate 
     property int myDelegateIndex: index + 1 
     width: 100; height: 50 
     text: "Push" 
     background: Rectangle { 
      id: myDelegateBackground 
      color: "red" 
      onColorChanged: { 
       myTimer.start(); 
      } 
     } 

     Timer { 
      id: myTimer 
      interval: 5000 
      running: true 
      repeat: true 
      onTriggered: { 
       myDelegateBackground.color = "red"; 
      } 
     } 
    } 
} 

謝謝大家了很多!

+1

爲什麼要在使用它之後銷燬計時器?爲什麼不把「repeat」屬性設置爲false,然後它只會觸發一次。也將「running」設置爲false,以便在按下按鈕之前不會啓動。當代理被銷燬時,Timer組件將被銷燬,你不需要手動去做 –

回答

1

您創建一個組件

SelfdestroyingTimer.qml

Timer { 
    property var action // Assing a function to this, that will be executed 
    running: true 
    onTriggered: { 
     action() 
     this.destroy() // If this timer is dynamically instantitated it will be destroyed when triggered 
    } 
} 

而且具有這樣的功能:

function createOneShotTimer(duration, action) { 
    var comp = Qt.createComponent('SelfdestroyingTimer.qml') 
    comp.createObject(root, { action: action, interval: duration }) 
} 

或在同一文件中聲明組件(所以你不需要每次你想要一個實例時創建它),它看起來像這樣:

import QtQuick 2.5 
import QtQuick.Controls 1.4 
import QtQuick.Controls.Styles 1.4 
import QtQuick.Window 2.0 
import QtQuick.Dialogs 1.2 

ApplicationWindow { 
    id: window 
    visible: true 
    width: 600 
    height: 600 

    Component { 
     id: singleShot 
     Timer { 
      property var action 
      running: true 
      onTriggered: { 
       if (action) action() // To check, whether it is a function, would be better. 
       this.destroy() 
      } 
      // This proves, it will be destroyed. 
      Component.onDestruction: console.log('Timer says bye bye!') 
     } 
    } 


    Button { 
     onClicked: { 
      singleShot.createObject(this, { action: function() { console.log('ACTION!!!') }, interval: 2000 }) 
     } 
    } 
} 
+0

'action'是什麼意思?它是決定計時器壽命的參數嗎?我如何將剛剛創建的定時器與我的按鈕代理相關聯? @derM – Elena

+0

儘管向人們展示新技術很好,但鼓勵從委託內部動態創建對象是很危險的。如果ListView被滾動以便它開始銷燬已經離開視圖的代表,那麼動態對象可以留下沒有有效的QML上下文並導致段錯誤。 –

+0

@MarkCh,你錯了。動態創建對象是完全安全的,如果做得對的話,即使是在委託內完成。唯一重要的是,你設置了一個父母,並且這個父母不會超出代表。因此,如果您將其設置爲代表或其任何子代,那麼該對象最遲會被銷燬,當它的父代被銷燬時,您也可以自己控制生命。 – derM

0

似乎沒有必要動態創建定時器。爲每個委託創建一個Timer並通過調用restart()來重用它。

見下面的例子:

ListView { 
    id: myListView 
    model: 20 
    anchors.fill: parent 
    anchors.leftMargin: 20; anchors.rightMargin: 20 
    orientation: Qt.Vertical 
    clip: true 
    spacing: 8 
    delegate: Button { 
     id: myDelegate 
     property int myDelegateIndex: index + 1 
     width: 100; height: 50 
     text: "Push" 
     background: Rectangle { 
      id: myDelegateBackground 
      color: "red" 
      onColorChanged: { 
       myTimer.restart(); 
      } 

      Timer { 
       id: myTimer 
       interval: 5000 
       running: false 
       repeat: false 
       onTriggered: { 
        myDelegateBackground.color = "red"; 
       } 
      } 
     } 
     onClicked: { 
      background.color = "blue" 
     } 
    } 
} 

不管你選擇這樣做有什麼機制,你將有造成破壞的ListView滾動哪出的ListView的可見區域的代表問題。當委託被破壞並重新創建時,它將具有其原始顏色,並且計時器將處於默認狀態。

有兩個選項來處理這樣的場景:

  • 保存委託給列表的狀態(在JavaScript VAR)委託的範圍之內。
  • 增加Listview cacheBuffer,以便ListView不會在代理不在可見區域時銷燬代理。
+0

您的假設「無論您選擇如何執行此操作,您都會遇到ListView銷燬代理的問題,這些代理會滾出ListView的可見區域。當委託被破壞並重新創建時,它將具有其原始顏色和計時器將處於默認狀態。「是錯的。特別是當有大量的代表時,鼓勵懶惰地實例化每個代表不一定需要的部分代碼。定時器雖然很小,但它們可以變得非常相關。 – derM

相關問題