QTableWidget介绍
QTableWidget是Qt框架中的一个表格控件,用于显示二维表格数据。它是基于QTableView和QStandardItemModel的封装,提供了更简单的接口和功能。
QTableWidget主要具有以下特点:
-
二维数据表示:QTableWidget以行和列的组合形式呈现表格数据,每个格子称为一个单元格。可以通过指定行数和列数来创建一个空的表格,并动态添加、删除行列。
-
单元格编辑:QTableWidget可以直接在表格中进行单元格的编辑操作。可以通过设置单元格的编辑属性来控制哪些单元格可编辑,哪些单元格只读。
-
表头管理:QTableWidget支持自定义表头,在水平方向和垂直方向上可以设置不同的表头标题。默认情况下,QTableWidget会根据数据模型自动生成默认表头。
-
可选行选择模式:QTableWidget提供多种选择模式,可以选择一行或多行数据。可以通过设置选择行为和选择模式来实现不同的选择方式。
-
排序与排序指示器:QTableWidget支持按照某一列的数据进行升序或降序排序,并在表头显示排序指示器。
-
样式定制:可以通过设置样式表来改变QTableWidget的外观,包括单元格颜色、字体、边框等。
-
信号与槽机制:QTableWidget发出多种信号,如单元格点击、双击、选择变化等,可以通过连接这些信号与自定义的槽函数实现特定的响应。
总的来说,QTableWidget是一个功能强大且灵活的表格控件,适用于在界面中展示和编辑二维表格数据。无论是简单的数据展示还是复杂的数据交互,QTableWidget都能提供便捷且高效的解决方案。
QTableWidget接口
以下是QTableWidget常用的一些接口:
- setRowCount(int count):设置表格的行数。
- setColumnCount(int count):设置表格的列数。
- rowCount():返回表格的行数。
- columnCount():返回表格的列数。
- insertRow(int row):在指定的行插入一行。
- removeRow(int row):移除指定的行。
- insertColumn(int column):在指定的列插入一列。
- removeColumn(int column):移除指定的列。
- clear():清空表格的所有内容。
- setItem(int row, int column, QTableWidgetItem *item):在指定的单元格设置一个QTableWidgetItem对象。
- item(int row, int column):返回指定单元格的QTableWidgetItem对象。
- setHorizontalHeaderLabels(const QStringList &labels):设置水平方向的表头标签。
- setVerticalHeaderLabels(const QStringList &labels):设置垂直方向的表头标签。
- horizontalHeaderItem(int column):返回指定列的水平表头项。
- verticalHeaderItem(int row):返回指定行的垂直表头项。
- setEditTriggers(EditTriggers triggers):设置表格的编辑触发方式,如单击、双击等。
- setSelectionMode(SelectionMode mode):设置表格的选择模式,如单选、多选等。
- currentRow():返回当前选择的行号。
- currentColumn():返回当前选择的列号。
- selectedItems():返回当前选择的所有单元格的QTableWidgetItem对象列表。
- sortItems(int column, Qt::SortOrder order):按照指定列的数据对表格进行排序。
- setSortingEnabled(bool enable):设置是否启用排序功能。
- setStyleSheet(const QString &styleSheet):设置表格的样式表。
- setCellWidget(int row, int column, QWidget *widget):在指定的单元格设置一个自定义的QWidget部件。
- cellWidget(int row, int column):返回指定单元格中的自定义QWidget部件。
请注意,这只是QTableWidget的一部分接口,还有更多其他接口可以用于更高级的操作和定制化需求。
QTableWidget的性能问题
实际上,QTableWidget和QTableView都是Qt框架提供的用于显示表格数据的类,它们在不同的场景下可能具有不同的性能表现。一般情况下,QTableView比QTableWidget具有更好的性能,原因如下:
-
数据模型的选择:QTableWidget使用的是QTableWidgetItem作为数据模型,这是一种基于QTableWidget的数据结构。而QTableView使用的是QAbstractTableModel等更通用的数据模型。相对而言,QAbstractTableModel可以更好地支持大量数据和高速数据更新,因为它提供了更灵活的数据模型。
-
内部数据结构:QTableWidget内部使用了QTableWidgetItem来表示单元格数据,而QTableView使用了与数据模型相匹配的数据结构。QTableWidgetItem是一种较为简单的数据结构,无法提供高效的数据操作和访问。
-
重新绘制的开销:由于QTableWidget是基于QWidget的,每次进行重绘时,它需要重新绘制整个表格,而QTableView可以只绘制可见区域,从而减少了绘制的开销。
-
灵活性和扩展性:使用QTableView可以更方便地自定义和扩展,例如通过自定义数据模型、委托或代理来实现特殊的显示和交互需求。而QTableWidget的功能和外观相对固定,定制性较低。
请注意,这种性能差异通常是在处理大量数据或高频更新数据时才会明显体现出来。对于小型数据集和简单的界面需求,两者的性能差异可能并不明显。如果您需要处理大量数据或需要更高级的功能和性能优化,建议使用QTableView以获得更好的性能和灵活性
QTableWidget不支持设置代理模型
在QTableWidget中,没有内置的过滤和排序功能。不过,您可以通过编写自定义的代码实现这些功能。以下是一些思路:
-
过滤:可以通过迭代遍历QTableWidget中的数据行,并根据某些条件进行筛选,然后隐藏或删除不符合条件的行。例如,可以使用
item(row, column)
获取单元格对象,然后使用text()
获取文本值进行比较。 -
排序:可以使用QTableWidget的
sortItems()
函数对特定列的数据进行排序。您可以将此函数与自定义的排序算法结合使用,根据需要的排序顺序(升序或降序)进行调整。
需要注意的是,这些操作都需要手动实现,并且可能会涉及到大量的数据复制和重新排列,所以性能可能会受到一定的影响。如果对于过滤和排序有更高的性能要求,推荐使用QTableView和QSortFilterProxyModel来实现这些功能。
注意事项
在使用QTableWidget时,请注意以下几点:
-
数据操作:通过QTableWidget添加、删除和修改数据时,要确保操作的数据与表格的行列索引一致。特别是在使用
setItem()
函数设置单元格数据时,要注意指定正确的行列索引值。 -
行列数设置:在使用QTableWidget之前,需要设置表格的行数和列数。可以使用
setRowCount()
和setColumnCount()
函数进行设置,确保与实际数据的行列数一致。 -
单元格属性:可以使用
setItem()
函数设置单元格的数据,还可以使用item(row, column)
函数获取单元格对象,并对其进行属性设置,如文本颜色、背景色等。 -
选择模式:通过设置
setSelectionBehavior()
和setSelectionMode()
函数可以定义表格的选择性行为和模式。例如,可以设置为选择整行或整列,或者设置为多选或单选模式。 -
表头设置:可以使用
setHorizontalHeaderLabels()
和setVerticalHeaderLabels()
函数设置表格的水平和垂直表头文本。 -
事件处理:可以通过重写
keyPressEvent()
等函数来处理键盘事件,或者通过重写mousePressEvent()
等函数来处理鼠标事件。这些事件处理函数可以用于实现自定义的交互逻辑。 -
布局管理:将QTableWidget嵌入到布局管理器中,以便进行自适应布局和窗口调整。
-
性能考虑:如果处理大量数据或需要频繁更新表格,请考虑使用更高级的数据模型(如QAbstractTableModel)和优化策略,以提高性能。
请记住,在使用QTableWidget时要遵循所需数据的正确行列索引,并根据实际需求进行适当的设置和处理。通过合理使用QTableWidget的属性和函数,可以轻松创建和管理表格数据。
代码示例
显示表格数据的基本思路是:
-
创建一个QTableWidget对象,并设置表格的行数和列数。可以使用
setRowCount()
和setColumnCount()
函数进行设置。 -
使用
setItem(row, column, item)
函数将数据逐个添加到表格中。其中,row表示行索引,column表示列索引,item为QTableWidgetItem对象,用于设置单元格的数据和属性。 -
可以使用
setHorizontalHeaderLabels()
和setVerticalHeaderLabels()
函数设置表格的水平和垂直表头文本。 -
根据需要,可以通过调用
setEditTriggers()
函数来设置表格的编辑触发器。例如,可以禁止编辑、只允许单元格内编辑、或者只允许行或列编辑。 -
可以使用
setSelectionMode()
函数设置表格的选择模式,例如设置为单选、多选或扩展选择模式。 -
选择合适的布局管理器,将QTableWidget添加到布局中,以便根据窗口大小自动调整表格大小和布局。
-
最后,将QTableWidget添加到主窗口或其他适当的窗口部件中进行显示。
通过上述步骤,可以创建并显示带有数据的表格。根据需要,还可以使用其他相关的函数和属性对表格进行进一步的定制和操作。
missiondata.h
#ifndef MISSIONDATA_H
#define MISSIONDATA_H
#include <QObject>
#include <QMap>
struct MissionHeadInfo
{
quint32 missionFlag;//标识,16进制显示
QString missionCode; //代号
QString missionName; //名称
MissionHeadInfo()
{
missionFlag = 0x00;//标识,16进制显示
missionCode = ""; //代号
missionName = ""; //名称
}
};
class MissionData : public QObject
{
Q_OBJECT
public:
explicit MissionData(QObject *parent = nullptr);
static MissionData * getInstance()
{
static MissionData instance;
return &instance;
}
//获取所有的代号
QStringList getCodes();
//获取头信息
MissionHeadInfo getMissionHeadInfo(const QString &code, bool &isOK);
private:
QMap<QString, MissionHeadInfo> map_MissionHeadInfo;//头信息字典
void initMap();
signals:
public slots:
};
#endif // MISSIONDATA_H
missiondata.cpp
#include "missiondata.h"
MissionData::MissionData(QObject *parent) : QObject(parent)
{
initMap();
}
QStringList MissionData::getCodes()
{
return map_MissionHeadInfo.keys();
}
MissionHeadInfo MissionData::getMissionHeadInfo(const QString &code, bool &isOK)
{
if(map_MissionHeadInfo.contains(code))
{
isOK = true;
return map_MissionHeadInfo.value(code);
}
isOK = false;
return MissionHeadInfo();
}
void MissionData::initMap()
{
//创建15个目标信息
for(int j=0; j<3; j++)
{
for(int i=0; i<5; i++)
{
static int totalNum = 0;
totalNum++;
int num = i+1;
quint32 missionFlag = totalNum;//标识,16进制显示
QString missionCode = QString("%1%2_%3").arg(j).arg(j).arg(num); //代号
QString missionName = QString("第%1个目标").arg(totalNum); //名称
MissionHeadInfo info;
info.missionFlag = missionFlag;
info.missionCode = missionCode;
info.missionName = missionName;
map_MissionHeadInfo.insert(missionCode,info);
}
}
}
tablewidgetdialog.h
#ifndef TABLEWIDGETDIALOG_H
#define TABLEWIDGETDIALOG_H
#include <QDialog>
#include <QTableWidget>
#include <QSortFilterProxyModel>
namespace Ui {
class TableWidgetDialog;
}
class TableWidgetDialog : public QDialog
{
Q_OBJECT
public:
explicit TableWidgetDialog(QWidget *parent = 0);
~TableWidgetDialog();
private slots:
void onTableWidgetClicked(const QModelIndex &index);
private:
Ui::TableWidgetDialog *ui;
QTableWidget *tableWidget = nullptr;
QSortFilterProxyModel *proxyModel = nullptr;
void initTableWidget();
void updateMissionItem();
};
#endif // TABLEWIDGETDIALOG_H
tablewidgetdialog.cpp
#include "tablewidgetdialog.h"
#include "ui_tablewidgetdialog.h"
#include "missiondata.h"
#include <QDebug>
TableWidgetDialog::TableWidgetDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::TableWidgetDialog)
{
ui->setupUi(this);
this->setFixedSize(600,800);
MissionData::getInstance();//数据初始化
ui->widget->setFixedSize(600,700);
initTableWidget();
updateMissionItem();
}
TableWidgetDialog::~TableWidgetDialog()
{
delete ui;
}
void TableWidgetDialog::initTableWidget()
{
// 创建一个QTableWidget对象,并设置行数和列数
tableWidget = new QTableWidget(ui->widget);
tableWidget->setColumnCount(4);
tableWidget->setFixedSize(ui->widget->size());
tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);//设置单元格不可编辑
//设置水平表头的颜色
tableWidget->horizontalHeader()->setStyleSheet("QHeaderView::section{background:rgb(179,208,230);border:1px solid rgb(94,152,205)}" );
// 设置表头
tableWidget->setHorizontalHeaderLabels(QStringList() <<"序号"<< "标识" << "代号" << "名称");
tableWidget->verticalHeader()->setVisible(false);
connect(tableWidget, &QAbstractItemView::clicked, this, &TableWidgetDialog::onTableWidgetClicked);
}
void TableWidgetDialog::onTableWidgetClicked(const QModelIndex &index)
{
if (index.isValid()) {
int clickedRow = index.row();
QString res = QString("第%1行:").arg(clickedRow+1);
for(int i=0;i<4;++i)
{
QModelIndex filterModelIndex = tableWidget->model()->index(clickedRow, i);
QString str = tableWidget->model()->data(filterModelIndex).toString();
res += str;
res += "-";
}
qDebug()<<res;
}
}
void TableWidgetDialog::updateMissionItem()
{
MissionData *pMissionData = MissionData::getInstance();
QStringList codeList =pMissionData->getCodes();
// 初始化表格数据
int row = 0;
tableWidget->setRowCount(codeList.count());
for(int i = 0; i < tableWidget->rowCount(); ++i) {
bool isOK = false;
MissionHeadInfo info = pMissionData->getMissionHeadInfo(codeList.at(i),isOK);
QTableWidgetItem* itemNum = new QTableWidgetItem(QString::number(row+1)); // 序号
QTableWidgetItem* itemFlag = new QTableWidgetItem(QString::number(info.missionFlag, 16).toUpper()); // 目标标识
QTableWidgetItem* itemCode = new QTableWidgetItem(info.missionCode); // 目标代号
QTableWidgetItem* itemName = new QTableWidgetItem(info.missionName); // 目标名称
// 将单元格添加到表格中
tableWidget->setItem(row, 0, itemNum);
tableWidget->setItem(row, 1, itemFlag);
tableWidget->setItem(row, 2, itemCode);
tableWidget->setItem(row, 3, itemName);
row++;
}
}
运行结果:
依次点击每一行: