前言
最近在研究表格时,找不到什么好的例子来研究, 索性模仿一下公司开发的软件里的表格案例,做的一个小项目。
效果:
其中包括功能:
查找按钮:查找Reference列,符合条件的将其显示出来;不符合条件将其隐藏;
取消按钮:清空输入框文本,显示所有表格项;
插入行按钮:在选中行的下方进行插入一行;
删除行按钮:将选中的表格项进行删除;
首行插入按钮:在首行插入一行记录;
右键菜单跳过点:在SK项打勾✔;
右键菜单取消跳过点:取消行SK项打勾✔。
ui界面
很简单的一个界面,一个lineEdit,五个QPushButton,一个QTableWidget。
撸代码
知识点汇总
设置行数ui.tableWidget->setRowCount(5);
设置列数ui.tableWidget->setColumnCount(16);
设置隔行变色ui.tableWidget->setAlternatingRowColors(true);
设置选择模式ui.tableWidget->setSelectionBehavior(QAbstractItemView::SelectItems);
QAbstractItemView::SelectItems 选中一个单元格
QAbstractItemView::SelectRows 选中一行
QAbstractItemView::SelectColumns 选中一列
// 使用此方法也可以设置,更多参数查看qt帮助文档ui.tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
设置列表头
- 初始化列表头
QTableWidgetItem *headItem = new QTableWidgetItem;
- 获取表头字体并设置字体
// 获取表头原有字体QFont font = headItem->font();
font.setBold(true);
// 设置粗体font.setPointSize(10);
// 设置字体大小headItem->setFont(font);
// 设置字体 - 设置列宽与设置行高
ui.tableWidget->setColumnWidth(5, 50);
ui.tableWidget->setRowHeight(5, 30);
- 设置列表头文本
headItem->setText("字符串");
- 设置列表头
ui.tableWidget->setHorizontalHeaderItem(5, headItem);
设置列表头与行行头不可点击ui.tableWidget->horizontalHeader()->setSectionsClickable(false);
horizontalHeader()->setSectionsClickable(false); //水平方向的头不可点击
verticalHeader()->setSectionsClickable(false); //垂直方向的头不可点击
设置固定列宽ui.tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);
设置固定行高ui.tableWidget->verticalHeader()->setSectionResizeMode(QHeaderView::Fixed);
统一设置表头文本,参数是QStringList类型ui.tableWidget->setHorizontalHeaderLabels(*this->headText);
隐藏列表头ui.tableWidget->verticalHeader()->setVisible(false);
隐藏行表头ui.tableWidget->horizontalHeader()->setVisible(false);
设置行表头背景颜色样式为浅黄色ui.tableWidget->horizontalHeader()->setStyleSheet("QHeaderView::section{background:#ffff9b;}");
设置列表头背景颜色样式为浅蓝色ui.tableWidget->verticalHeader()->setStyleSheet("QHeaderView::section{background:#a7fffa;}");
设置左上角两个表头相交的区域的颜色样式为浅灰色ui.tableWidget->setStyleSheet("QTableCornerButton::section{background:#c2c2c2;}");
打开ps,选择自己喜欢的颜色,复制颜色编号替换即可。
设置左上角航行于列交汇处的按钮
- 获取到左上角行和列交汇处的按钮对象
QAbstractButton* btn = findChild<QAbstractButton*>();
- 连接信号与槽
链接后,就可以在槽函数中执行自己项目需要的操作。
connect(btn, &QAbstractButton::clicked,
[=]() {
// 槽函数中执行项目需要的操作
});
设置表格全选ui.tableWidget->selectAll();
获取的所有选中的单元格QList<QTableWidgetItem *> selectedList = ui.tableWidget->selectedItems();
取消选中所有选中的单元格ui.tableWidget->clearSelection();
获取单元格的选中状态ui.tableWidget->item(row, column)->isSelected();
获取选中的最后一行的行号row = ui.tableWidget->currentRow();
设置焦点对准某个单元格ui.tableWidget->setCurrentItem(item);
设置单元格选中ui.tableWidget->setItemSelected(item, true);
获取表格中的所有行int rowCount = ui.tableWidget->rowCount();
获取表格中的所有列int columnCount = ui.tableWidget->columnCount();
获取单元格的行号int row = ui.tableWidget->item(row, column)->row();
获取单元格的列号int column = ui.tableWidget->item(row, column)->column();
获取某个单元格QTableWidgetItem *item = ui.tableWidget->item(row, column);
获取某个单元格的文本ui.tableWidget->item(row, column)->text();
隐藏当前行ui.tableWidget->hideRow(row);
显示当前行ui.tableWidget->showRow(row);
插入一行ui.tableWidget->insertRow(row);
删除一行ui.tableWidget->removeRow(row);
注意:删除一行之后,后面的所有行都会往前挪,替换掉被删除行的位置
设置行高ui.tableWidget->setRowHeight(row, 50);
为单元格分配内存ui.tableWidget->setItem(row, column, new QTableWidgetItem("单元格文本"));
单元格设置复选框ui.tableWidget->item(row, column)->setCheckState(Qt::CheckState::Unchecked);
单元格添加控件ui.tableWidget->setCellWidget(row, column, Widget);
控件居中
仅供参考,使用布局进行居中,然后将布局添加到Widget里,最后将Widget添加到单元格中。
注意:此种方式居中的控件,本人不知道如何获得控件的对象!
QCheckBox * checkBox[] = { new QCheckBox, new QCheckBox, new QCheckBox };
int column[] { COLUMN_HEAD_INDEX::CS, COLUMN_HEAD_INDEX::SK, COLUMN_HEAD_INDEX::FID };
for (int i = 0; i < sizeof(column) / sizeof(column[0]); i++) {
QWidget *widget = new QWidget;
QHBoxLayout *hLayout = new QHBoxLayout();
hLayout->addWidget(checkBox[i]);
hLayout->setMargin(0);
// 设置水平居中
hLayout->setAlignment(widget, Qt::AlignCenter);
// 设置部件周围的左、上、右、下边距
hLayout->setContentsMargins(10, 0, 10, 0);
// 添加布局
widget->setLayout(hLayout);
// 添加单元格
ui.tableWidget->setCellWidget(row, column[i], widget);
//QCheckBox *box = qobject_cast<QCheckBox *>(ui.tableWidget->cellWidget(row, column[i]));
//box->setCheckState(Qt::CheckState::Checked);
//QHBoxLayout *hbLayout = qobject_cast<QHBoxLayout *>(ui.tableWidget->cellWidget(row, column[i]));
//qobject_cast<QCheckBox *>(hbLayout->widget())->setCheckState(Qt::CheckState::Checked);
}
返回在给定行和列的单元格中显示的小部件ui.tableWidget->cellWidget(row, column);
设置单元格文本居中ui.tableWidget->item(row, column)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
设置滚动条
- 获取垂直滚动条对象
QScrollBar *scareen = ui.tableWidget->verticalScrollBar();
- 获取水平滚动条对象
ui.tableWidget->horizontalScrollBar();
- 设置滚动条位置为最上方
scareen->setValue(scareen->minimum());
- 设置滚动条位置为最下方
scareen->setValue(scareen->maximum());
对容器中的数据进行去重
// 存储被选中的所有行
QVector<int> selectedRows;
// 进行排序
std::sort(selectedRows.begin(), selectedRows.end());
// 去除容器内重复元素
auto it = std::unique(selectedRows.begin(), selectedRows.end());
selectedRows.erase(it, selectedRows.end());
鼠标旋停提示当前单元格内容
// 鼠标追踪
ui.tabWidget->setMouseTracking(true);
// 鼠标旋停提示当前单元格内容
connect(ui.tabWidget, &QTableWidget::entered,
[=](QModelIndex index) {
QToolTip::showText(QCursor::pos(), index.data().toString());
});
右键菜单功能
实例化菜单对象this->menu = new QMenu(this);
定义菜单子项QAction *addRowAction = new QAction("插入行");
返回一个分隔符QAction *separator = this->menu->addSeparator();
将QAction项添加到菜单中this->menu->addAction(addRowAction);
this->menu->addAction(separator);
添加子菜单QMenu *menu1 = new QMenu("填充元件");
this->menu->addMenu(menu1);
鼠标单击菜单子项关联信号与槽connect(addRowAction, SIGNAL(triggered()), this, SLOT(on_addRowBtn_clicked()));
最后添加上鼠标右键事件函数即可
// 右键显示菜单事件
void contextMenuEvent(QContextMenuEvent * event);
// 鼠标右键显示菜单事件
void QTableWidgets::contextMenuEvent(QContextMenuEvent * event) {
this->menu->normalGeometry();
// 菜单出现的位置为当前鼠标的位置
this->menu->exec(QCursor::pos());
}
代码
有详细注释,对照着看应该可以看懂!
可将代码直接拷贝下来运行。
.h文件
#pragma once
#include <QtWidgets/QWidget>
#include "ui_QTableWidgets.h"
#include <QMenu>
#include <QVector>
#include <QCheckBox>
enum COLUMN_HEAD_INDEX {
No = 0,
Reference = 1,
X = 2,
Y = 3,
Z = 4,
R = 5,
Part = 6,
Feeder = 7,
Nozzle = 8,
HD = 9,
CS = 10,
CY = 11,
SK = 12,
AR = 13,
FID = 14,
BL = 15,
COLUMN = 16
};
class QTableWidgets : public QWidget
{
Q_OBJECT
public:
QTableWidgets(QWidget *parent = Q_NULLPTR);
private:
// 初始化表头文本链表
void initHeadText();
// 初始化菜单栏
void initMenu();
// 查询显示行
void SelectDataRow();
// 检查是否选中一整行
bool checkedSelectedRows();
// 右键显示菜单事件
void contextMenuEvent(QContextMenuEvent * event);
// 插入行与首行插入
void insertRow(bool flag);
private slots:
void on_findBtn_clicked();
void on_cancleBtn_clicked();
void on_addRowBtn_clicked();
void on_removeRowBtn_clicked();
void on_topRowAddBtn_clicked();
void skipPoints(); // 跳过点
void cancleSkipPoints(); // 取消跳过点
private:
Ui::QTableWidgetsClass ui;
// 头文本
QStringList *headText;
// 第一列No.
int No;
// 右键菜单
QMenu *menu;
QStringList partList;
QList<QAction *> partAction;
};
.cpp文件
#include "QTableWidgets.h"
#include <QComboBox>
#include <QCheckBox>
#include <iostream>
#include <QMessageBox>
#include <QDebug>
#include <QAction>
#include <QScrollBar>
#define HEAD_HEIGHT 30
#define HEAD_COUNT 16
#pragma execution_character_set("utf-8") // qt支持显示中文
/* QObjectUserData */
//class myQCheckBoxData :public QObjectUserData {
//public:
// myQCheckBoxData(QCheckBox *checkBox = nullptr) {
// this->checkBox = checkBox;
// }
//
// QCheckBox * getCheckBox() {
// return this->checkBox;
// }
//private:
// QCheckBox *checkBox;
//};
//
//static int index = 0;
//this->checkBox1 = new QCheckBox;
//this->checkBox2 = new QCheckBox;
//this->checkBox3 = new QCheckBox;
// 将对象内存存储
//this->checkBox->setUserData(index++, new myQCheckBoxData(this->checkBox1));
//this->checkBox->setUserData(index++, new myQCheckBoxData(this->checkBox2));
//this->checkBox->setUserData(index++, new myQCheckBoxData(this->checkBox3));
//
//
// 根据索引获取存储中对应的值
//QObjectUserData *cbox = this->checkBox->userData(row * 3);
// 将其转换类型
//myQCheckBoxData *myCheck = (myQCheckBoxData *)dynamic_cast<myQCheckBoxData *>(cbox);
//if (myCheck) {
// 获取对应的值
// QCheckBox * box = myCheck->getCheckBox();
// box->setCheckState(Qt::CheckState::Checked);
//}
QTableWidgets::QTableWidgets(QWidget *parent)
: QWidget(parent) {
ui.setupUi(this);
this->partList << " " << "0805" << "0603" << "0402";
this->No = 1;
// 单元格的宽度
int headWidth[HEAD_COUNT] = { 40, 100, 80, 80, 80, 80, 100, 120, 100, 40, 40, 40, 40, 40, 40, 40 };
// 搜索框显示提示文本
ui.inputEdit->setPlaceholderText("Search...");
this->setFixedSize(850, 555);
initHeadText();
initMenu();
// 设置行数
//ui.tableWidget->setRowCount(1024);
// 设置列数
ui.tableWidget->setColumnCount(HEAD_COUNT);
// 设置隔行变色
ui.tableWidget->setAlternatingRowColors(true);
// 设置选择模式
ui.tableWidget->setSelectionBehavior(QAbstractItemView::SelectItems);
/*QAbstractItemView::SelectItems 选中一个单元格
QAbstractItemView::SelectRows 选中一行
QAbstractItemView::SelectColumns 选中一列*/
// 使用此方法也可以设置,更多参数查看qt帮助文档
//ui.tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
// 根据列数设置表头
for (int i = 0; i < ui.tableWidget->columnCount(); i++) {
QTableWidgetItem *headItem = new QTableWidgetItem;
// 获取表头原有字体
QFont font = headItem->font();
font.setBold(true); // 设置粗体
font.setPointSize(10); // 设置字体大小
headItem->setFont(font); // 设置字体
// 设置列宽
ui.tableWidget->setColumnWidth(i, headWidth[i]);
// 设置行高
ui.tableWidget->setRowHeight(i, HEAD_HEIGHT);
// 设置表头文本
headItem->setText(this->headText->at(i));
// 设置表头
ui.tableWidget->setHorizontalHeaderItem(i, headItem);
}
//horizontalHeader()->setSectionsClickable(false); //水平方向的头不可点击
//verticalHeader()->setSectionsClickable(false); //垂直方向的头不可点击
ui.tableWidget->horizontalHeader()->setSectionsClickable(false);
// 设置固定列宽
//ui.tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);
// 设置固定行高
ui.tableWidget->verticalHeader()->setSectionResizeMode(QHeaderView::Fixed);
// 统一设置表头文本,参数是QStringList类型
//ui.tableWidget->setHorizontalHeaderLabels(*this->headText);
// 隐藏列表头
//ui.tableWidget->verticalHeader()->setVisible(false);
// 隐藏行表头
//ui.tableWidget->horizontalHeader()->setVisible(false);
// 设置行表头背景颜色样式为浅黄色
ui.tableWidget->horizontalHeader()->setStyleSheet("QHeaderView::section{background:#ffff9b;}");
// 设置列表头背景颜色样式为浅蓝色
ui.tableWidget->verticalHeader()->setStyleSheet("QHeaderView::section{background:#a7fffa;}");
// 设置左上角两个表头相交的区域的颜色样式为浅灰色
ui.tableWidget->setStyleSheet("QTableCornerButton::section{background:#c2c2c2;}");
// 获取到左上角行和列交汇处的按钮对象
QAbstractButton* btn = findChild<QAbstractButton*>();
// 设置表格全选
connect(btn, &QAbstractButton::clicked,
[=]() {
QList<QTableWidgetItem *> selectedList = ui.tableWidget->selectedItems(); // 获取的所有选中的单元格
// 设置焦点为最后一行的第一个单元格,但是不起作用。反而使焦点对准第0行的上一行
ui.tableWidget->setCurrentItem(ui.tableWidget->item(ui.tableWidget->rowCount(), 0));
// 设置表格全选
ui.tableWidget->selectAll();
// 设置单元格选中
//ui.tableWidget->setItemSelected(item, true);
});
for (int i = 0; i < 30; i++) {
on_addRowBtn_clicked();
}
}
// 初始化表头文本链表
void QTableWidgets::initHeadText() {
headText = new QStringList;
headText->append(QString("No."));
headText->append(QString("Reference"));
headText->append(QString("X"));
headText->append(QString("Y"));
headText->append(QString("Z"));
headText->append(QString("R"));
headText->append(QString("Part"));
headText->append(QString("Feeder"));
headText->append(QString("Nozzle"));
headText->append(QString("HD"));
headText->append(QString("CS"));
headText->append(QString("CY"));
headText->append(QString("SK"));
headText->append(QString("AR"));
headText->append(QString("FID"));
headText->append(QString("BL"));
}
// 初始化菜单栏
void QTableWidgets::initMenu() {
// 实例化菜单对象
this->menu = new QMenu(this);
// 定义菜单子项
QAction *addRowAction = new QAction("插入行");
QAction *removeRowAction = new QAction("删除行");
QAction *skipPointsAction = new QAction("跳过点");
QAction *cancleSkipPointsAction = new QAction("取消跳过点");
QAction *skipJointBoardAction = new QAction("跳过拼版");
QAction *fillElementAction = new QAction("填充元件");
QAction *separator = this->menu->addSeparator(); // 返回一个分隔符
// 将QAction项添加到菜单中
this->menu->addAction(addRowAction);
this->menu->addAction(removeRowAction);
this->menu->addAction(skipPointsAction);
this->menu->addAction(cancleSkipPointsAction);
this->menu->addAction(separator);
this->menu->addAction(skipJointBoardAction);
//this->menu->addAction(fillElementAction);
QMenu *menu1 = new QMenu("填充元件");
// 实例化子菜单对象,并将其存入链表中
for each (QString part in this->partList) {
this->partAction.append(new QAction(part));
}
// 将子菜单对象添加到子菜单中
for (int i = 0; i < this->partList.count(); i++) {
menu1->addAction(this->partAction.at(i));
}
// 子菜单添加到菜单中
this->menu->addMenu(menu1);
// 鼠标单击菜单子项关联信号与槽
connect(addRowAction, SIGNAL(triggered()), this, SLOT(on_addRowBtn_clicked()));
connect(removeRowAction, SIGNAL(triggered()), this, SLOT(on_removeRowBtn_clicked()));
connect(skipPointsAction, SIGNAL(triggered()), this, SLOT(skipPoints()));
connect(cancleSkipPointsAction, SIGNAL(triggered()), this, SLOT(cancleSkipPoints()));
}
// 鼠标右键显示菜单事件
void QTableWidgets::contextMenuEvent(QContextMenuEvent * event) {
if (!checkedSelectedRows()) {
//QMessageBox::information(this, "提示", "请选中一整行!");
return;
}
this->menu->normalGeometry();
// 菜单出现的位置为当前鼠标的位置
this->menu->exec(QCursor::pos());
}
// 查询按钮
void QTableWidgets::on_findBtn_clicked() {
SelectDataRow();
}
// 取消按钮
void QTableWidgets::on_cancleBtn_clicked() {
// 将输入框文本置空
ui.inputEdit->setText("");
// 显示所有行
int row = ui.tableWidget->rowCount();
for (int i = 0; i < row; i++) {
ui.tableWidget->showRow(i);
}
}
// 插入行按钮
void QTableWidgets::on_addRowBtn_clicked() {
insertRow(true);
}
// 删除行按钮
void QTableWidgets::on_removeRowBtn_clicked() {
if (!checkedSelectedRows()) {
QMessageBox::information(this, "提示", "请选中一整行!");
return;
}
/* 删除多行 */
// 存储选中行中的第一个单元格
QList<QTableWidgetItem *> rowItem;
// 获得所有选中的单元格的行,去掉重复的行
QList<QTableWidgetItem *> selectedList = ui.tableWidget->selectedItems(); // 获取的所有选中的单元格
// 提高效率 与 提示
if (selectedList.count() == 0) return;
if (QMessageBox::warning(this, "警告", "是否删除选择行?", QMessageBox::Button::Yes | QMessageBox::Button::No) == QMessageBox::Button::No) {
return;
}
// 将每行的第一个单元格存储;每次循环完后加上16,索引就指向了下一行的第一个单元格位置
for (int row = 0; row < selectedList.count(); row += HEAD_COUNT) {
rowItem.append(selectedList.at(row)); // 将每行的第一个单元格存储
}
// 遍历所有选中行的第一项
for each (QTableWidgetItem *item in rowItem) {
// 获取该项对应的行
int row = item->row();
// 遍历固定的所有列,释放该行每个单元格的同时,释放单元格里的控件
for (int column = 0; column < HEAD_COUNT; column++) {
if (column == COLUMN_HEAD_INDEX::Part || column == COLUMN_HEAD_INDEX::Feeder || column == COLUMN_HEAD_INDEX::Nozzle || column == COLUMN_HEAD_INDEX::HD) {
// 获取到单元格中的控件对象
//QComboBox *box = qobject_cast<QComboBox *>(ui.tableWidget->cellWidget(row, column));
QComboBox *box = (QComboBox *)dynamic_cast<QComboBox *>(ui.tableWidget->cellWidget(row, column));
delete box; // 释放
}
// 释放单元格内存
delete ui.tableWidget->item(row, column);
}
// 删除行
ui.tableWidget->removeRow(row);
// 注意:删除一行之后,后面的所有行都会往前挪,替换掉被删除行的位置
}
// 排序No.列
for (int row = 0; row < ui.tableWidget->rowCount(); row++) {
ui.tableWidget->item(row, 0)->setText(QString("%1").arg(row + 1));
}
// 取消所有选中
ui.tableWidget->clearSelection();
// No.编号赋值总行号加一(插入数据连续)
this->No = ui.tableWidget->rowCount() + 1;
}
// 首行插入
void QTableWidgets::on_topRowAddBtn_clicked() {
insertRow(false);
}
// 查找显示行
void QTableWidgets::SelectDataRow() {
// 获取输入框中的文本
QString str = ui.inputEdit->text();
// 为空则显示所有行
if (str.isEmpty()) {
int row = ui.tableWidget->rowCount();
for (int i = 0; i < row; i++) {
ui.tableWidget->showRow(i);
}
return;
}
int rowCount = ui.tableWidget->rowCount();
//int columnCount = ui.tableWidget->columnCount();
for (int row = 0; row < rowCount; row++) {
QString rowData = "";
获得一行当中的所有文本
//for (int column = 0; column < columnCount; column++) {
// if (ui.tableWidget->item(row, column)) {
// rowData += ui.tableWidget->item(row, column)->text();
// }
//}
// 获得Reference单元格的文本
rowData = ui.tableWidget->item(row, COLUMN_HEAD_INDEX::Reference)->text();
if (rowData.isEmpty()) {
// 隐藏当前行
ui.tableWidget->hideRow(row);
} else {
// 当前行的文本是否与输入框中的文本相等
if (rowData.contains(str)) {
// 显示当前行
ui.tableWidget->showRow(row);
} else {
// 隐藏当前行
ui.tableWidget->hideRow(row);
}
}
}
}
// 检查是否选中一整行
bool QTableWidgets::checkedSelectedRows() {
// 获取所有选中的单元格
QList<QTableWidgetItem *> widgetItems = ui.tableWidget->selectedItems();
// 存储被选中的所有行
QVector<int> selectedRows;
// 获得所有选中单元格的行
for each (QTableWidgetItem *item in widgetItems) {
selectedRows.append(item->row());
}
// 进行排序
std::sort(selectedRows.begin(), selectedRows.end());
// 去除容器内重复元素
auto it = std::unique(selectedRows.begin(), selectedRows.end());
selectedRows.erase(it, selectedRows.end());
// 遍历所有行的单元格,存在有一个单元格没有被选中,则返回false
bool selectedFlag = true;
for (int row = 0; row < selectedRows.count(); row++) {
for (int column = 0; column < ui.tableWidget->columnCount(); column++) {
// 检查单元格有没有被选中
if (ui.tableWidget->item(selectedRows.at(row), column)->isSelected() == false) {
selectedFlag = false;
break;
}
}
// 为false,直接返回结果
if (selectedFlag == false) return selectedFlag;
}
/* 此处为良好BUG :当用于没有选中任何单元格,也会返回true,是为了默认在行末尾连续插入行 */
return selectedFlag;
}
// 插入行与首行插入
void QTableWidgets::insertRow(bool flag) {
int row = 0; // 所选中的行号
if (!checkedSelectedRows()) {
QMessageBox::information(this, "提示", "请选中一整行!");
return;
}
// 真,插入按钮被点击;假首行插入
if (flag) {
QList<QTableWidgetItem *> selectedList = ui.tableWidget->selectedItems(); // 获取所有选中的单元格
// 为真,没有选中单元格
if (selectedList.isEmpty()) {
// 行号默认赋值行尾
row = ui.tableWidget->rowCount();
} else {
// 获取选中的最后一行的行号 + 1
row = ui.tableWidget->currentRow() + 1;
// 取消选中所有选中的单元格
ui.tableWidget->clearSelection();
}
}
// 插入一行
ui.tableWidget->insertRow(row);
// 设置行高
ui.tableWidget->setRowHeight(row, HEAD_HEIGHT);
// 为每个单元格分配内存
ui.tableWidget->setItem(row, COLUMN_HEAD_INDEX::No, new QTableWidgetItem(QString("%1").arg(No)));
ui.tableWidget->setItem(row, COLUMN_HEAD_INDEX::Reference, new QTableWidgetItem(QString("%1").arg(No++)));
ui.tableWidget->setItem(row, COLUMN_HEAD_INDEX::X, new QTableWidgetItem("0.000"));
ui.tableWidget->setItem(row, COLUMN_HEAD_INDEX::Y, new QTableWidgetItem("0.000"));
ui.tableWidget->setItem(row, COLUMN_HEAD_INDEX::Z, new QTableWidgetItem("0.000"));
ui.tableWidget->setItem(row, COLUMN_HEAD_INDEX::R, new QTableWidgetItem("0.000"));
ui.tableWidget->setItem(row, COLUMN_HEAD_INDEX::Part, new QTableWidgetItem);
ui.tableWidget->setItem(row, COLUMN_HEAD_INDEX::Feeder, new QTableWidgetItem);
ui.tableWidget->setItem(row, COLUMN_HEAD_INDEX::Nozzle, new QTableWidgetItem);
ui.tableWidget->setItem(row, COLUMN_HEAD_INDEX::HD, new QTableWidgetItem);
ui.tableWidget->setItem(row, COLUMN_HEAD_INDEX::CS, new QTableWidgetItem);
ui.tableWidget->setItem(row, COLUMN_HEAD_INDEX::CY, new QTableWidgetItem("1"));
ui.tableWidget->setItem(row, COLUMN_HEAD_INDEX::SK, new QTableWidgetItem);
ui.tableWidget->setItem(row, COLUMN_HEAD_INDEX::AR, new QTableWidgetItem("1"));
ui.tableWidget->setItem(row, COLUMN_HEAD_INDEX::FID, new QTableWidgetItem);
ui.tableWidget->setItem(row, COLUMN_HEAD_INDEX::BL, new QTableWidgetItem("0"));
// 单元格设置复选框
ui.tableWidget->item(row, COLUMN_HEAD_INDEX::CS)->setCheckState(Qt::CheckState::Unchecked);
ui.tableWidget->item(row, COLUMN_HEAD_INDEX::SK)->setCheckState(Qt::CheckState::Unchecked);
ui.tableWidget->item(row, COLUMN_HEAD_INDEX::FID)->setCheckState(Qt::CheckState::Unchecked);
/* 控件居中 */
//QCheckBox * checkBox[] = { new QCheckBox, new QCheckBox, new QCheckBox };
//
//int column[] { COLUMN_HEAD_INDEX::CS, COLUMN_HEAD_INDEX::SK, COLUMN_HEAD_INDEX::FID };
//for (int i = 0; i < sizeof(column) / sizeof(column[0]); i++) {
// QWidget *widget = new QWidget;
// QHBoxLayout *hLayout = new QHBoxLayout();
// hLayout->addWidget(checkBox[i]);
//
// hLayout->setMargin(0);
// // 设置水平居中
// hLayout->setAlignment(widget, Qt::AlignCenter);
// // 设置部件周围的左、上、右、下边距
// hLayout->setContentsMargins(10, 0, 10, 0);
// // 添加布局
// widget->setLayout(hLayout);
// // 添加单元格
// ui.tableWidget->setCellWidget(row, column[i], widget);
//
// //QCheckBox *box = qobject_cast<QCheckBox *>(ui.tableWidget->cellWidget(row, column[i]));
// //box->setCheckState(Qt::CheckState::Checked);
//
// //QHBoxLayout *hbLayout = qobject_cast<QHBoxLayout *>(ui.tableWidget->cellWidget(row, column[i]));
// //qobject_cast<QCheckBox *>(hbLayout->widget())->setCheckState(Qt::CheckState::Checked);
//}
QStringList Part;
Part << " " << "0805" << "0603" << "0402";
QStringList Feeder;
Feeder << "A" << "C0805(2012)" << "R0603(1608)" << "C0402(1005)";
QStringList Nozzle;
Nozzle << "A" << "1-1-EMPTY" << "1-2-CN020" << "1-3-CN030" << "1-4-CN040" << "1-5-CN065" << "1-6-CN140" << "1-7-CN220" << "1-8-CN400";
QStringList HD;
HD << "1" << "2" << "3" << "4" << "5" << "6";
QComboBox *comBox[] = { new QComboBox, new QComboBox, new QComboBox, new QComboBox };
comBox[0]->addItems(Part);
comBox[1]->addItems(Feeder);
comBox[2]->addItems(Nozzle);
comBox[3]->addItems(HD);
// 单元格添加控件
ui.tableWidget->setCellWidget(row, COLUMN_HEAD_INDEX::Part, comBox[0]);
ui.tableWidget->setCellWidget(row, COLUMN_HEAD_INDEX::Feeder, comBox[1]);
ui.tableWidget->setCellWidget(row, COLUMN_HEAD_INDEX::Nozzle, comBox[2]);
ui.tableWidget->setCellWidget(row, COLUMN_HEAD_INDEX::HD, comBox[3]);
/* ui.tableWidget->cellWidget(row, column) 返回在给定行和列的单元格中显示的小部件 */
QComboBox *comboBox = qobject_cast<QComboBox *>(ui.tableWidget->cellWidget(row, COLUMN_HEAD_INDEX::Part));
comboBox->setCurrentIndex(2); // 根据索默认选择显示
/**************************************************************************************/
// 设置单元格文本居中
int columnCount = ui.tableWidget->columnCount();
for (int column = 0; column < columnCount; column++) {
ui.tableWidget->item(row, column)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
}
// 获取垂直滚动条
QScrollBar *scareen = ui.tableWidget->verticalScrollBar();
// ui.tableWidget->horizontalScrollBar();
// 如果是首行插入
if (row == 0) {
// 设置滚动条位置为最上方
scareen->setValue(scareen->minimum());
// 如果是尾行插入
} else if (row == ui.tableWidget->rowCount() - 1) {
// 设置滚动条位置为最下方
scareen->setValue(scareen->maximum());
} else {
// 否则位置不变
return;
}
}
// 跳过点操作
void QTableWidgets::skipPoints() {
// 存储选中行中的第一个单元格
QList<QTableWidgetItem *> rowItem;
// 获得所有选中的单元格的行
QList<QTableWidgetItem *> selectedList = ui.tableWidget->selectedItems(); // 获取的所有选中的单元格
// 提高效率 与 提示
if (selectedList.count() == 0) return;
if (QMessageBox::warning(this, "警告", "是否跳过选择行?", QMessageBox::Button::Yes | QMessageBox::Button::No) == QMessageBox::Button::No) {
return;
}
// 将每行的第一个单元格存储;每次循环完后加上16,索引就指向了下一行的第一个单元格位置
for (int row = 0; row < selectedList.count(); row += HEAD_COUNT) {
// 去重
rowItem.append(selectedList.at(row)); // 将每行的第一个单元格存储
}
// 效率就提高了
for each (QTableWidgetItem *item in rowItem) {
int row = item->row();
// 设置为选中状态
ui.tableWidget->item(row, COLUMN_HEAD_INDEX::SK)->setCheckState(Qt::CheckState::Checked);
}
}
// 取消跳过点
void QTableWidgets::cancleSkipPoints() {
// 存储选中行中的第一个单元格
QList<QTableWidgetItem *> rowItem;
// 获得所有选中的单元格的行
QList<QTableWidgetItem *> selectedList = ui.tableWidget->selectedItems(); // 获取的所有选中的单元格
// 提高效率 与 提示
if (selectedList.count() == 0) return;
if (QMessageBox::warning(this, "警告", "是否取消跳过选择行?", QMessageBox::Button::Yes | QMessageBox::Button::No) == QMessageBox::Button::No) {
return;
}
// 将每行的第一个单元格存储;每次循环完后加上16,索引就指向了下一行的第一个单元格位置
for (int row = 0; row < selectedList.count(); row += HEAD_COUNT) {
// 去重
rowItem.append(selectedList.at(row)); // 将每行的第一个单元格存储
}
// 效率就提高了
for each (QTableWidgetItem *item in rowItem) {
int row = item->row();
ui.tableWidget->item(row, COLUMN_HEAD_INDEX::SK)->setCheckState(Qt::CheckState::Unchecked);
}
}
总结:
此小项目本人花了两周时间研究完成,其中蕴涵的知识点还是蛮多的,记录下来,供大家参考借鉴。
删除行记得释放控件的内存。
qt的类型转换:
qobject_cast<QComboBox *>(ui.tableWidget->cellWidget(row, column));(QComboBox *)dynamic_cast<QComboBox *>(ui.tableWidget->cellWidget(row, column));