有人可以给我一些想法,在QTableWidget上创建一个过滤机制(在Microsoft Excel中可用)吗?
每当我点击列名时,我希望标题过滤器机制自动激活该表。
我正在Windows上构建。
更新以下是我的部分实施。但是我需要帮助设置插槽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();
}
答案 0 :(得分:3)
我创建了一个继承自QHBoxLayout
的列跟踪布局。它不如将小部件嵌入到标题中那么好,但至少它给出了小部件绑定到各自表列的外观:
该项目在https://github.com/sashoalm/ColumnAlignedLayout的GitHub上托管。
您只需要columnalignedlayout.cpp和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
#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()));
然后在插槽中调用invalidate():
void MainWindow::invalidateAlignedLayout()
{
alignedLayout->invalidate();
}
答案 1 :(得分:1)
没有任何内置功能可以执行该特定功能。但你可以从QHeaderView派生自己的类,就像这个人做的那样:
http://lists.qt.nokia.com/pipermail/qt-interest/2009-August/011654.html
我尝试了它,它似乎成功地将小部件 - 一个文本框和一个组合框 - 放在相应的标题列下面。使用这种技术,如果你有一个长表并滚动,过滤器将保留在标题中。
(有一个先前的帖子,人们建议在代理数据模型中加入“假”行。这是一种非常可怕的方法,当您向下滚动数据时,过滤列也会滚动到顶部。 )
他的示例代码没有显示过滤。但是,您可以通过查看基本排序/过滤模型示例来查看该功能的模式:
http://doc.qt.nokia.com/latest/itemviews-basicsortfiltermodel.html
好消息是Qt足够灵活,可以处理这类事情。糟糕的(?)新闻是你在列标题中放置的那些小部件是如何填充的。除非您编写,否则不会进行任何扫描以查找唯一值并将其显示在组合框中。但是,使用固定列表填充将是微不足道的。