如何在QTableWidget上实现类似Excel的过滤机制?

任何人都可以给我一些想法,在QTableWidget上创build一个过滤机制(如Microsoft Excel中可用)?

每当我点击一个列的名称,我希望头过滤机制自动激活该表。

我在Windows上构build。


更新这里是我的部分实现。 但我需要帮助实施slot testanother(const QString &text)来显示表中的匹配数据并隐藏不匹配的数据。

 bool TableData::filterSlot() { int columnCount = this->tablewidget->columnCount(); int rowCount = this->tablewidget->rowCount(); QStringList filterList; QString temp_string; qDebug()<<"Count inside filter slot is"; qDebug()<<rowCount<<":"<<columnCount; for(int c = 0; c<columnCount;c++) { for(int r = 0; r<rowCount;r++) { temp_string = this->tablewidget->item(r,c)->text(); if(!filterList.contains(temp_string)) filterList << temp_string; } filterList << "None"; combo = new QComboBox(tablewidget); combo->addItems(filterList); combo->setCurrentIndex(filterList.count()-1); this->tablewidget->setCellWidget(0,c,combo); filterList.clear(); connect(combo,SIGNAL(activated(const QString &)), this,SLOT(testAnother(const QString &))); } return true; } void TableData::testAnother(const QString &text) { int c = sender()->objectName().toInt(); } 

我创build了一个从QHBoxLayoutinheritance的列跟踪布局。 它不如将小部件embedded到标题中,但至less它给出了小部件绑定到它们各自的表列的外观:

演示screencap

在这里输入图像说明

该项目在https://github.com/sashoalm/ColumnAlignedLayout上的GitHub上进行托pipe&#x3002;

您只需要columnalignedlayout.cpp和columnalignedlayout.h

既然他们足够小,我会直接粘贴他们。

columnalignedlayout.h

 #ifndef COLUMNALIGNEDLAYOUT_H #define COLUMNALIGNEDLAYOUT_H #include <QHBoxLayout> class QHeaderView; class ColumnAlignedLayout : public QHBoxLayout { Q_OBJECT public: ColumnAlignedLayout(); explicit ColumnAlignedLayout(QWidget *parent); void setTableColumnsToTrack(QHeaderView *view) { headerView = view; } signals: public slots: private: void setGeometry(const QRect &r); QHeaderView *headerView; }; #endif // COLUMNALIGNEDLAYOUT_H 

columnalignedlayout.cpp

 #include "columnalignedlayout.h" #include <QHeaderView> ColumnAlignedLayout::ColumnAlignedLayout() : QHBoxLayout() { } ColumnAlignedLayout::ColumnAlignedLayout(QWidget *parent) : QHBoxLayout(parent) { } void ColumnAlignedLayout::setGeometry(const QRect &r) { QHBoxLayout::setGeometry(r); Q_ASSERT_X(headerView, "layout", "no table columns to track"); if (!headerView) { return; } Q_ASSERT_X(headerView->count() == count(), "layout", "there must be as many items in the layout as there are columns in the table"); if (headerView->count() != count()) { return; } Q_ASSERT(parentWidget()); int widgetX = parentWidget()->mapToGlobal(QPoint(0, 0)).x(); int headerX = headerView->mapToGlobal(QPoint(0, 0)).x(); int delta = headerX - widgetX; for (int ii = 0; ii < headerView->count(); ++ii) { int pos = headerView->sectionViewportPosition(ii); int size = headerView->sectionSize(ii); auto item = itemAt(ii); auto r = item->geometry(); r.setLeft(pos + delta); r.setWidth(size); item->setGeometry(r); } } 

示例用法:

 alignedLayout = new ColumnAlignedLayout(); alignedLayout->addWidget(new QLineEdit(this)); alignedLayout->addWidget(new QLineEdit(this)); alignedLayout->addWidget(new QLineEdit(this)); alignedLayout->addWidget(new QLineEdit(this)); ui->widget->setLayout(alignedLayout); alignedLayout->setTableColumnsToTrack(ui->tableWidget->horizontalHeader()); alignedLayout->setParent(ui->widget); connect(ui->tableWidget->horizontalHeader(), SIGNAL(sectionResized(int,int,int)), SLOT(invalidateAlignedLayout())); connect(ui->tableWidget->horizontalScrollBar(), SIGNAL(valueChanged(int)), SLOT(invalidateAlignedLayout())); 

然后在slot中调用invalidate():

 void MainWindow::invalidateAlignedLayout() { alignedLayout->invalidate(); } 

没有什么内置的那个特殊的function。 但是你可以从QHeaderView派生你自己的类,就像这个人所做的一样:

http://lists.qt.nokia.com/pipermail/qt-interest/2009-August/011654.html

我试过了,它似乎成功地把小部件,一个文本框和一个combobox,在适当的标题列下面。 使用这种技术,如果你有一个长表和滚动,filter将保持与标题。

(之前有一个线程,人们build议在代理数据模型中放置一个“假”行,这是一个非常糟糕的方法,而filter列也会在滚动数据的时候滚动到顶部。

他的示例代码不显示它的过滤。 但是通过查看基本的sorting/过滤模型示例,您可以看到该function的模式:

http://doc.qt.nokia.com/latest/itemviews-basicsortfiltermodel.html

好消息是Qt足够灵活来处理这种事情。 糟糕的(?)消息是,如何填充列标题中的这些小部件取决于您。 除非您编写它,否则将不会有任何扫描来查找唯一值并将其显示在combobox中。 但是,填充固定列表将是微不足道的。