如何将同一StateMachine重复应用于多个QML列元素(如signal1与signal2)
Great question! You don't need to modify any C++ code—all you need to do is adjust your QML file to reuse the existing TrafficLightStateMachine logic for signal2 (and future traffic light components).
Why no C++ changes are needed
Your existing TrafficLightStateMachine is already exposed as a property of the root Image component (lights.stateMachine), and it emits all the state signals (red, redGoingGreen, etc.) that you need. The state machine itself doesn't care which QML components are listening to its state changes—it just broadcasts the current state. So we can reuse it across multiple traffic light groups without touching C++.
How to update the QML
There are two approaches you can take, depending on how scalable you want the solution to be:
Approach 1: Quick fix (direct updates to existing States)
Modify each existing State in your lights component to include property changes for signal2's lights, alongside signal1's. For example:
states: [ State { name: "Red" when: stateMachine.red // Update signal1's lights PropertyChanges { target: redLight; opacity: 1 } PropertyChanges { target: yellowLight; opacity: 0.2 } PropertyChanges { target: greenLight; opacity: 0.2 } // Update signal2's lights PropertyChanges { target: redLight1; opacity: 1 } PropertyChanges { target: yellowLight1; opacity: 0.2 } PropertyChanges { target: greenLight1; opacity: 0.2 } }, State { name: "RedGoingGreen" when: stateMachine.redGoingGreen PropertyChanges { target: redLight; opacity: 1 } PropertyChanges { target: yellowLight; opacity: 1 } PropertyChanges { target: greenLight; opacity: 0.2 } PropertyChanges { target: redLight1; opacity: 1 } PropertyChanges { target: yellowLight1; opacity: 1 } PropertyChanges { target: greenLight1; opacity: 0.2 } }, State { name: "Yellow" when: stateMachine.yellow PropertyChanges { target: redLight; opacity: 0.2 } PropertyChanges { target: yellowLight; opacity: 1 } PropertyChanges { target: greenLight; opacity: 0.2 } PropertyChanges { target: redLight1; opacity: 0.2 } PropertyChanges { target: yellowLight1; opacity: 1 } PropertyChanges { target: greenLight1; opacity: 0.2 } }, State { name: "Green" when: stateMachine.green PropertyChanges { target: redLight; opacity: 0.2 } PropertyChanges { target: yellowLight; opacity: 0.2 } PropertyChanges { target: greenLight; opacity: 1 } PropertyChanges { target: redLight1; opacity: 0.2 } PropertyChanges { target: yellowLight1; opacity: 0.2 } PropertyChanges { target: greenLight1; opacity: 1 } } ]
This will immediately sync signal2's state with signal1 using the same state machine.
Approach 2: Scalable solution (create a reusable TrafficLight component)
If you plan to add more traffic light components in the future, wrapping the light group into a reusable QML component will save you repetition.
- Create a new file named
TrafficLight.qmlwith this content:
import QtQuick 2.5 Column { // Expose aliases for the lights so parent components can control them property alias redLight: redLight property alias yellowLight: yellowLight property alias greenLight: greenLight width: 22 height: 120 spacing: 27 Image { id: redLight width: 20 height: 20 opacity: 0.2 source: "red.png" } Image { id: yellowLight width: 20 height: 20 opacity: 0.2 source: "yellow.png" } Image { id: greenLight width: 20 height: 20 opacity: 0.2 source: "green.png" } }
- Replace the two
Columncomponents inLights.ui.qmlwith this reusable component:
TrafficLight { id: signal1 y: 286 layer.smooth: true layer.enabled: false rotation: 0 transformOrigin: Item.Center anchors.horizontalCenterOffset: -87 anchors.horizontalCenter: parent.horizontalCenter } TrafficLight { id: signal2 x: -8 y: 237 rotation: 270 transformOrigin: Item.Center anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenterOffset: 124 }
- Update your
statesto reference the component's aliased lights (this looks cleaner and is easier to extend):
states: [ State { name: "Red" when: stateMachine.red PropertyChanges { target: signal1.redLight; opacity: 1 } PropertyChanges { target: signal1.yellowLight; opacity: 0.2 } PropertyChanges { target: signal1.greenLight; opacity: 0.2 } PropertyChanges { target: signal2.redLight; opacity: 1 } PropertyChanges { target: signal2.yellowLight; opacity: 0.2 } PropertyChanges { target: signal2.greenLight; opacity: 0.2 } }, // Repeat the pattern for RedGoingGreen, Yellow, Green states ]
Now, adding a new traffic light is as simple as dropping another TrafficLight component into your QML and adding its property changes to the states (or even using a Repeater if you have many identical lights!).
Final Notes
The key here is that your TrafficLightStateMachine is already a shared state source—you just need to connect additional QML components to its state signals. If you ever want each traffic light to have independent state logic later, you'd need to create separate instances of TrafficLightStateMachine, but that's not required for your current use case.
内容的提问来源于stack exchange,提问作者SHREERAKSHA BHAT

