QTableWidget是Qt中的表格组件类。在窗体上放置一个QTableWidget组件后,可以在Property Editor里对其属性进行编辑,双击这个组件,可以打开一个编辑器,对其Colum、Row和Item进行编辑。一个QTableWidget的基本结构如图所示:
表格的第一行通常称为表头,用于设置每一列的标题, 第一列称为列表头,可以设置其标题,但一般使用缺省的标题(行号)。行表头和列表头一般不可编辑
除了行表头和列表头之外为表格的内容区,内容区是规则的网格状,每个网格被称为单元格且每个单元格都有行号和列号
在QTableWidget表格中,每个表格都是一个QTableWidgetItem对象,可以设置文字内容、字体、前景色和背景色、图标,也可以设置编辑和显示标记。每个单元格还可以存储一个QVariant数据,用以设置用户自定义数据
实例效果如下:
该实例将演示以下功能的实现:
实例的主窗体从QMainWindow继承而来,窗口中,左侧是一个GroupBox组件,所有的PushButton组件和CheckBox组件都在其中,并且采用栅格布局;右侧分别是一个QTableWidget组件和一个QPlainTextEdit组件,二者采用垂直布局,这是一个典型的三区分割的布局
在主窗体类中,MainWindow里自定义了一些变量和函数,用于后面的代码是实现,下面是在MainWindow的private部分的变量和函数:
private:
Ui::MainWindow *ui;
//自定义单元格Type的类型,在创建单元格的item时使用
enum CellType{ctName=1000, ctSex, ctBirth, ctNation, ctPartyM, ctScore};
//各字段在表格中的列号
enum FieldColNumP{colName=0, colSex, colBirth, colNation, colPartyM, colScore};
QLabel *labCellIndex; //状态栏上用以显示单元格的行号、列号
QLabel *labCellType; //状态栏上用以显示单元格的type
QLabel *labStudID; //状态栏上用以显示学号
//创建item
void createItemARow(int rowNo, QString Name, QString Sex, QDate brith,
QString Nation, bool isPM, int socore);
枚举类型CellType是用来表示单元格类型的,在创建单元格时使用
枚举类型FieldColNum用枚举常量表示格字段在表格中的列号
设置表头
界面上的"设置表头"按钮实现对表头的设置,其clicked()信号的槽函数代码如下:
void MainWindow::on_btn_SetHeader_clicked()
{
//设置表头
QTableWidgetItem *headerItem;
QStringList headerText;
headerText<<"姓名"<<"性别"<<"出生日期"<<"民族"<<"分数"<<"是否党员";
//ui->tableWidget->setHorizontalHeaderLabels(headerText);
ui->tableWidget->setColumnCount(headerText.count());
for (int i=0; itableWidget->columnCount(); i++) {
headerItem = new QTableWidgetItem(headerText.at(i));
QFont font = headerItem->font();
font.setBold(true); //设置字体加粗
font.setPointSize(12); //设置字体字号
headerItem->setTextColor(Qt::red); //设置颜色
headerItem->setFont(font);
ui->tableWidget->setHorizontalHeaderItem(i,headerItem);
}
}
行表头各列的文字标题由一个QStrnigList对象headerText初始化储存,如果只是设置行表头各列的标题,只需使用:
ui->tableWidget->setHorizontalHeaderLabels(headerText);
如果需要进行更加具体的设置,需要为行表头的每个单元创建一个QTableWidgetItem类型的变量,并进行相关设置
在一个表格中,不管是表头还是工作区,每个单元格都是一个QTableWidgetItem对象。QTableWidgetItem对象储存了单元格的所有内容,包括字标题、格式设置,已经关联的数据。
上面的程序中的for循环遍历headerText的每一行,用每一行的文字创建一个QTableWidgetItem对象headerItem,然后设置headerItem的字体大小,粗体,颜色,然后将headerItem赋给表头的某一列:
ui->tableWidget->setHorizontalHeaderItem(i,headerItem);
初始化列表数据
界面上的"初始化表格数据"按钮根据表格的行数,生成数据填充表格,并为每个单元格生成QTableWidgetItem对象,设置相应属性。下面是btn_IniTable的响应槽函数代码:
void MainWindow::on_btn_InitTable_clicked()
{
//初始化表格
QString strName,strSex;
bool isSingal = true;
QDate birth;
birth.setDate(1998,05,01);
ui->tableWidget->clearContents(); //清除工作区,但不清除表头
int Rows = ui->tableWidget->rowCount(); //数据区行数
for (int i=0; i
其中,QTableWidget::clearContents()函数清除表格工作区的数据,但不会清除表头;QTableWidget::rowCount()函数返回表格的行数
在for循环中为每一行生成需要显示的数据,然后调用自定义函数createItemsARow(),为表格一行的各个单元格生成QTableWidgetItem对象,其详细代码如下:
void MainWindow::createItemARow(int rowNo, QString Name, QString Sex,
QDate brith, QString Nation, bool isPM, int score)
{
//为一行表格创建item
QTableWidgetItem *item;
QString str;
uint StudID = 20190000; //学号基数
item = new QTableWidgetItem(Name,MainWindow::ctName);
StudID += rowNo; //学号=基数+行号
//姓名
item->setData(Qt::UserRole,QVariant(StudID));
ui->tableWidget->setItem(rowNo,MainWindow::colName,item);
QIcon icon;
if(Sex == "男")
icon.addFile("../images/男生.png");
else
icon.addFile("../images/女生.png");
item = new QTableWidgetItem(Sex,MainWindow::ctSex);
item->setIcon(icon);
item->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
ui->tableWidget->setItem(rowNo,MainWindow::colSex,item);
//出生日期
str = brith.toString("yyyy-MM-dd"); //日期转换为字符串
item = new QTableWidgetItem(str,MainWindow::ctBirth);
item->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);
ui->tableWidget->setItem(rowNo,MainWindow::colBirth,item);
//民族
item = new QTableWidgetItem(Nation,MainWindow::ctNation);
item->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);
ui->tableWidget->setItem(rowNo,MainWindow::colNation,item);
//是否党员
item = new QTableWidgetItem("党员",MainWindow::ctPartyM);
item->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);
if(isPM)
item->setCheckState(Qt::Checked);
else
item->setCheckState(Qt::Unchecked);
item->setBackgroundColor(Qt::yellow);
ui->tableWidget->setItem(rowNo,MainWindow::colPartyM,item);
//分数
str.setNum(score);
item = new QTableWidgetItem(str,MainWindow::ctScore);
item->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);
ui->tableWidget->setItem(rowNo,MainWindow::colScore,item);
}
该表格的每一行有5列,为每一个单元格都创建一个QTableWidgetItem类型的变量item,并做相应的设置
创建QTableWidgeItem使用的构造函数的原型为:
QTableWidgetItem::QTableWidgetItem(const QString &text, int type = Type)
其中,第一个参数作为单元格的显示文字,第二个参数作为节点的类型;例如创建"姓名"单元格对象时语句是:
item = new QTableWidgetItem(Name,MainWindow::ctName);
其中,MainWindow::ctName是定义枚举类型的一个常量值
"姓名"单元格还调用了setData()函数设置了一个自定义类型数据,储存的信息为学生ID
item->setData(Qt::UserRole,QVariant(StudID));
这个自定义数据是不显示在界面上的,但是与单元格相关联
QTableWidgetItem中有一些函数可以对单元格的属性进行设置,如下:
setTextAlignment(int alignment); //设置文字对齐方式
setBackground(const QBrush &brush); //设置单元格背景颜色
setForeground(const QBrush &brush); //设置单元格前景色
setIcon(const QIcon &icon); //设置单元格图标
setFont(const QFont &font); //设置字体
setCheckState(Qt::CheckState state); //设置单元格勾选状态
setFlages(Qt::ItemFlags flags); //设置单元格的属性标记
设置完相关属性之后,用QTableWidget的setItem函数将item设置为单元格的项:例如:
ui->tablewidget->setItem(rowNo,MainWindow::colName,item);
其中,MainWindow::colName是定义的枚举类型FiledColNum的一个常量值
当进行初始化之后,表格里面并没有显示学号,学号是"姓名"单元格的关联数据
获取单元格数据
当鼠标在单元格上单击单元格时,被选中的单元格是当前单元格。通过QTableWidget的currentColumn()和currentRow()可以获得当前单元格的列编号和行编号
当前单元格发生切换时,会发射currentCellChanged()信号和currentItemChanged()信号,两个信号的区别在于传递的参数不同
对currentCellChanged()信号编写槽函数,用于获取当前单元格的数据,以及当前行的学生的学号信息
在currentCellChanged()信号中,传递的参数为为当前单元格的行号和列号,通过这两个编号就能得到单元格的QTableWidget对象item
获得item之后,通过type()函数得到单元格的类型参数,这个类型就是创建单元格的QTableWidgetItem对象时传递的类型参数
再获取同一行的"姓名"单元格的项,用data()函数提取自定义数据学生ID
插入、删除、添加行
QTableWidget处理行操作的函数如下:
insertRow(int row):在行号为row的行前面添加一行,如果row等于或大于总行数,则在表格最后添加一行;insertRow()只是添加一个空行,不会为单元格创建QWidgetItem对象,需要手动创建
removeRow(int row):删除行号为row的行
下面是界面上"插入行"、"添加行"、"删除当前行"的响应槽函数。在调用插入之后,会调用createItemARow()函数为新创建的空行的各单元构造QTableWidgetItem对象
void MainWindow::on_btn_InsertItem_clicked()
{
//插入行
int curRow = ui->tableWidget->currentRow();
ui->tableWidget->insertRow(curRow); //插入空行
createItemARow(curRow,"新同学","男",QDate::fromString("1990-1-1","yyyy-M-d"),"汉族",true,70);
}
void MainWindow::on_btn_addItem_clicked()
{
//添加行
int curRow = ui->tableWidget->rowCount();
ui->tableWidget->insertRow(curRow);
createItemARow(curRow,"新同学","女",QDate::fromString("2000-1-1","yyyy-M-d"),"满族",false,70);
}
void MainWindow::on_btn_removeItem_clicked()
{
//删除行
int curRow = ui->tableWidget->currentRow();
ui->tableWidget->removeRow(curRow);
}
自动调整行高和列宽
QTableWIdget有几个函数自动调整表格的行高和列宽,分别如下:
resizeCloumnsToContents() //自动调整所有列的宽度,以适应其内容
resizeCloumnToContents(int column) //自动调整列号为column的列的宽度
resizeRowsToContents() //自动调整所有行的高度,以适应其内容
resizeRowToContents(int row) //自动调整行号为row的行的高度
界面中的调整高度和调整宽度的响应槽函数如下:
void MainWindow::on_btn_autoHight_clicked()
{
//自动调整高度
ui->tableWidget->resizeRowsToContents();
}
void MainWindow::on_btn_autoWidth_clicked()
{
//自动调整宽度
ui->tableWidget->resizeColumnsToContents();
}
读取表格数据
"读取文本"按钮演示了将表格中的数据区的内容全部读出的方法,它将每个单元格的文字读出,同一行的单元格的文字用空格隔开,作为文本的一行,然后将这些文本作为文本编辑器的一行内容,代码如下:
void MainWindow::on_btn_readTable_clicked()
{
//读取表格数据
QString str;
QTableWidgetItem *cellitem;
ui->plainTextEdit->clear();
for (int i=0;itableWidget->rowCount(); i++) {
str = QString::asprintf("第%d行:",i+1);
for (int j=0; jtableWidget->columnCount()-1; j++) {
cellitem = ui->tableWidget->item(i,j);
str = str+cellitem->text()+" "; //字符串的拼接
}
cellitem = ui->tableWidget->item(i,colPartyM); //最后一列
if(cellitem->checkState() == Qt::Checked)
str = str+"党员";
else {
str = str+"群众";
}
ui->plainTextEdit->appendPlainText(str);
}
}