目录
-
- 一、问题背景
-
- 1.1 运行环境
- 1.2 问题现象
- 二、排查思路与过程
-
- 2.1 初步排查:排除常见原因
- 2.2 关键发现:去掉颜色属性后正常
- 2.3 深入分析:是"color"还是"着色组"
- 2.4 踩坑记录
- 三、根本原因分析
-
- 3.1 ImageParticle 的四组数据共享机制
- 3.2 崩溃的触发链
- 四、解决方案
-
- 方案 A:只给目标组设置颜色
- 方案 B:使用 ItemParticle 替代源组
- 五、方案对比
-
- 5.1 功能对比
- 5.2 选型决策树
- 六、适用边界与限制条件
-
- 6.1 影响范围
- 6.2 不受影响的场景
- 6.3 与其他 Affector 的关系
- 6.4 Qt 版本说明
- 七、总结
- 参考资料
摘要:在使用 Qt Quick Particles 的 GroupGoal 实现粒子组转换时,如果源组和目标组的 ImageParticle 都显式设置了颜色属性,程序会立即崩溃。本文通过深入分析 ImageParticle 的数据共享机制,定位了崩溃的根本原因,并提供了两种经过验证的解决方案。
一、问题背景
1.1 运行环境
- Qt 版本:6.8.2
- 编译器:MinGW 64-bit
- 操作系统:Windows 11 家庭中文版 24H2
- 验证日期:2026-04-19
该问题从 Qt 5.x 到 Qt 6.11 均可复现,是 ImageParticle 数据共享机制的设计限制。
1.2 问题现象
在使用 Qt Quick Particles 进行粒子组转换(通过 GroupGoal 或 ParticleGroup.to 属性)时,如果源组和目标组的 ImageParticle 都显式设置了 color 属性,程序会在粒子经过转换区域时崩溃。
复现代码:
ParticleSystem {
id: particleSystem
ImageParticle {
groups: ["default"]
source: "qrc:/images/star.png"
color: "#4ECDC4"// 源组设置了颜色
}
ImageParticle {
groups: ["attracted"]
source: "qrc:/images/star.png"
color: "#FFE66D"// 目标组也设置了颜色
}
ParticleGroup {
name: "default"
duration: 1000
}
ParticleGroup {
name: "attracted"
duration: 1000
}
Emitter {
id: emitter
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
width: parent.width
height: 1
emitRate: 50
lifeSpan: 4000
size: 12
group: "default"
velocity: PointDirection { y: -100; yVariation: 20 }
acceleration: PointDirection { y: -20 }
}
GroupGoal {
id: groupGoal
system: particleSystem
groups: ["default"]
goalState: "attracted"
// 当粒子经过此区域时会崩溃
x: 0
y: parent.height / 2
width: parent.width
height: 20
jump: true
}
}
崩溃现象:无警告、无错误输出,程序直接闪退

二、排查思路与过程
2.1 初步排查:排除常见原因
首先排除了以下常见原因:
| 图片资源是否存在 | ✅ 存在 | 排除资源问题 |
| ParticleSystem 是否正确配置 | ✅ 正确 | 排除配置问题 |
| GroupGoal 区域是否正确 | ✅ 正确 | 排除区域问题 |
| Qt 版本是否有已知 bug | ❓ 未找到 | 需要深入分析 |
2.2 关键发现:去掉颜色属性后正常
通过逐步注释代码,发现:
// 实验 1:两个都设置 color → 崩溃
ImageParticle { groups: ["default"]; color: "#4ECDC4" }
ImageParticle { groups: ["attracted"]; color: "#FFE66D" }
// 实验 2:只设置目标组 color → 正常
ImageParticle { groups: ["default"] } // 不设置 color
ImageParticle { groups: ["attracted"]; color: "#FFE66D" }
// 实验 3:只设置源组 color → 正常
ImageParticle { groups: ["default"]; color: "#4ECDC4" }
ImageParticle { groups: ["attracted"] } // 不设置 color
关键结论:只有当两个 ImageParticle 都设置 color 时才会崩溃。
2.3 深入分析:是"color"还是"着色组"
进一步实验发现,问题不仅限于 color 属性:
| 1 | color: "#4ECDC4" | color: "#FFE66D" | 崩溃 |
| 2 | colorVariation: 0.3 | color: "#FFE66D" | 崩溃 |
| 3 | alpha: 0.8 | color: "#FFE66D" | 崩溃 |
| 4 | rotation: 45 | color: "#FFE66D" | 正常 |
| 5 | xVector: … | color: "#FFE66D" | 正常 |
关键发现:问题根源是"两个 ImageParticle 都显式设置了着色组中的任意属性",而非"两个都设置了 color"。
2.4 踩坑记录
在排查过程中,尝试了以下错误方向:
错误尝试 1:以为是 GroupGoal 的 jump 属性问题
- 尝试:将 jump: true 改为 jump: false
- 结果:仍然崩溃
- 结论:与 jump 属性无关
错误尝试 2:以为是图片资源格式问题
- 尝试:更换不同的图片格式(png/jpg)
- 结果:仍然崩溃
- 结论:与资源格式无关
错误尝试 3:网上搜索到的"解决方案"
- 方案:在 GroupGoal 前添加延迟
- 结果:无效,崩溃发生在切换瞬间
- 结论:不是时序问题
三、根本原因分析
3.1 ImageParticle 的四组数据共享机制
ImageParticle 的渲染能力分为四组,每组独立共享:
#mermaid-svg-luUxR4RBpLMSFg0G{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-luUxR4RBpLMSFg0G .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-luUxR4RBpLMSFg0G .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-luUxR4RBpLMSFg0G .error-icon{fill:#552222;}#mermaid-svg-luUxR4RBpLMSFg0G .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-luUxR4RBpLMSFg0G .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-luUxR4RBpLMSFg0G .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-luUxR4RBpLMSFg0G .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-luUxR4RBpLMSFg0G .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-luUxR4RBpLMSFg0G .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-luUxR4RBpLMSFg0G .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-luUxR4RBpLMSFg0G .marker{fill:#333333;stroke:#333333;}#mermaid-svg-luUxR4RBpLMSFg0G .marker.cross{stroke:#333333;}#mermaid-svg-luUxR4RBpLMSFg0G svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-luUxR4RBpLMSFg0G p{margin:0;}#mermaid-svg-luUxR4RBpLMSFg0G .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-luUxR4RBpLMSFg0G .cluster-label text{fill:#333;}#mermaid-svg-luUxR4RBpLMSFg0G .cluster-label span{color:#333;}#mermaid-svg-luUxR4RBpLMSFg0G .cluster-label span p{background-color:transparent;}#mermaid-svg-luUxR4RBpLMSFg0G .label text,#mermaid-svg-luUxR4RBpLMSFg0G span{fill:#333;color:#333;}#mermaid-svg-luUxR4RBpLMSFg0G .node rect,#mermaid-svg-luUxR4RBpLMSFg0G .node circle,#mermaid-svg-luUxR4RBpLMSFg0G .node ellipse,#mermaid-svg-luUxR4RBpLMSFg0G .node polygon,#mermaid-svg-luUxR4RBpLMSFg0G .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-luUxR4RBpLMSFg0G .rough-node .label text,#mermaid-svg-luUxR4RBpLMSFg0G .node .label text,#mermaid-svg-luUxR4RBpLMSFg0G .image-shape .label,#mermaid-svg-luUxR4RBpLMSFg0G .icon-shape .label{text-anchor:middle;}#mermaid-svg-luUxR4RBpLMSFg0G .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-luUxR4RBpLMSFg0G .rough-node .label,#mermaid-svg-luUxR4RBpLMSFg0G .node .label,#mermaid-svg-luUxR4RBpLMSFg0G .image-shape .label,#mermaid-svg-luUxR4RBpLMSFg0G .icon-shape .label{text-align:center;}#mermaid-svg-luUxR4RBpLMSFg0G .node.clickable{cursor:pointer;}#mermaid-svg-luUxR4RBpLMSFg0G .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-luUxR4RBpLMSFg0G .arrowheadPath{fill:#333333;}#mermaid-svg-luUxR4RBpLMSFg0G .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-luUxR4RBpLMSFg0G .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-luUxR4RBpLMSFg0G .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-luUxR4RBpLMSFg0G .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-luUxR4RBpLMSFg0G .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-luUxR4RBpLMSFg0G .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-luUxR4RBpLMSFg0G .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-luUxR4RBpLMSFg0G .cluster text{fill:#333;}#mermaid-svg-luUxR4RBpLMSFg0G .cluster span{color:#333;}#mermaid-svg-luUxR4RBpLMSFg0G div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-luUxR4RBpLMSFg0G .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-luUxR4RBpLMSFg0G rect.text{fill:none;stroke-width:0;}#mermaid-svg-luUxR4RBpLMSFg0G .icon-shape,#mermaid-svg-luUxR4RBpLMSFg0G .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-luUxR4RBpLMSFg0G .icon-shape p,#mermaid-svg-luUxR4RBpLMSFg0G .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-luUxR4RBpLMSFg0G .icon-shape .label rect,#mermaid-svg-luUxR4RBpLMSFg0G .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-luUxR4RBpLMSFg0G .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-luUxR4RBpLMSFg0G .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-luUxR4RBpLMSFg0G :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
ImageParticle
着色组color / colorVariationalpha / alphaVariation
旋转组rotation / rotationVelocityrotationVariation
变形组xVector / yVector
精灵组sprites / spritesInterpolate
Qt 6.8.2 官方文档的原话:
“ImageParticles implicitly share data on particles if multiple ImageParticles are painting the same logical particle group. This is broken down along the four capabilities listed above.”
3.2 崩溃的触发链
#mermaid-svg-tBNZ8GmeISiTcEvP{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-tBNZ8GmeISiTcEvP .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-tBNZ8GmeISiTcEvP .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-tBNZ8GmeISiTcEvP .error-icon{fill:#552222;}#mermaid-svg-tBNZ8GmeISiTcEvP .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-tBNZ8GmeISiTcEvP .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-tBNZ8GmeISiTcEvP .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-tBNZ8GmeISiTcEvP .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-tBNZ8GmeISiTcEvP .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-tBNZ8GmeISiTcEvP .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-tBNZ8GmeISiTcEvP .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-tBNZ8GmeISiTcEvP .marker{fill:#333333;stroke:#333333;}#mermaid-svg-tBNZ8GmeISiTcEvP .marker.cross{stroke:#333333;}#mermaid-svg-tBNZ8GmeISiTcEvP svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-tBNZ8GmeISiTcEvP p{margin:0;}#mermaid-svg-tBNZ8GmeISiTcEvP .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-tBNZ8GmeISiTcEvP .cluster-label text{fill:#333;}#mermaid-svg-tBNZ8GmeISiTcEvP .cluster-label span{color:#333;}#mermaid-svg-tBNZ8GmeISiTcEvP .cluster-label span p{background-color:transparent;}#mermaid-svg-tBNZ8GmeISiTcEvP .label text,#mermaid-svg-tBNZ8GmeISiTcEvP span{fill:#333;color:#333;}#mermaid-svg-tBNZ8GmeISiTcEvP .node rect,#mermaid-svg-tBNZ8GmeISiTcEvP .node circle,#mermaid-svg-tBNZ8GmeISiTcEvP .node ellipse,#mermaid-svg-tBNZ8GmeISiTcEvP .node polygon,#mermaid-svg-tBNZ8GmeISiTcEvP .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-tBNZ8GmeISiTcEvP .rough-node .label text,#mermaid-svg-tBNZ8GmeISiTcEvP .node .label text,#mermaid-svg-tBNZ8GmeISiTcEvP .image-shape .label,#mermaid-svg-tBNZ8GmeISiTcEvP .icon-shape .label{text-anchor:middle;}#mermaid-svg-tBNZ8GmeISiTcEvP .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-tBNZ8GmeISiTcEvP .rough-node .label,#mermaid-svg-tBNZ8GmeISiTcEvP .node .label,#mermaid-svg-tBNZ8GmeISiTcEvP .image-shape .label,#mermaid-svg-tBNZ8GmeISiTcEvP .icon-shape .label{text-align:center;}#mermaid-svg-tBNZ8GmeISiTcEvP .node.clickable{cursor:pointer;}#mermaid-svg-tBNZ8GmeISiTcEvP .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-tBNZ8GmeISiTcEvP .arrowheadPath{fill:#333333;}#mermaid-svg-tBNZ8GmeISiTcEvP .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-tBNZ8GmeISiTcEvP .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-tBNZ8GmeISiTcEvP .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-tBNZ8GmeISiTcEvP .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-tBNZ8GmeISiTcEvP .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-tBNZ8GmeISiTcEvP .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-tBNZ8GmeISiTcEvP .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-tBNZ8GmeISiTcEvP .cluster text{fill:#333;}#mermaid-svg-tBNZ8GmeISiTcEvP .cluster span{color:#333;}#mermaid-svg-tBNZ8GmeISiTcEvP div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-tBNZ8GmeISiTcEvP .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-tBNZ8GmeISiTcEvP rect.text{fill:none;stroke-width:0;}#mermaid-svg-tBNZ8GmeISiTcEvP .icon-shape,#mermaid-svg-tBNZ8GmeISiTcEvP .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-tBNZ8GmeISiTcEvP .icon-shape p,#mermaid-svg-tBNZ8GmeISiTcEvP .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-tBNZ8GmeISiTcEvP .icon-shape .label rect,#mermaid-svg-tBNZ8GmeISiTcEvP .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-tBNZ8GmeISiTcEvP .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-tBNZ8GmeISiTcEvP .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-tBNZ8GmeISiTcEvP :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
源组设置着色组属性
着色组标记为显式
目标组设置着色组属性
着色组标记为显式
粒子到达 GroupGoal
触发组切换
需要重置源组着色数据
两个显式着色组冲突
💥 崩溃
关键规则:
官方文档承认的缺陷:
“One drawback of the current implementation is that it is only possible to reset the capabilities as a whole.”
四、解决方案
方案 A:只给目标组设置颜色
// 源组:不设置任何着色组属性
ImageParticle {
groups: ["default"]
system: particleSystem
source: "qrc:/images/dot.png"
// 不设置 color,使用默认白色
}
// 目标组:设置颜色
ImageParticle {
groups: ["attracted"]
system: particleSystem
source: "qrc:/images/star.png"
color: "#FFE66D"
}
原理:源组的着色组处于隐式状态,切换时不需要重置着色数据,避免触发崩溃。
优点:性能高,实现简单 缺点:源组粒子只能是默认白色

方案 B:使用 ItemParticle 替代源组
// 源组:使用 ItemParticle
ItemParticle {
groups: ["default"]
system: particleSystem
delegate: Rectangle {
width: 6; height: 6; radius: 3
color: "#4ECDC4" // 可以自由设置颜色
}
}
// 目标组:使用 ImageParticle
ImageParticle {
groups: ["attracted"]
system: particleSystem
source: "qrc:/images/star.png"
color: "#FFE66D"
}
原理:ItemParticle 不参与 ImageParticle 的数据共享机制,组切换时不存在着色数据冲突。
优点:源组可以自由设置颜色 缺点:性能较低(每个粒子都是独立 Item)

五、方案对比
5.1 功能对比
| A. 只给目标组设颜色 | 受限(默认白色) | ✅ 自由 | 低 | 简单的两状态切换 |
| B. ItemParticle 替代 | ✅ 自由 | ✅ 自由 | 低 | 需要自定义源/目标粒子 |
5.2 选型决策树
#mermaid-svg-XdR3yP7pdq5Ba31f{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-XdR3yP7pdq5Ba31f .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-XdR3yP7pdq5Ba31f .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-XdR3yP7pdq5Ba31f .error-icon{fill:#552222;}#mermaid-svg-XdR3yP7pdq5Ba31f .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-XdR3yP7pdq5Ba31f .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-XdR3yP7pdq5Ba31f .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-XdR3yP7pdq5Ba31f .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-XdR3yP7pdq5Ba31f .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-XdR3yP7pdq5Ba31f .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-XdR3yP7pdq5Ba31f .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-XdR3yP7pdq5Ba31f .marker{fill:#333333;stroke:#333333;}#mermaid-svg-XdR3yP7pdq5Ba31f .marker.cross{stroke:#333333;}#mermaid-svg-XdR3yP7pdq5Ba31f svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-XdR3yP7pdq5Ba31f p{margin:0;}#mermaid-svg-XdR3yP7pdq5Ba31f .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-XdR3yP7pdq5Ba31f .cluster-label text{fill:#333;}#mermaid-svg-XdR3yP7pdq5Ba31f .cluster-label span{color:#333;}#mermaid-svg-XdR3yP7pdq5Ba31f .cluster-label span p{background-color:transparent;}#mermaid-svg-XdR3yP7pdq5Ba31f .label text,#mermaid-svg-XdR3yP7pdq5Ba31f span{fill:#333;color:#333;}#mermaid-svg-XdR3yP7pdq5Ba31f .node rect,#mermaid-svg-XdR3yP7pdq5Ba31f .node circle,#mermaid-svg-XdR3yP7pdq5Ba31f .node ellipse,#mermaid-svg-XdR3yP7pdq5Ba31f .node polygon,#mermaid-svg-XdR3yP7pdq5Ba31f .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-XdR3yP7pdq5Ba31f .rough-node .label text,#mermaid-svg-XdR3yP7pdq5Ba31f .node .label text,#mermaid-svg-XdR3yP7pdq5Ba31f .image-shape .label,#mermaid-svg-XdR3yP7pdq5Ba31f .icon-shape .label{text-anchor:middle;}#mermaid-svg-XdR3yP7pdq5Ba31f .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-XdR3yP7pdq5Ba31f .rough-node .label,#mermaid-svg-XdR3yP7pdq5Ba31f .node .label,#mermaid-svg-XdR3yP7pdq5Ba31f .image-shape .label,#mermaid-svg-XdR3yP7pdq5Ba31f .icon-shape .label{text-align:center;}#mermaid-svg-XdR3yP7pdq5Ba31f .node.clickable{cursor:pointer;}#mermaid-svg-XdR3yP7pdq5Ba31f .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-XdR3yP7pdq5Ba31f .arrowheadPath{fill:#333333;}#mermaid-svg-XdR3yP7pdq5Ba31f .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-XdR3yP7pdq5Ba31f .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-XdR3yP7pdq5Ba31f .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-XdR3yP7pdq5Ba31f .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-XdR3yP7pdq5Ba31f .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-XdR3yP7pdq5Ba31f .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-XdR3yP7pdq5Ba31f .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-XdR3yP7pdq5Ba31f .cluster text{fill:#333;}#mermaid-svg-XdR3yP7pdq5Ba31f .cluster span{color:#333;}#mermaid-svg-XdR3yP7pdq5Ba31f div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-XdR3yP7pdq5Ba31f .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-XdR3yP7pdq5Ba31f rect.text{fill:none;stroke-width:0;}#mermaid-svg-XdR3yP7pdq5Ba31f .icon-shape,#mermaid-svg-XdR3yP7pdq5Ba31f .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-XdR3yP7pdq5Ba31f .icon-shape p,#mermaid-svg-XdR3yP7pdq5Ba31f .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-XdR3yP7pdq5Ba31f .icon-shape .label rect,#mermaid-svg-XdR3yP7pdq5Ba31f .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-XdR3yP7pdq5Ba31f .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-XdR3yP7pdq5Ba31f .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-XdR3yP7pdq5Ba31f :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
否
是
需要源组自定义颜色?
方案 A推荐
方案 B
六、适用边界与限制条件
6.1 影响范围
#mermaid-svg-jZlOTp1DrmSGPXqL{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-jZlOTp1DrmSGPXqL .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-jZlOTp1DrmSGPXqL .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-jZlOTp1DrmSGPXqL .error-icon{fill:#552222;}#mermaid-svg-jZlOTp1DrmSGPXqL .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-jZlOTp1DrmSGPXqL .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-jZlOTp1DrmSGPXqL .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-jZlOTp1DrmSGPXqL .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-jZlOTp1DrmSGPXqL .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-jZlOTp1DrmSGPXqL .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-jZlOTp1DrmSGPXqL .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-jZlOTp1DrmSGPXqL .marker{fill:#333333;stroke:#333333;}#mermaid-svg-jZlOTp1DrmSGPXqL .marker.cross{stroke:#333333;}#mermaid-svg-jZlOTp1DrmSGPXqL svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-jZlOTp1DrmSGPXqL p{margin:0;}#mermaid-svg-jZlOTp1DrmSGPXqL .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-jZlOTp1DrmSGPXqL .cluster-label text{fill:#333;}#mermaid-svg-jZlOTp1DrmSGPXqL .cluster-label span{color:#333;}#mermaid-svg-jZlOTp1DrmSGPXqL .cluster-label span p{background-color:transparent;}#mermaid-svg-jZlOTp1DrmSGPXqL .label text,#mermaid-svg-jZlOTp1DrmSGPXqL span{fill:#333;color:#333;}#mermaid-svg-jZlOTp1DrmSGPXqL .node rect,#mermaid-svg-jZlOTp1DrmSGPXqL .node circle,#mermaid-svg-jZlOTp1DrmSGPXqL .node ellipse,#mermaid-svg-jZlOTp1DrmSGPXqL .node polygon,#mermaid-svg-jZlOTp1DrmSGPXqL .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-jZlOTp1DrmSGPXqL .rough-node .label text,#mermaid-svg-jZlOTp1DrmSGPXqL .node .label text,#mermaid-svg-jZlOTp1DrmSGPXqL .image-shape .label,#mermaid-svg-jZlOTp1DrmSGPXqL .icon-shape .label{text-anchor:middle;}#mermaid-svg-jZlOTp1DrmSGPXqL .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-jZlOTp1DrmSGPXqL .rough-node .label,#mermaid-svg-jZlOTp1DrmSGPXqL .node .label,#mermaid-svg-jZlOTp1DrmSGPXqL .image-shape .label,#mermaid-svg-jZlOTp1DrmSGPXqL .icon-shape .label{text-align:center;}#mermaid-svg-jZlOTp1DrmSGPXqL .node.clickable{cursor:pointer;}#mermaid-svg-jZlOTp1DrmSGPXqL .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-jZlOTp1DrmSGPXqL .arrowheadPath{fill:#333333;}#mermaid-svg-jZlOTp1DrmSGPXqL .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-jZlOTp1DrmSGPXqL .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-jZlOTp1DrmSGPXqL .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jZlOTp1DrmSGPXqL .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-jZlOTp1DrmSGPXqL .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jZlOTp1DrmSGPXqL .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-jZlOTp1DrmSGPXqL .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-jZlOTp1DrmSGPXqL .cluster text{fill:#333;}#mermaid-svg-jZlOTp1DrmSGPXqL .cluster span{color:#333;}#mermaid-svg-jZlOTp1DrmSGPXqL div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-jZlOTp1DrmSGPXqL .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-jZlOTp1DrmSGPXqL rect.text{fill:none;stroke-width:0;}#mermaid-svg-jZlOTp1DrmSGPXqL .icon-shape,#mermaid-svg-jZlOTp1DrmSGPXqL .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jZlOTp1DrmSGPXqL .icon-shape p,#mermaid-svg-jZlOTp1DrmSGPXqL .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-jZlOTp1DrmSGPXqL .icon-shape .label rect,#mermaid-svg-jZlOTp1DrmSGPXqL .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jZlOTp1DrmSGPXqL .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-jZlOTp1DrmSGPXqL .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-jZlOTp1DrmSGPXqL :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
同一能力组
不同能力组
两个 ImageParticle都显式设置了属性?
💥 崩溃
✅ 安全
崩溃条件:两个 ImageParticle 都显式设置了着色组中的任意属性:
- color / colorVariation
- redVariation / greenVariation / blueVariation
- alpha / alphaVariation
安全场景:以下能力组不受影响:
- 旋转组:rotation / rotationVelocity / rotationVariation
- 变形组:xVector / yVector
6.2 不受影响的场景
- 源组和目标组都使用 ItemParticle
- 只有一个 ImageParticle 设置了着色属性
- 两个 ImageParticle 都设置了非着色属性(如 rotation)
6.3 与其他 Affector 的关系
该崩溃与以下因素无关:
- GroupGoal 的 jump 属性(true/false 都会崩溃)
- 使用 ParticleGroup.to 属性定义的时间触发跳转(也会崩溃)
6.4 Qt 版本说明
该问题从 Qt 5.x 到 Qt 6.11 均存在,Qt 官方文档将其描述为"当前实现的缺陷"(drawback of the current implementation),而非计划修复的 bug。
七、总结
这是 ImageParticle 数据共享机制的设计限制。核心规则:组转换时,源组和目标组的 ImageParticle 不能同时显式设置着色组属性。
排查这类问题的方法很简单:逐步注释代码定位触发点,然后分组测试各个属性组(着色/旋转/变形/精灵)。本例中,去掉颜色属性后问题消失,再结合官方文档的数据共享说明,根因就清晰了。
简单场景推荐方案 A(只给目标组设颜色),需要源组自定义颜色且粒子数量少用方案 B(ItemParticle)。
该问题从 Qt 5.x 到 Qt 6.11 均存在,Qt 官方将其描述为"当前实现的缺陷",没有明确是否有修复计划。
参考资料
- ImageParticle QML Type 官方文档
- Qt Quick Particles Affectors 示例






