所以在我的项目中,我使用的是具有模型的tableview:tableModel fopm Qt.labs.qmlmodels 1.0;所以我想用一些方法对它进行排序,我发现了QAbsructProxyModel类,我不知道我是否使用得很好,但是我发现代码过滤和排序的问题在我的代码下面,在此先感谢neeed help
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);
}
答案 0 :(得分:1)
我无法运行您的代码。由于我使用的是旧版Qt。因此,我使用重新实现的QSortFilterProxyModel类制作了一个简单的工作原型,并在qml中将其用于过滤和排序。我的源模型是一个列表视图,在您的情况下是一个表视图。其他都一样。
代码的可能部分需要检查。
1.重新实现filterAcceptsRow
2.重新实现lessThan
3.确保在更改搜索文本时致电invalidateFilter
4.确保在更改sortOrder
sort
函数
============这里的示例代码============
************** 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;
}