单击列时在 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 列,因此它使用属性(即角色和名称)来将属性映射到列,但似乎我可以使用委托来尝试公开单击事件,但是进行排序会比使用查询刷新模型更复杂,这就是我想要做的,只需更新模型,而不是对它们进行排序。感谢您提供替代方案,很高兴知道这一点,其他发现这一点的人可能更喜欢这个想法。 在这种情况下,将onSortIndicatorColumnChangedonSortIndicatorOrderChanged 中的代码替换为tableView.model = (sortIndicatorColumn == 0) ?myListModel1 : myListModel2 成功了,谢谢,不知道如何将此标记为已接受的答案,所以我会接受您的第一个答案,所以请更新它以反映这一点,再次感谢。

以上是关于单击列时在 Qml TableView Header 中查找单击事件的主要内容,如果未能解决你的问题,请参考以下文章

Array 的 onChanged 属性在 QML 中的鼠标单击时在其中推送项目时不会被调用

通过单击 QML TableView 中的列标题进行排序[关闭]

通过 C++ 单击按钮后更新 QML TableView

QML如何通过单击列的标题对tableView进行排序

在 QML 中单击时如何在 GridView 中显示较大版本的选定图像

如何在 2 个 qml 窗口之间进行通信