如何在QT/QML中将多个信号连接到一个插槽?
How to connect multiple signals to one slot in QT/QML?
我有一个自定义工具栏组件,我希望其中的按钮组件发出切换信号。我还想在顶级工具栏组件的一个 onToggled
处理程序中捕获所有按钮的信号。
我知道可以通过Repeater
+ Component
+ VisualItemModel
来实现,但我觉得有点矫枉过正。
有没有更简单的方法?
再次重申。当前示例代码工作正常,没有任何问题。我的问题是我发现它 非常 复杂的小问题可以用我的伪代码解决(如果 QML 中有类似的东西)
伪代码:
// CustomButton emits onClicked(string name)
Rectangle {
CustomButton {
id: button2
text: "Button1"
name: "button1"
}
CustomButton {
id: button2
text: "Button2"
name: "button2"
}
CustomButton {
id: button3
text: "Button3"
name: "button3"
}
}
Connections {
target: button1, button2, button3
onClicked: { console.log ("Button "+name+" pressed"); }
}
当前代码:
ApplicationToolbar.qml
import QtQuick 2.0
import QtQuick.Layouts 1.11
import QtQuick.Controls 1.4
import "../Style"
import "../Widgets/Buttons"
Rectangle {
id: toolbar
Gradients { id: gradients }
width: parent.width
height: UIStyle.buttonHeight + 2*UIStyle.verticalSpacer
gradient: storage.operationMode()==="online" ? gradients.onlineTabbarGradient : gradients.trainingTabbarGradient
property int defaultItem : 0
property VisualItemModel toolbarModel
property var subtabs
signal tabItemClicked(string tabid)
Component {
id: toolbarItem
ButtonTab {
height: toolbarModel.children[index].height
selected: toolbarModel.children[index].selected
iconsource: toolbarModel.children[index].iconsource
MouseArea {
anchors.fill: parent
onClicked: {
console.log ("toggled index "+index);
for (var i = 0; i < toolbarModel.count; i++) toolbarModel.children[i].selected = false;
toolbarModel.children[index].selected = true;
toolbar.tabItemClicked(toolbarModel.children[index].name);
}
}
}
}
RowLayout {
id: tabs
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.leftMargin: UIStyle.horizontalSpacer
spacing: UIStyle.horizontalSpacer/2
Repeater {
model: toolbarModel.count
delegate: toolbarItem
}
}
Component.onCompleted: {
for (var i = 0; i < toolbarModel.count; i++) toolbarModel.children[i].selected = false;
toolbarModel.children[defaultItem].selected = true
toolbar.tabItemClicked(toolbarModel.children[defaultItem].name);
}
}
ButtonTab.qml
import QtQuick 2.0
import QtQuick.Extras 1.4
import QtQuick.Layouts 1.11
import "../../Style"
import "../"
Rectangle {
id: buttontab
property string name
property string iconsource: ""
property bool selected: false
Gradients { id: gradients }
width: UIStyle.buttonWidth * 3
height: selected ? UIStyle.buttonHeight * 1.25 : UIStyle.buttonHeight
radius: UIStyle.cornerRadiusSmall
// doesn't work
//Layout.alignment: Qt.AlignBottom
anchors.bottom: parent.bottom
gradient: {
if (!enabled) {
gradients.disabledButtonGradient
} else if (selected) {
gradients.selectedTabButtonGradien
} else {
gradients.tabButtonGradient
}
}
Image {
source : buttontab.iconsource
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
}
您不需要 VisualItemModel
(顺便说一下已被 ObjectModel
取代)来使用 Repeater
,如果可以的话,一个简单的按钮文本字符串列表就足够了接受使用按钮的索引而不是插槽中的名称:
Row {
Repeater {
model: ["Button 1", "Button 2", "Button 3"]
delegate: CustomButton {
text: modelData
onClicked: console.log("Button " + index + " pressed")
}
}
}
如果您真的需要按钮也有一个名称,您仍然可以回到对象列表:
Row {
Repeater {
model: [{ text: "Button 1", name: "button1" },
{ text: "Button 2", name: "button2" },
{ text: "Button 3", name: "button3" }]
delegate: CustomButton {
text: modelData.text
name: modelData.name
onClicked: console.log("Button " + name + " pressed")
}
}
}
我有一个自定义工具栏组件,我希望其中的按钮组件发出切换信号。我还想在顶级工具栏组件的一个 onToggled
处理程序中捕获所有按钮的信号。
我知道可以通过Repeater
+ Component
+ VisualItemModel
来实现,但我觉得有点矫枉过正。
有没有更简单的方法?
再次重申。当前示例代码工作正常,没有任何问题。我的问题是我发现它 非常 复杂的小问题可以用我的伪代码解决(如果 QML 中有类似的东西)
伪代码:
// CustomButton emits onClicked(string name)
Rectangle {
CustomButton {
id: button2
text: "Button1"
name: "button1"
}
CustomButton {
id: button2
text: "Button2"
name: "button2"
}
CustomButton {
id: button3
text: "Button3"
name: "button3"
}
}
Connections {
target: button1, button2, button3
onClicked: { console.log ("Button "+name+" pressed"); }
}
当前代码:
ApplicationToolbar.qml
import QtQuick 2.0
import QtQuick.Layouts 1.11
import QtQuick.Controls 1.4
import "../Style"
import "../Widgets/Buttons"
Rectangle {
id: toolbar
Gradients { id: gradients }
width: parent.width
height: UIStyle.buttonHeight + 2*UIStyle.verticalSpacer
gradient: storage.operationMode()==="online" ? gradients.onlineTabbarGradient : gradients.trainingTabbarGradient
property int defaultItem : 0
property VisualItemModel toolbarModel
property var subtabs
signal tabItemClicked(string tabid)
Component {
id: toolbarItem
ButtonTab {
height: toolbarModel.children[index].height
selected: toolbarModel.children[index].selected
iconsource: toolbarModel.children[index].iconsource
MouseArea {
anchors.fill: parent
onClicked: {
console.log ("toggled index "+index);
for (var i = 0; i < toolbarModel.count; i++) toolbarModel.children[i].selected = false;
toolbarModel.children[index].selected = true;
toolbar.tabItemClicked(toolbarModel.children[index].name);
}
}
}
}
RowLayout {
id: tabs
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.leftMargin: UIStyle.horizontalSpacer
spacing: UIStyle.horizontalSpacer/2
Repeater {
model: toolbarModel.count
delegate: toolbarItem
}
}
Component.onCompleted: {
for (var i = 0; i < toolbarModel.count; i++) toolbarModel.children[i].selected = false;
toolbarModel.children[defaultItem].selected = true
toolbar.tabItemClicked(toolbarModel.children[defaultItem].name);
}
}
ButtonTab.qml
import QtQuick 2.0
import QtQuick.Extras 1.4
import QtQuick.Layouts 1.11
import "../../Style"
import "../"
Rectangle {
id: buttontab
property string name
property string iconsource: ""
property bool selected: false
Gradients { id: gradients }
width: UIStyle.buttonWidth * 3
height: selected ? UIStyle.buttonHeight * 1.25 : UIStyle.buttonHeight
radius: UIStyle.cornerRadiusSmall
// doesn't work
//Layout.alignment: Qt.AlignBottom
anchors.bottom: parent.bottom
gradient: {
if (!enabled) {
gradients.disabledButtonGradient
} else if (selected) {
gradients.selectedTabButtonGradien
} else {
gradients.tabButtonGradient
}
}
Image {
source : buttontab.iconsource
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
}
您不需要 VisualItemModel
(顺便说一下已被 ObjectModel
取代)来使用 Repeater
,如果可以的话,一个简单的按钮文本字符串列表就足够了接受使用按钮的索引而不是插槽中的名称:
Row {
Repeater {
model: ["Button 1", "Button 2", "Button 3"]
delegate: CustomButton {
text: modelData
onClicked: console.log("Button " + index + " pressed")
}
}
}
如果您真的需要按钮也有一个名称,您仍然可以回到对象列表:
Row {
Repeater {
model: [{ text: "Button 1", name: "button1" },
{ text: "Button 2", name: "button2" },
{ text: "Button 3", name: "button3" }]
delegate: CustomButton {
text: modelData.text
name: modelData.name
onClicked: console.log("Button " + name + " pressed")
}
}
}