问题描述
我需要一个具有多选功能的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
的工作方式相同,因此我可以从自定义{{ 1}},并定义如何标记所选项目。但这似乎不可行。
还有其他可能性或选择吗?
解决方法
我可以想到两种方法。
- 使用
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 }
}
}