我有一张这样的桌子
在此表中,Abbreviation
和Meaning
是标题。当我们单击它时,应该安排项目。但是,当我单击该命令时,我需要的顺序是:
|Last Used or |Last Used
|--FBI |--PIG
|--PIG |--FBI
|Something |Something
|--ADIDAS |--TEAM
|--DIET |--DIET
|--TEAM |--ADIDAS
|Lorem Ipsum |Lorem Ipsum
|--CLASS |--PwC
|--PMS |--PMS
|--PwC |--CLASS
这意味着,我仅将项目布置在每个组(Last Used
,Something
和Lorem Ipsum
)的内部,应保持组的顺序。
这些是我的约会对象
CompleterSourceModel.h
#include <QStandardItemModel>
#include <CompleterData.h>
class CompleterSourceModel : public QStandardItemModel
{
public:
CompleterSourceModel( QObject *p_parent = nullptr );
Qt::ItemFlags flags( const QModelIndex &index ) const override;
void setCompleterData( const CompleterData &p_completerData );
private:
CompleterData m_completerData;
};
CompleterSourceModel.cpp
#include "CompleterSourceModel.h"
CompleterSourceModel::CompleterSourceModel( QObject *p_parent ) : QStandardItemModel( p_parent )
{
}
Qt::ItemFlags CompleterSourceModel::flags( const QModelIndex &p_index ) const
{
if ( !p_index.isValid() ) {
return Qt::NoItemFlags;
}
CompleterDataRow::Type type = m_completerData.data().at( p_index.row() ).type();
if ( type == CompleterDataRow::Type::Data || type == CompleterDataRow::Type::LastUsed ) {
return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
}
return Qt::NoItemFlags;
}
void CompleterSourceModel::setCompleterData( const CompleterData &p_completerData )
{
m_completerData = p_completerData;
setColumnCount( m_completerData.headers().size() + 1 );
setRowCount( m_completerData.data().size() );
for ( int col = 0; col <= m_completerData.headers().size(); col++ ) {
col < m_completerData.headers().size() ? setHeaderData( col, Qt::Horizontal, m_completerData.headers().at( col ) ) : setHeaderData( col, Qt::Horizontal, {} );
}
for ( int row = 0; row < m_completerData.data().size(); row++ ) {
for ( int col = 0; col <= m_completerData.headers().size(); col++ ) {
if ( m_completerData.data().at( row ).type() == CompleterDataRow::Type::Header || m_completerData.data().at( row ).type() == CompleterDataRow::Type::SecondHeader ) {
col == 0 ? setData( index( row, col ), m_completerData.data().at( row ).rowData().at( col ).first, Qt::EditRole ) : setData( index( row, col ), {}, Qt::EditRole );
}
else {
col == m_completerData.headers().size() ? setData( index( row, col ), {}, Qt::EditRole ) : setData( index( row, col ), m_completerData.data().at( row ).rowData().at( col ).first, Qt::EditRole );
}
setData( index( row, col ), QVariant( static_cast<int>( m_completerData.data().at( row ).type() ) ), Qt::UserRole );
}
}
}
CompleterData.h
#include <QList>
#include <QPair>
#include <QVariant>
#include <QVector>
class CompleterDataRow
{
public:
enum class Type
{
Header,
SecondHeader,
Data,
LastUsed
};
CompleterDataRow() = default;
CompleterDataRow( const CompleterDataRow::Type p_rowType, const
QList<QPair<QString, QVariant>> &p_rowData );
void setType( const CompleterDataRow::Type p_type );
CompleterDataRow::Type type() const;
QList<QPair<QString, QVariant>> rowData() const;
void setRowData( const QList<QPair<QString, QVariant>> &p_rowData );
private:
QList<QPair<QString, QVariant>> m_rowData;
Type m_type;
};
class CompleterData
{
public:
CompleterData() = default;
QVector<CompleterDataRow> data() const;
void setData( const QVector<CompleterDataRow> &p_data );
void addData( const CompleterDataRow &p_rowData );
void removeData( int p_row );
void setHeaders( const QStringList &p_headers );
void setTitle( const QString &p_label );
const QStringList &headers() const;
const QString &title() const;
private:
QVector<CompleterDataRow> m_completerData;
QString m_title;
QStringList m_headers;
};
CompleterData.cpp
#include "CompleterData.h"
CompleterDataRow::CompleterDataRow( const CompleterDataRow::Type p_rowType, const QList<QPair<QString, QVariant>> &p_rowData )
{
m_type = p_rowType;
m_rowData = p_rowData;
}
QList<QPair<QString, QVariant>> CompleterDataRow::rowData() const
{
return m_rowData;
}
void CompleterDataRow::setRowData( const QList<QPair<QString, QVariant>> &p_rowData )
{
m_rowData = p_rowData;
}
CompleterDataRow::Type CompleterDataRow::type() const
{
return m_type;
}
void CompleterDataRow::setType( const Type p_type )
{
m_type = p_type;
}
QVector<CompleterDataRow> CompleterData::data() const
{
return m_completerData;
}
void CompleterData::addData( const CompleterDataRow &p_rowData )
{
m_completerData.append( p_rowData );
}
void CompleterData::removeData( int p_row )
{
m_completerData.remove( p_row );
}
void CompleterData::setData( const QVector<CompleterDataRow> &p_data )
{
m_completerData = p_data;
}
void CompleterData::setTitle( const QString &p_title )
{
m_title = p_title;
}
const QString &CompleterData::title() const
{
return m_title;
}
void CompleterData::setHeaders( const QStringList &p_headers )
{
m_headers = p_headers;
}
const QStringList &CompleterData::headers() const
{
return m_headers;
}
MyComboBox.h
#include <QComboBox>
#include <QTreeView>
#include "CompleterData.h"
#include "CompleterSourceModel.h"
#include "CompleterProxyModel.h"
class MyComboBox : public QComboBox
{
public:
MyComboBox( QWidget *p_parent = nullptr );
CompleterData createTestData();
void setDataForCompleter(const CompleterData &p_data); // this function should be set in main.cpp in Qt Project so that problem can be reproduced
private:
QTreeView *m_view = nullptr;
CompleterSourceModel *m_sourceModel = nullptr;
CompleterProxyModel *m_proxyModel =nullptr;
};
MyComboBox.cpp
#include "MyComboBox.h"
MyComboBox::MyComboBox( QWidget *p_parent ) : QComboBox( p_parent )
{
setEditable( true );
m_view = new QTreeView();
m_sourceModel = new CompleterSourceModel( this );
m_proxyModel = new CompleterProxyModel( this );
m_proxyModel->setSourceModel(m_sourceModel);
setModel( m_proxyModel );
setView( m_view );
}
void MyComboBox::setDataForCompleter(const CompleterData &p_data)
{
m_sourceModel->setCompleterData( p_data );
}
CompleterData MyComboBox::createTestData()
{
CompleterData data;
data.addData( CompleterDataRow( CompleterDataRow::Type::Header, { { "Last Used", {} } } ) );
data.addData( CompleterDataRow( CompleterDataRow::Type::Data, { { "FBI", {} }, { "Female Body Inspector", {} } } ) );
data.addData( CompleterDataRow( CompleterDataRow::Type::Data, { { "PIG", {} }, { "Pretty Insensitive Guy", {} } } ) );
data.addData( CompleterDataRow( CompleterDataRow::Type::Header, { { "Something", {}} } ) );
data.addData( CompleterDataRow( CompleterDataRow::Type::LastUsed, { { "ADIDAS", {} }, {"All Day I Dream About Soccer", {} } } ) );
data.addData( CompleterDataRow( CompleterDataRow::Type::LastUsed, { { "DIET", {}}, {"Do I eat today?", {}} } ) );
data.addData( CompleterDataRow( CompleterDataRow::Type::Data, { { "TEAM", {} }, { "Together Everyone Achieves More", {} } } ) );
data.addData( CompleterDataRow( CompleterDataRow::Type::SecondHeader, { { "Lorem Ipsum", {} } } ) );
data.addData( CompleterDataRow( CompleterDataRow::Type::LastUsed, { { "CLASS", {}}, {"Come late and start sleeping", {}} } ) );
data.addData( CompleterDataRow( CompleterDataRow::Type::LastUsed, { { "PMS", {}}, {"Purchase More Shoes", {}} } ) );
data.addData( CompleterDataRow( CompleterDataRow::Type::LastUsed, { { "PwC", {}}, {"Partner want Cash", {}} } ) );
data.addData( CompleterDataRow( CompleterDataRow::Type::Header, { { "Some Countries", {} } } ) );
data.addData( CompleterDataRow( CompleterDataRow::Type::SecondHeader, { { "Some Cities", {} } } ) );
data.setTitle( "Proposal List" );
data.setHeaders( { "Abbreviation", "Meaning" } );
return data;
}
main.cpp
#include "mycombobox.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MyComboBox combo;
combo.setDataForCompleter(combo.createTestData());
combo.show();
return a.exec();
}
为了满足要求,我认为我应该使用Proxymodel。但是我的代理模型有问题,因此加载模型时我得到的结果是这样的(我还没有点击标题来对项目进行排序)
如您所见,Lorem Ipsum
被移到列表的末尾,开头的顺序是错误的。所以我认为我的代理模型有误。您能告诉我我的代理模型中的确切位置吗?或者也欢迎任何其他解决方案。
这是我的代理模型:
CompleterProxyModel.h
#include <QSortFilterProxyModel>
#include <CompleterData.h>
class CompleterProxyModel : public QSortFilterProxyModel
{
public:
CompleterProxyModel( QObject *p_parent = nullptr );
protected:
bool lessThan( const QModelIndex &p_left, const QModelIndex &p_right ) const override;
};
CompleterProxyModel.cpp
#include "CompleterProxyModel.h"
CompleterProxyModel::CompleterProxyModel( QObject *p_parent ) : QSortFilterProxyModel( p_parent )
{
}
bool CompleterProxyModel::lessThan( const QModelIndex &p_left, const QModelIndex &p_right ) const
{
CompleterDataRow::Type leftType = static_cast<CompleterDataRow::Type>( p_left.data( Qt::UserRole ).toInt() );
CompleterDataRow::Type rightType = static_cast<CompleterDataRow::Type>( p_right.data( Qt::UserRole ).toInt() );
if ( ( leftType == CompleterDataRow::Type::Data && rightType == CompleterDataRow::Type::Data ) ||
( leftType == CompleterDataRow::Type::LastUsed && rightType == CompleterDataRow::Type::LastUsed ) )
{
QString leftString = p_left.data( Qt::EditRole ).toString();
QString rightString = p_right.data( Qt::EditRole ).toString();
qDebug() << leftString << rightString << QString::localeAwareCompare( leftString, rightString );
return QString::localeAwareCompare( leftString, rightString ) < 0;
}
return false;
}
答案 0 :(得分:1)
对于排序代理,您有两个规则:
一个项目是一个类别。因此,这是一个没有父项的根项目,您必须对行号进行排序以保持原始顺序。
否则,它是一个子项,您可以按其值对其进行排序。
您的代理非常简单:如果某个项目有一个父项,则将其与行进行排序。否则,请使用原始的排序规则(或其他排序规则)。
唯一棘手的部分是顺序(升序或降序)。因此,您必须处理它(否则您的类别将被颠倒)。
例如:
class SortProxyModel: public QSortFilterProxyModel
{
public:
SortProxyModel(): QSortFilterProxyModel() {}
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override
{
if (!left.parent().isValid())
{
if (sortOrder() == Qt::DescendingOrder) // Don't care about the order
return left.row() > right.row();
return left.row() < right.row();
}
return QSortFilterProxyModel::lessThan(left, right);
}
};
测试:
QTreeView* view = new QTreeView();
QStandardItemModel* model = new QStandardItemModel();
QSortFilterProxyModel* proxy = new SortProxyModel();
proxy->setSourceModel(model);
model->setHorizontalHeaderLabels(QStringList() << "Col 1");
QStandardItem* item1 = new QStandardItem("Last Used");
item1->appendRows(QList<QStandardItem*>() << new QStandardItem("A") << new QStandardItem("C") << new QStandardItem("B"));
QStandardItem* item2 = new QStandardItem("Something");
item2->appendRows(QList<QStandardItem*>() << new QStandardItem("F") << new QStandardItem("E") << new QStandardItem("D"));
QStandardItem* item3 = new QStandardItem("Lorem");
item3->appendRows(QList<QStandardItem*>() << new QStandardItem("I") << new QStandardItem("G") << new QStandardItem("H"));
model->appendRow(item1);
model->appendRow(item2);
model->appendRow(item3);
view->setModel(proxy);
view->setSortingEnabled(true);
view->show();
答案 1 :(得分:0)
在这种情况下,我刚刚找到了解决方案。我认为应该在将数据导入模型时对其进行更新。因此,我将System.out.println(x.split(" \\+\\+ ")[0]);
和SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
String dateString = formatter.format(new Date(yourDateValue)));
放入函数beginResetModel()
中,现在可以使用了。
endResetModel()