QML 如何通过点击列头对tableView进行排序。

问题描述 投票:0回答:1

所以在我的项目中,我使用一个tableview,它有模型:tableModel fopm Qt.labs.qmlmodels 1.0;所以我想排序它使用一些方法,我发现类QAbsructProxyModel,我不知道如果我使用它很好,但我发现的问题在filtring和排序这里是下面我的代码,提前感谢`Neeed帮助,请。

    import QtQuick 2.15
import QtQuick.Window 2.12
import Qt.labs.qmlmodels 1.0
import QtQuick.Controls 2.15
import QtQml.Models 2.15

import org.qtproject.example 1.0

ApplicationWindow {
    width: 1000
    height: 400
    visible: true

     header: ToolBar {
        TextField {
            id: searchBox


            placeholderText: "Search..."
            inputMethodHints: Qt.ImhNoPredictiveText

            //width: window.width / 5 * 2
            anchors.right: parent.right
            anchors.verticalCenter: parent.verticalCenter
        }
    }



    TableView {
        id:tableView
        anchors.fill: parent
        //sortIndicatorVisible: true

        //anchors.topMargin: 30
        columnSpacing: 1
        rowSpacing: 3
        anchors.topMargin:30
        //boundsBehavior: Flickable.StopAtBounds



        model:SortFilterProxyModel {
            id: proxyModel
            source: sourceModel.rowCount> 0 ? sourceModel : null
            onSourceChanged: console.log(source+" source")

            sortOrder: Qt.AscendingOrder//tableView.sortIndicatorOrder

            sortCaseSensitivity: Qt.CaseInsensitive
            sortRole: sourceModel.rowCount > 0 ? " nomdetrame": ""
            onSortRoleChanged: console.log(" role")
            filterString: "*" + searchBox.text + "*"
            //onFilterStringChanged: console.log(filterString)
            filterSyntax: SortFilterProxyModel.Wildcard
            filterCaseSensitivity: Qt.CaseInsensitive
        }

            TableModel {
            id:sourceModel


            TableModelColumn{ display: " teta"}
            TableModelColumn { display: "visibilite" }
            TableModelColumn { display: "couleur" }
            TableModelColumn{ display: "chaine_can"}
            TableModelColumn{ display: "nomdetrame" }
            TableModelColumn{ display: "nondusignal"}
            TableModelColumn { display: "valeurDec" }
            TableModelColumn { display: "valeurHex" }
            TableModelColumn { display: "TxouRx" }


            // Each row is one type of fruit that can be ordered
            rows: [
                {
                    // Each property is one cell/column.
                    teta:"+",
                    visibilite: false,
                    couleur: "red",
                    chaine_can: "CAN 4",
                    nomdetrame: "rRX",
                    nondusignal: "1.50",
                    valeurDec: "CAN 4",
                    valeurHex: "rRX",
                    TxouRx: "Tx"
                },
                {   teta:"+",
                    visibilite: false,
                    couleur: "grey",
                    chaine_can: "CAN 1",
                    nomdetrame: "rRX",
                    nondusignal: "1.5",
                    valeurDec: "CAN 4",
                    valeurHex: "rRX",
                    TxouRx: "Rx"
                },
                {   teta:"+",
                    visibilite: true,
                    couleur: "black",
                    chaine_can: "CAN 2",
                    nomdetrame: "rRX",
                    nondusignal: "1",
                    valeurDec: "CAN 4",
                    valeurHex: "RXE",
                    TxouRx: "Tx"
                }
            ]



        }





        delegate:  DelegateChooser {

            DelegateChoice{
                column: 0
                //width: 100
            delegate:Button{
                    id:teta
                    text:"+"
                    //anchors.fill: parent
                    onClicked:{tableView.sourceModel.appendRow({
                                                   // Each property is one cell/column.
                                                   teta:"+",
                                                   visibilite: false,
                                                   couleur: "red",
                                                   chaine_can: "CAN 4",
                                                   nomdetrame: "rRX",
                                                   nondusignal: "1.50",
                                                   valeurDec: "CAN 4",
                                                   valeurHex: "rRX",
                                                   TxouRx: "Tx"
                                               }
                                               )}

                }
                //z: -1
            }

            DelegateChoice{
                column: 1
            delegate:Rectangle{
                border.color: "black"
                implicitWidth: 80
                CheckBox{
                //anchors.fill: parent
                    anchors.centerIn: parent
                checked: model.display


            }
        }
            }
            DelegateChoice{
                column: 2
            delegate:Rectangle {
                implicitWidth: 80
                //anchors.fill: parent
                 border.color: "black"
                color: model.display
                //z: -1
            }
        }
            DelegateChoice{
                column: 3
            delegate:Rectangle{
                border.color:"black"
                implicitWidth: 80

                Button{
                    anchors.fill: parent
                    onClicked: console.log(currentIndex)
//                    TextInput {
//                        //textRole: "display"
//                    anchors.fill: parent
//                    text:model.display
//                    //z: -1
//                }
                }


        }
            }
            DelegateChoice{
                column: 4
           delegate:Rectangle{
               border.color: "black"
               implicitWidth: 80
               TextInput {
                //anchors.fill: parent
                   anchors.centerIn: parent
                text:model.display
                //z: -1
            }
        }
            }
            DelegateChoice{
                column: 5
            delegate:Rectangle{
                border.color: "black"
                implicitWidth: 80
                TextInput {
                //anchors.fill: parent
                    anchors.centerIn: parent
                text:model.display
                //z: -1
            }
        }
            }
            DelegateChoice{
                column: 6
            delegate:Rectangle{
                implicitWidth: 80
                border.color: "black"
                TextInput {
//                anchors.fill: parent
                    anchors.centerIn: parent
                text:model.display
                //z: -1
            }
        }
            }
            DelegateChoice{
                column: 7
            delegate:Rectangle{
                implicitWidth: 80
                border.color: "black"

                TextInput {
                //anchors.fill: parent
                    anchors.centerIn: parent
                text:model.display
                //z: -1
            }
        }
            }
            DelegateChoice{
                column: 8
            delegate:Rectangle{
                implicitWidth: 80
                border.color: "black"
                TextInput {
                //anchors.fill: parent
                    anchors.centerIn: parent
                text:model.display

                //z: -1
            }
            }
        }


    }
        Component.onCompleted: {
            console.log(searchBox.text)
            //console.log(tableView.model.getRow(0).couleur)}

}
    }
    HorizontalHeaderView{
        id:headerView
        anchors.left: tableView.left
      syncView: tableView
      model:[" ","Visible","Couleur","Chaine_Can","NomTrame","NomSignal","ValeurDec","ValeurHex","TX/RX"]





        MouseArea{
            id:ms
            anchors.fill: parent
            hoverEnabled: true


        }

    }




}

c++代码。

include "sortfilterproxymodel.h"
#include <QtDebug>
#include <QtQml>

SortFilterProxyModel::SortFilterProxyModel(QObject *parent) : QSortFilterProxyModel(parent), m_complete(false)
{
    connect(this, &QSortFilterProxyModel::rowsInserted, this, &SortFilterProxyModel::countChanged);
    connect(this, &QSortFilterProxyModel::rowsRemoved, this, &SortFilterProxyModel::countChanged);
    qDebug()<<"je suis entré chez moi";
}

int SortFilterProxyModel::count() const
{
    return rowCount();
}

QObject *SortFilterProxyModel::source() const
{
    return sourceModel();
}

void SortFilterProxyModel::setSource(QObject *source)
{
    setSourceModel(qobject_cast<QAbstractItemModel *>(source));
    emit sourceChanged();
}

QByteArray SortFilterProxyModel::sortRole() const
{
    return m_sortRole;
}

void SortFilterProxyModel::setSortRole(const QByteArray &role)
{
    if (m_sortRole != role) {
        m_sortRole = role;
        if (m_complete)
            QSortFilterProxyModel::setSortRole(roleKey(role));
    }
}

void SortFilterProxyModel::setSortOrder(Qt::SortOrder order)
{
    QSortFilterProxyModel::sort(0, order);
}

QByteArray SortFilterProxyModel::filterRole() const
{
    return m_filterRole;
}

void SortFilterProxyModel::setFilterRole(const QByteArray &role)
{
    if (m_filterRole != role) {
        m_filterRole = role;
        if (m_complete)
            QSortFilterProxyModel::setFilterRole(roleKey(role));
    }
}

QString SortFilterProxyModel::filterString() const
{
    return filterRegExp().pattern();
}

void SortFilterProxyModel::setFilterString(const QString &filter)
{

    setFilterRegExp(QRegExp(filter, filterCaseSensitivity(), static_cast<QRegExp::PatternSyntax>(filterSyntax())));
    emit filterStringChanged();
}


SortFilterProxyModel::FilterSyntax SortFilterProxyModel::filterSyntax() const
{
    return static_cast<FilterSyntax>(filterRegExp().patternSyntax());
}

void SortFilterProxyModel::setFilterSyntax(SortFilterProxyModel::FilterSyntax syntax)
{
    setFilterRegExp(QRegExp(filterString(), filterCaseSensitivity(), static_cast<QRegExp::PatternSyntax>(syntax)));
}

QJSValue SortFilterProxyModel::get(int idx) const
{
    QJSEngine *engine = qmlEngine(this);
    QJSValue value = engine->newObject();
    if (idx >= 0 && idx < count()) {
        QHash<int, QByteArray> roles = roleNames();
        for (auto it = roles.cbegin(), end = roles.cend(); it != end; ++it)
            value.setProperty(QString::fromUtf8(it.value()), data(index(idx, 0), it.key()).toString());
    }
    return value;
}

void SortFilterProxyModel::classBegin()
{
}

void SortFilterProxyModel::componentComplete()
{
    m_complete = true;

    if (!m_sortRole.isEmpty())
        QSortFilterProxyModel::setSortRole(roleKey(m_sortRole));

    if (!m_filterRole.isEmpty())
        QSortFilterProxyModel::setFilterRole(roleKey(m_filterRole));

}

int SortFilterProxyModel::roleKey(const QByteArray &role) const
{
    return roleNames().key(role, -1);

}

QHash<int, QByteArray> SortFilterProxyModel::roleNames() const
{
    qDebug()<<"RoleNames";
    if (QAbstractItemModel *source = sourceModel()){
        qDebug()<<"RoleNames";
        //qDebug()<< source->roleNames();
                    //qDebug()<<roleNames().key(0)<< " keys";
        return source->roleNames();}
    return QHash<int, QByteArray>();
}

bool SortFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
    QRegExp rx = filterRegExp();
    if (rx.isEmpty())
        return true;
    QAbstractItemModel *model = sourceModel();
    if (filterRole().isEmpty()) {
        QHash<int, QByteArray> roles = roleNames();
        for (auto it = roles.cbegin(), end = roles.cend(); it != end; ++it) {
            QModelIndex sourceIndex = model->index(sourceRow, 0, sourceParent);
            QString key = model->data(sourceIndex, it.key()).toString();
            if (key.contains(rx))
                return true;
        }
        return false;
    }
    QModelIndex sourceIndex = model->index(sourceRow, 0, sourceParent);
    if (!sourceIndex.isValid())
        return true;
    QString key = model->data(sourceIndex, roleKey(filterRole())).toString();
    qDebug()<<rx;
    return key.contains(rx);
}

qt sorting search qml tableview
1个回答
0
投票

我无法运行你的代码。由于我使用的是旧版本的Qt。所以我做了一个简单的工作proto与重新实现的QSortFilterProxyModel类,并在qml中使用它进行过滤和排序。我的源模型是一个列表视图,在你的例子中是一个表格视图,其他东西都是一样的。

可能部分代码需要检查.1. 重新实现 filterAcceptsRow2. 2. 重新执行 lessThan3. 确保打电话给 invalidateFilter 同时更改搜索文本4。确保调用默认的 sort 函数,同时改变sortOrder

************** main.qml **************
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.2

import SortFilter 1.0

Window {
    id: rootId
    width: 320
    height: 568
    visible: true

    SortFilterProxy {
        id: sortFilterProxyModelId
        sourceModel: fruitModel
        sortRole: Qt.DisplayRole
        searchString: ""
        sortOrder: Qt.AscendingOrder
    }

    ListModel {
        id: fruitModel
        ListElement { name: "Apple" }
        ListElement { name: "Orange" }
        ListElement { name: "Banana" }
    }

    Column {
        anchors.fill: parent

        TextField {
            id: searchIpId
            height: 40
            width: parent.width
            focus: true
            placeholderText: "Enter search text"
            onTextChanged: sortFilterProxyModelId.searchString = text

            Button {
                id: sortButtonId
                height: parent.height - 10
                width: 60
                text: "sort"
                anchors.rightMargin: 10
                anchors.right: parent.right
                anchors.verticalCenter: parent.verticalCenter
                onClicked: {
                    // call proxy
                    if(sortFilterProxyModelId.sortOrder == Qt.AscendingOrder)
                        sortFilterProxyModelId.sortOrder = Qt.DescendingOrder
                    else
                        sortFilterProxyModelId.sortOrder = Qt.AscendingOrder
                    searchIpId.forceActiveFocus()
                }
            }
        }

        ListView {
            width: parent.width
            height: parent.height - searchIpId.height
            model: sortFilterProxyModelId // change to proxy output
            delegate: Rectangle {
                width: parent.width
                height: 40
                color: index % 2 == 0 ? "white" : "#C0C0C0"
                Label {
                    anchors.fill: parent
                    anchors.margins: 10
                    text: name
                }
            }
        }
    }
}


************** sortfilterproxymodel.h **************
#ifndef SORTPROXYMODEL_H
#define SORTPROXYMODEL_H

#include <QSortFilterProxyModel>

class SortFilterProxyModel : public QSortFilterProxyModel
{
    Q_OBJECT
    Q_PROPERTY(QString searchString READ searchString WRITE setSearchString NOTIFY searchStringChanged)
    Q_PROPERTY(Qt::SortOrder sortOrder READ sortOrder WRITE setSortOrder NOTIFY sortOrderChanged)
public:
    explicit SortFilterProxyModel(QObject* parent = nullptr);

    QString searchString() const
    {
        return _searchString;
    }
    Qt::SortOrder sortOrder() const
    {
        return _sortOrder;
    }
    void setSearchString(const QString &searchString);
    void setSortOrder(const Qt::SortOrder &sortOrder);

signals:
    void searchStringChanged(QString searchString);
    void sortOrderChanged(Qt::SortOrder sortOrder);

protected:
    bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const;   // custom sort logic
    bool filterAcceptsRow(int sourceRow,const QModelIndex &sourceParent) const;             // custom filter logic

private:
    QString _searchString;
    Qt::SortOrder _sortOrder;
};

#endif // SORTPROXYMODEL_H


************** sortfilterproxymodel.cpp **************
 #include "sortfilterproxymodel.h"

SortFilterProxyModel::SortFilterProxyModel(QObject* parent) :
    QSortFilterProxyModel(parent)
{
    connect(this, &SortFilterProxyModel::searchStringChanged, this, &SortFilterProxyModel::invalidate); //
}

void SortFilterProxyModel::setSearchString(const QString &searchString)
{
    if (_searchString == searchString)
        return;

    _searchString = searchString;
    emit searchStringChanged(searchString); // connected with invalidateFilter, internally invalidateFilter makes call to filterAcceptsRow function
}

void SortFilterProxyModel::setSortOrder(const Qt::SortOrder &sortOrder)
{
    if(_sortOrder == sortOrder)
        return ;
    _sortOrder = sortOrder;
    sort(0, sortOrder);         // responsible call to make sorting, internally it will make a call to lessthan function
    emit sortOrderChanged(sortOrder);
}

bool SortFilterProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
{
    QVariant left = sourceModel()->data(source_left);
    QVariant right = sourceModel()->data(source_right);

    if(left.isValid() && right.isValid())
    {
        return left.toString() > right.toString();
    } else
    {
        return false;
    }
}

bool SortFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
    QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
    QString data = sourceModel()->data(index, Qt::DisplayRole).value<QString>();

    if(_searchString.isEmpty() || _searchString.isNull())
        return true;

    if(data.contains(_searchString, Qt::CaseInsensitive))
        return true;

    return false;
}


© www.soinside.com 2019 - 2024. All rights reserved.