具有多选功能的 GridView
GridView with multiselect
我需要 GridView
多选。我找不到任何现有的解决方案,所以我决定扩展 GridView
的功能。
我写了一个处理多选的快速草稿:
import QtQuick 2.15
import cpp_objects.qml 1.0
GridView {
id: grid
function isSelected(index) {
return selectionManager.isIndexSelected(index)
}
SelectionManager {
id: selectionManager
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton
propagateComposedEvents: true
onClicked: {
var ctrl = mouse.modifiers & Qt.ControlModifier;
if (ctrl == false)
selectionManager.clearSelection()
var index = grid.indexAt(mouse.x, mouse.y)
selectionManager.toggleIndexSelection(index)
mouse.accepted = false
}
}
}
SelectionManager
在cpp端实现,收集选中项
这是它的界面:
class SelectionManagerComponent: public QObject
{
Q_OBJECT
public:
SelectionManagerComponent(QObject * = nullptr);
Q_INVOKABLE void toggleIndexSelection(int);
Q_INVOKABLE void clearSelection();
Q_INVOKABLE bool isIndexSelected(int) const;
private:
std::unordered_set<int> m_selected;
};
现在我遇到了最具挑战性的问题:如何可视化我的额外选择?
我希望这个 qml 组件尽可能通用,所以我不想在这里提供硬编码委托。完美的解决方案是添加某种 'selectionDelegate' 属性 ,它需要 Item
并且工作方式与 delegate
和 highlight
相同,所以我可以继承自我的自定义 GridView
并定义如何标记所选项目。但这似乎不可行。
还有其他可能性或选择吗?
我可以想到两种方法。
- 使用
Loader
作为您的代表。根据您的项目是否被选中更改 sourceComponent
。
GridView {
// Define these to specify your selected/unselected delegates
property Component selectedComponent
property Component unselectedComponent
delegate: Loader {
sourceComponent: selectionManager.isIndexSelected(index)
? selectedComponent
: unselectedComponent
}
}
- 或者您可以使用 DelegateChooser。它允许您根据模型中某个字段的值使用不同的委托。我会把它作为第一选择,但我不知道它是否适用于您的 selectionManager,因为它与模型数据无关。但也许仍然有办法让它发挥作用。
GridView {
// Define these to specify your selected/unselected delegates
property Component selectedComponent
property Component unselectedComponent
delegate: DelegateChooser {
role: "selected" // <-- This needs to be a role in your model
DelegateChoice { roleValue: true; selectedComponent }
DelegateChoice { roleValue: false; unselectedComponent }
}
}
我需要 GridView
多选。我找不到任何现有的解决方案,所以我决定扩展 GridView
的功能。
我写了一个处理多选的快速草稿:
import QtQuick 2.15
import cpp_objects.qml 1.0
GridView {
id: grid
function isSelected(index) {
return selectionManager.isIndexSelected(index)
}
SelectionManager {
id: selectionManager
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton
propagateComposedEvents: true
onClicked: {
var ctrl = mouse.modifiers & Qt.ControlModifier;
if (ctrl == false)
selectionManager.clearSelection()
var index = grid.indexAt(mouse.x, mouse.y)
selectionManager.toggleIndexSelection(index)
mouse.accepted = false
}
}
}
SelectionManager
在cpp端实现,收集选中项
这是它的界面:
class SelectionManagerComponent: public QObject
{
Q_OBJECT
public:
SelectionManagerComponent(QObject * = nullptr);
Q_INVOKABLE void toggleIndexSelection(int);
Q_INVOKABLE void clearSelection();
Q_INVOKABLE bool isIndexSelected(int) const;
private:
std::unordered_set<int> m_selected;
};
现在我遇到了最具挑战性的问题:如何可视化我的额外选择?
我希望这个 qml 组件尽可能通用,所以我不想在这里提供硬编码委托。完美的解决方案是添加某种 'selectionDelegate' 属性 ,它需要 Item
并且工作方式与 delegate
和 highlight
相同,所以我可以继承自我的自定义 GridView
并定义如何标记所选项目。但这似乎不可行。
还有其他可能性或选择吗?
我可以想到两种方法。
- 使用
Loader
作为您的代表。根据您的项目是否被选中更改sourceComponent
。
GridView {
// Define these to specify your selected/unselected delegates
property Component selectedComponent
property Component unselectedComponent
delegate: Loader {
sourceComponent: selectionManager.isIndexSelected(index)
? selectedComponent
: unselectedComponent
}
}
- 或者您可以使用 DelegateChooser。它允许您根据模型中某个字段的值使用不同的委托。我会把它作为第一选择,但我不知道它是否适用于您的 selectionManager,因为它与模型数据无关。但也许仍然有办法让它发挥作用。
GridView {
// Define these to specify your selected/unselected delegates
property Component selectedComponent
property Component unselectedComponent
delegate: DelegateChooser {
role: "selected" // <-- This needs to be a role in your model
DelegateChoice { roleValue: true; selectedComponent }
DelegateChoice { roleValue: false; unselectedComponent }
}
}