目录互斥单选演示代码关键逻辑解析多选与父子联动演示代码关键逻辑解析运行验证小结单选用 RadioButton多选用 CheckBox但数量一多当前选中了谁、谁和谁是一组就不好管理了。ButtonGroup 把一组按钮收进来由组统一管选中状态。下面两个 demo一个展示如何管理单选一个如何管理多选后者还具有父子三态联动的效果。互斥单选界面上有两组单选按钮左边竖着三个大图标视图、列表视图、详细信息视图下面横着两个平铺、内容预览。它们不在同一个父容器里却同属一个 ButtonGroup所以只能选中一个。点任何一个另一个自动取消底部文字实时显示当前选中的视图。演示代码import QtQuick import QtQuick.Controls import QtQuick.Layouts FadeInAnimation { ColumnLayout { anchors.fill: parent anchors.margins: 20 spacing: 15 // ... 省略标题组件 TitleSeparator ... // 互斥按钮组跨容器组织单选 ButtonGroup { id: viewGroup exclusive: true onCheckedButtonChanged: { if (checkedButton) statusText.text 当前视图 checkedButton.text } } ColumnLayout { spacing: 10 RadioButton { text: 大图标视图; ButtonGroup.group: viewGroup; checked: true } RadioButton { text: 列表视图; ButtonGroup.group: viewGroup } RadioButton { text: 详细信息视图; ButtonGroup.group: viewGroup } } RowLayout { spacing: 20 RadioButton { text: 平铺; ButtonGroup.group: viewGroup } RadioButton { text: 内容预览; ButtonGroup.group: viewGroup } } Text { id: statusText Layout.fillWidth: true color: #1296FF font.pointSize: 11 text: 当前视图大图标视图 } Text { Layout.fillWidth: true color: #999 font.pointSize: 11 wrapMode: Text.Wrap text: 提示两组按钮位于不同父容器但同属一个 ButtonGroup互斥生效 } Item { Layout.fillHeight: true } } }关键逻辑解析exclusive 决定单选还是多选ButtonGroup 最核心的属性是 exclusive。为 true 时组内一次只能选中一个选中新的会自动取消旧的——这正是单选按钮需要的互斥行为。RadioButton 天生就是单选控件再套一层 ButtonGroup把成员关系和选中状态统一管起来。附加属性把按钮登记进组每个 RadioButton 上写ButtonGroup.group: viewGroup靠这个附加属性加入组。按钮不需要是兄弟节点——竖排的在一组 Column 里横排的在另一组 Row 里父容器完全无关但只要都登记进同一个组互斥照常生效。布局怎么摆都行分组只看声明不看位置。组用 checkedButton 暴露选中项组的只读属性checkedButton指向当前选中的按钮。onCheckedButtonChanged在选中项变化时触发把新的按钮文字写到底部状态栏。每个 RadioButton 不用各自维护我是不是被选中的那个判断逻辑集中在组这一层。多选与父子联动一个父级 CheckBox功能开关控制五个子项代码高亮、行号显示、自动缩进、括号匹配、拼写检查。父节点是三态的——全选、部分选中、全不选。点父节点五个子项一起变手动勾几个子项父节点自动变成全选或部分选中。演示代码import QtQuick import QtQuick.Controls import QtQuick.Layouts FadeInAnimation { ColumnLayout { anchors.fill: parent anchors.margins: 20 spacing: 15 // ... 省略标题组件 TitleSeparator ... // 非互斥组父子双向绑定 checkState ButtonGroup { id: featureGroup exclusive: false checkState: parentBox.checkState buttons: childColumn.children } CheckBox { id: parentBox text: 功能开关父节点 tristate: true checkState: featureGroup.checkState Layout.alignment: Qt.AlignLeft onCheckStateChanged: { var s checkState Qt.Checked ? 全选 : checkState Qt.PartiallyChecked ? 部分选中 : 全不选 statusText.text 父节点状态 s } } ColumnLayout { id: childColumn Layout.leftMargin: 30 spacing: 10 CheckBox { text: 代码高亮 } CheckBox { text: 行号显示; checked: true } CheckBox { text: 自动缩进 } CheckBox { text: 括号匹配; checked: true } CheckBox { text: 拼写检查 } } Text { id: statusText Layout.fillWidth: true color: #1296FF font.pointSize: 11 } Text { Layout.fillWidth: true color: #999 font.pointSize: 11 wrapMode: Text.Wrap text: 提示父节点 tri-state 双向绑定子节点全部选中时父自动勾选部分选中时父显示半选状态 } Item { Layout.fillHeight: true } } }关键逻辑解析exclusive 设为 false组变成收集器这次组不再做互斥exclusive 为 false所有子项可以同时选中。ButtonGroup 的价值在于把整组按钮收集起来统一计算整体状态。它通过buttons属性接收成员——这里直接写成childColumn.children把一列 CheckBox 一次性全部收进组不用一个个登记。checkState 三态父子双向绑定这是整个 demo 的难点。ButtonGroup 有自己的 checkState整组的状态父 CheckBox 也有 checkState。代码里两行互相绑定一行让组的 checkState 取父节点的值父决定子另一行让父节点的 checkState 取组的值子回写父。两个绑定连成一个环任意一边变化另一边跟着同步。父节点开了tristate才有三种状态全选、部分选中、全不选。子项全部勾上时组的状态是全选父节点自动打勾只勾一部分时组的状态是部分选中父节点变成半选一个都不勾时父节点是空。整个过程不用手写统计几个勾了几个没勾的代码。信号处理器把状态翻译成人话onCheckStateChanged里用 checkState 和 Qt.Checked、Qt.PartiallyChecked、Qt.Unchecked 三个常量比较把状态翻译成全选/部分选中/全不选显示在底部。这段只是方便观察核心的联动逻辑已经由 checkState 的绑定完成了。互斥单选和多选联动的区别很简单exclusive 为 true 时配 RadioButton适合视图模式、对齐方式这类只能选一个的场景exclusive 为 false 时配 CheckBox适合功能选项、筛选条件组的作用是汇总整组状态、做三态联动。运行验证Qt Creator 打开示例的 CMakeLists.txt按 CtrlR 运行互斥单选依次点五个单选按钮看底部文字跟着变注意竖排和横排之间也是互斥的多选联动点父节点看五个子项一起变手动勾几个子项看父节点在全选/部分选中/全不选之间切换。小结视图模式切换、对齐方式这类只能选一个的场景直接用互斥 ButtonGroup 加 RadioButton。全选/部分选的父子联动适合做设置面板、筛选条件多个开关统一由一个总开关控制。把按钮组、三态父级封装成组件暴露已选列表和全选信号可以全项目复用。ButtonGroup 也可以管理普通 Button配合 checkable实现工具栏按钮之间的互斥。已验证环境Qt 版本Qt 6.11.1操作系统Windows 11项目地址QML 示例合集V2.0 - qml_action_button_group