QML中如何获取并存储属性变更前的旧值?
Great question! This is a common gotcha with QML's default property change signals—they only fire after the property has been updated, so you can't access the old value directly in the standard onPropertyNameChanged handler. Let's break down a couple of reliable solutions with code examples.
Solution 1: Custom Property with an Overridden Setter (Best for Custom Properties)
If you're defining your own property (not a built-in one from a Qt Quick control), you can override the property's setter to save the old value before updating the property itself. You can even emit a custom signal that includes both the old and new values for easier downstream handling.
import QtQuick 2.15 Item { // Property to store the previous value of our target property property int oldCounterValue: 0 // Our target property with a custom setter property int counterValue: 0 { set(newValue) { // Save the current value as the old value BEFORE updating oldCounterValue = counterValue // Update the property to the new value counterValue = newValue // Emit a custom signal with both old and new values (optional but useful) counterValueChanged(oldCounterValue, newValue) } } // Custom signal that carries both old and new values signal counterValueChanged(int oldVal, int newVal) // Test the logic Component.onCompleted: { counterValue = 5 console.log("Old value:", oldCounterValue, "| New value:", counterValue) counterValue = 15 console.log("Old value:", oldCounterValue, "| New value:", counterValue) } // Listen to our custom signal onCounterValueChanged: { console.log("Counter updated:", oldVal, "→", newVal) } }
Solution 2: Proxy Property for Built-in Control Properties
If you need to track the old value of a built-in property (like Text.text or Rectangle.width), you can't override the built-in setter directly. Instead, create a proxy property that acts as the middleman for all updates to the target property.
import QtQuick 2.15 Text { id: displayText text: "" // Initial default value // Property to store the old text value property string oldDisplayText: displayText.text // Proxy property to control updates to the built-in `text` property property string proxyText: displayText.text { set(newText) { // Save the current text as the old value first oldDisplayText = displayText.text // Update the actual text property displayText.text = newText } } // Test the proxy logic Component.onCompleted: { proxyText = "Hello QML!" console.log("Old text:", oldDisplayText, "| New text:", displayText.text) proxyText = "Tracking old values works!" console.log("Old text:", oldDisplayText, "| New text:", displayText.text) } }
Why the Default onXChanged Handler Doesn't Work
Just to clarify: QML's default property change signals are designed to notify you after the property has been updated. By the time onCounterValueChanged runs, the property already holds the new value, so the old value is lost unless you explicitly save it before the update happens.
内容的提问来源于stack exchange,提问作者Xintrea

