Qt QML如何通过单击列的标题对tableView进行排序
所以在我的项目中,我使用了一个具有模型的tableview:TableModelFopm Qt.labs.qmlmodels 1.0; 所以我想用一些方法对它进行排序,我发现类QabStructProxyModel,我不知道我是否使用得很好,但我发现过滤和排序方面的问题在我的代码下面,请提前感谢需要帮助的人Qt QML如何通过单击列的标题对tableView进行排序,qt,sorting,search,qml,tableview,Qt,Sorting,Search,Qml,Tableview,所以在我的项目中,我使用了一个具有模型的tableview:TableModelFopm Qt.labs.qmlmodels 1.0; 所以我想用一些方法对它进行排序,我发现类QabStructProxyModel,我不知道我是否使用得很好,但我发现过滤和排序方面的问题在我的代码下面,请提前感谢需要帮助的人 import QtQuick 2.15 import QtQuick.Window 2.12 import Qt.labs.qmlmodels 1.0 import QtQuick.
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);
}
包括“sortfilterproxymodel.h”
#包括
#包括
SortFilterProxyModel::SortFilterProxyModel(QObject*父对象):QSortFilterProxyModel(父对象),m_complete(false)
{
连接(this,&QSortFilterProxyModel::rowsInserted,this,&SortFilterProxyModel::countChanged);
连接(此,&QSortFilterProxyModel::rowsRemoved,此,&SortFilterProxyModel::countChanged);
qDebug()=0&&idx qDebug()我无法运行您的代码。因为我使用的是较旧版本的Qt。因此,我使用重新实现的QSortFilterProxyModel类制作了一个简单的工作原型,并在qml中使用它进行筛选和排序。我的源模型是一个列表视图,在您的示例中,它是一个表视图。其他方面也是一样的
代码的可能部分需要检查。
1.重新实施filterAcceptsRow
2.重新实施lessThan
3.确保在更改搜索文本时调用invalidateFilter
4.确保在更改排序器时调用默认的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;
}
*************main.qml**************
导入QtQuick 2.9
导入QtQuick.Window 2.2
导入QtQuick.Controls 2.2
导入SortFilter 1.0
窗口{
id:rootId
宽度:320
身高:568
可见:正确
酸滤氧化{
id:sortFilterProxyModelId
sourceModel:水果模型
sortRole:Qt.DisplayRole
搜索字符串:“
排序器:Qt.AscendingOrder
}
列表模型{
id:水果模型
ListElement{name:“Apple”}
ListElement{name:“Orange”}
ListElement{name:“香蕉”}
}
纵队{
锚定。填充:父级
文本字段{
id:searchIpId
身高:40
宽度:parent.width
焦点:正确
占位符文本:“输入搜索文本”
ContextChanged:sortFilterProxyModelId.searchString=text
钮扣{
id:sortButtonId
高度:parent.height-10
宽度:60
文本:“排序”
1.右页边距:10
anchors.right:父项.right
anchors.verticalCenter:父级.verticalCenter
再次点击:{
//呼叫代理
if(sortFilterProxyModelId.sortOrder==Qt.AscendingOrder)
sortFilterProxyModelId.sortOrder=Qt.DowningOrder
其他的
sortFilterProxyModelId.sortOrder=Qt.AscendingOrder
searchIpId.forceActiveFocus()
}
}
}
列表视图{
宽度:parent.width
高度:parent.height-searchIpId.height
模型:sortFilterProxyModelId//更改为代理输出
代表:矩形{
宽度:parent.width
身高:40
颜色:索引%2==0?“白色”:“#C0”
标签{
锚定。填充:父级
2.5.2.利润率:10
文本:名称
}
}
}
}
}
**************sortfilterproxymodel.h**************
#ifndef SORTPROXY模型
#定义SortProxy模型
#包括
类SortFilterProxyModel:公共QSortFilterProxyModel
{
Q_对象
Q_属性(QString searchString读取searchString写入setSearchString通知searchStringChanged)
Q_属性(Qt::SortOrder SortOrder读取SortOrder写入设置SortOrder通知sortOrderChanged)
公众:
显式SortFilterProxyModel(QObject*parent=nullptr);
QString searchString()常量
{
返回搜索字符串;
}
Qt::SortOrder SortOrder()常量
{
返回-排序器;
}
void setSearchString(const QString和searchString);
无效设置排序顺序(常量Qt::排序器和排序器);
信号:
作废searchStringChanged(QString searchString);
void sortOrderChanged(Qt::SortOrder SortOrder);
受保护的:
bool lessThan(const QModelIndex&source_左,const QModelIndex&source_右)const;//自定义排序逻辑
bool filterAcceptsRow(int sourceRow,const QModelIndex&sourceParent)const;//自定义筛选器逻辑
私人:
QString_searchString;
Qt::SortOrder _SortOrder;
};
#endif//sortproxy模型
**************sortfilterproxymodel.cpp**************
#包括“sortfilterproxymodel.h”
SortFilterProxyModel::SortFilterProxyModel(QObject*父对象):
QSortFilterProxyModel(父级)
{
连接(此,&SortFilterProxyModel::searchStringChanged,此,&SortFilterProxyModel::invalidate)//
}
void SortFilterProxyModel::setSearchString(const QString和searchString)
{
if(_searchString==searchString)
返回;
_searchString=searchString;
发出searchStringChanged(searchString);//与invalidateFilter、inter连接