单击列时在 Qml TableView Header 中查找单击事件
Posted
技术标签:
【中文标题】单击列时在 Qml TableView Header 中查找单击事件【英文标题】:finding click event in Qml TableView Header when Column is clicked 【发布时间】:2019-04-06 21:22:36 【问题描述】:在这个例子中我有 2 个静态 ListModel,实际上我使用 LocalStorage 来填充 ListModel,但为了简单起见,我添加了 2 个按钮来更改模型,但我想将它绑定到 TableView 的 Header Column 点击事件,并且无法从其他尝试排序的示例中弄清楚如何做到这一点,我不知道是否可以使用 ListModel 进行排序,我找不到任何示例,所以有人可以解释一下或展示一个示例,关于如何用列单击事件替换按钮,然后我可以使用它来将 sort by 参数传递给我的 LocalStorage sql 语句以更新 ListModel。
更新:我忘了提到我正在寻找 Qml / Qml javascript 解决方案,出于某种原因,我想如果我离开 C++ 标记,我会避免这个问题,我将使用这种方法作为最后的手段,因为我决定只使用 Qml 编写这个应用程序,没有 C++ 后端,但我现在确实有那个版本,因为我在导入为 Web 编写的 JavaScript 时遇到了问题,而不是 Qml JavaScript,这不一样.
要清楚,我正在尝试更改模型而不是对行进行排序,这些不是同一个问题,不同之处在于单击事件的使用方式,而我要做的就是更改查询的名称在后端,即 Qml JavaScript,我不想要 C++ 解决方案的原因是因为我在 Felgo 中这样做,但这不是 Felgo 问题,它适用于 C++,但你必须设置 Live 才能工作有了它,实际上这将是我向 github 开放的源代码,并希望它能够在没有 C++ 的情况下工作,而且似乎应该有一种方法来挂钩它,而 Mouse 确实为我工作,捕获了它甚至阻止标题加载,因为它在开始时挂起并等待输入,但如果我必须这样做,我相信你的解决方案会起作用,那么我会接受它,对这种混乱感到抱歉,我对什么感到困惑要使用的标签,所以最初我只包含了 qml,并且将 qt 添加到其中,我认为这是一个好主意,因为这确实是一个 Qt 问题,这与只到 Qml,而不是 C++,这是另一个标签,这是 Felgo 正在推动的趋势,他们有充分的理由,它更易于 JavaScript 或 C/C++ 程序员使用,并且在没有 C++ 的情况下使用实时调试更快后端,所以现在我提供了更多信息,当最初我虽然这是一个简单的问题,只与 Qml 有关,如果不是,那么已经给出了 C++ 的答案,除非有更好的方法,看看我想要的是否可以像在按钮上一样单击标题列,我可以将按钮嵌入到列中吗?如果有怎么办?我找不到这样的例子,只有那些会影响文本属性并会对行进行排序的例子,这不是我想要做的,只是更新模型。
import QtQuick 2.11
import QtQuick.Controls 1.3
import QtQuick.Layouts 1.3
import QtQuick.Window 2.11
Window
visible: true
width: 640
height: 480
title: qsTr("TableView Sort")
Column
id: column
spacing: 9
anchors.fill: parent
TableView
id: tableView
anchors.left: column.left
anchors.leftMargin: 6
anchors.right: column.right
anchors.rightMargin: 273
highlightOnFocus: true
model: myListModel1
sortIndicatorVisible: true
TableViewColumn
role: "title"
title: "Column 1"
//width: 133
TableViewColumn
role: "description"
title: "Column 2"
//width: 166
Button
id: button1
text: qsTr("Model 1")
anchors.left: column.left
anchors.leftMargin: 6
onClicked:
tableView.model = myListModel1
Button
id: button2
text: qsTr("Model 2")
anchors.left: column.left
anchors.leftMargin: 6
onClicked:
tableView.model = myListModel2
ListModel
id: myListModel1
ListElement
title: "Orange"
description: "Orange is Orange"
ListElement
title: "Banana"
description: "Yellow"
ListElement
title: "Apple"
description: "Red"
ListModel
id: myListModel2
ListElement
title: "Apple"
description: "Red"
ListElement
title: "Banana"
description: "Yellow"
ListElement
title: "Orange"
description: "Orange is Orange"
更新:这有效
onSortIndicatorColumnChanged: tableView.model = (sortIndicatorColumn == 0) ? myListModel1 : myListModel2
onSortIndicatorOrderChanged: tableView.model = (sortIndicatorColumn == 0) ? myListModel1 : myListModel2
感谢您的帮助。
【问题讨论】:
不要在问题标题中添加 SOLVED 【参考方案1】:您可以使用代理模型对模型进行排序。但是,没有 QML 组件,您必须使用QSortFilterProxyModel
。
这很容易做到。但是,QSortFilterProxyModel
不能与 QML 表视图一起使用(您的表使用角色名称来显示列,并且代理模型将尝试对索引进行排序)。
一个简单的例子:
class SortProxyModel : public QSortFilterProxyModel
Q_OBJECT
public:
SortProxyModel(): QSortFilterProxyModel ()
// Define the way you want to sort data
bool lessThan(const QModelIndex& left, const QModelIndex& right) const
int role = sourceModel()->roleNames().key(roleName.toLocal8Bit(), 0);
return left.data(role) < right.data(role);
Q_INVOKABLE void setSortRole(QString const& roleName) // Used to select the sort role
this->roleName = roleName;
Q_INVOKABLE virtual void sort(int /*column*/, Qt::SortOrder order = Qt::AscendingOrder)
QSortFilterProxyModel::sort(0, order); // Always use the first column.
private:
QString roleName; // Role used to sort the model
;
// main.cpp
// Declare your type to use it in QML
qmlRegisterType<SortProxyModel>("SortProxyModel", 0, 1, "SortProxyModel");
// Main.qml
import SortFilterProxyModel 0.1;
TableView
id: tableView
model: proxy // Use the proxy model rather than the model itself
sortIndicatorVisible: true
onSortIndicatorColumnChanged: // Called when you click on the header
if (sortIndicatorColumn == 0) // Set the role used to sort data
model.setSortRole("title");
else
model.setSortRole("description");
model.sort(sortIndicatorColumn, sortIndicatorOrder)
onSortIndicatorOrderChanged: // Called when you click on the header
if (sortIndicatorColumn == 0) // Set the role used to sort data
model.setSortRole("title");
else
model.setSortRole("description");
model.sort(sortIndicatorColumn, sortIndicatorOrder)
SortProxyModel
id: proxy
objectName: "proxy"
sourceModel: myListModel1
这只是一个简单的示例,您应该改进代码。但是,我认为这将是一个好的开始......
【讨论】:
我更新了我的问题以将其限制为 Qml。在查看了在 C++ 中完成的排序之后,我意识到 TableView 只有 1 列,因此它使用属性(即角色和名称)来将属性映射到列,但似乎我可以使用委托来尝试公开单击事件,但是进行排序会比使用查询刷新模型更复杂,这就是我想要做的,只需更新模型,而不是对它们进行排序。感谢您提供替代方案,很高兴知道这一点,其他发现这一点的人可能更喜欢这个想法。 在这种情况下,将onSortIndicatorColumnChanged
和onSortIndicatorOrderChanged
中的代码替换为tableView.model = (sortIndicatorColumn == 0) ?myListModel1 : myListModel2
。
成功了,谢谢,不知道如何将此标记为已接受的答案,所以我会接受您的第一个答案,所以请更新它以反映这一点,再次感谢。以上是关于单击列时在 Qml TableView Header 中查找单击事件的主要内容,如果未能解决你的问题,请参考以下文章
Array 的 onChanged 属性在 QML 中的鼠标单击时在其中推送项目时不会被调用
通过单击 QML TableView 中的列标题进行排序[关闭]