2017-07-14 88 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

相关问题