目录
2.批量添加QPushButton控件,实现“打开”/“关闭”的切换
3.批量添加QCheckBox控件,实现“选中”/“未选中”的切换
前言
先看效果动图:
表格分页等操作
下面开始实现每个功能。
一、新建项目
新建项目很简单,就不具体详述了,不会的自己摸索以下,已经会的可以跳过。我的项目名称是QT_QTableWidget
二、设置主窗口标题和图标
项目创建完成后,点击左下角的绿色按钮,先运行下是否报错。如图:
没有报错,就可以正常编写代码了。
首先把项目标题和项目图标设置一下。
1.项目标题设置:
在构造函数中敲出下面一行代码。
this->setWindowTitle(tr("QTableWidget批量添加数据、批量添加控件、分页跳转、定位到指定行、添加/插入/删除行的功能实现"));
2.项目图标设置:
设置图标需要将图片放入到项目的资源文件中,否则,无法设置。
(1)创建资源文件操作
鼠标放在项目名上,鼠标右击,在弹出的菜单中选择“Add New.....”,再次弹出一个提示框,依次选择“Qt”和Qt资源文件,之后按着如下截图依次操作。
(2)设置图标
在构造函数中,添加以下代码:
// 设置图标必须要创建资源文件,并将所需要的图片添加到项目中,复制图片的资源路径
this->setWindowIcon(QIcon(":/menu/xue.png"));
(3)代码截图和运行效果图
三、界面设计
(1)在ui设计界面,拖出一个TableWidget控件,对象名为tableWidget;
(2)再拖出4个PushButton按钮控件,文本为:“首页”、“上一页”、“下一页”、“尾页”,对象名依次为:FirstPageBtn、PrevPageBtn、NextPageBtn、LastPageBtn;
再放入5个Lable控件和1个LineEdit控件(对象名为lineEdit),Lable文本为:“第几页(这个会动态修改掉)”(对象名为CurPageLable)、“/”、“共几页(可动态修改)”(对象名为TotalPageLable)、“跳转到第”、“页”;
(3)放入一个Lable控件,文本为“当前行号:”、放入1个LineEdit控件,对象名为“currentRowLineEdit”;
再放入3个PushButton按钮,文本分别为“添加一行”、“插入一行”、“删除一行”,对象名分别为“addBtn”、“insertBtn”、“delBtn”;
再放入一个Lable控件,文本为“定位到指定行:”、放入1个LineEdit控件,对象名为“input”,设置placeholderText属性值为“请输入要查询的内容”;
(4)为每个按钮添加点击样式
(4)界面设计图如下
四、QTableWidget的初始化
在mainwindow.h中声明初始化函数:
private:
void setTableWidget(int row,int column); /* QTableWidget的初始化 */
在mainwindow.cpp中添加定义,并设置QTableWidget的相关属性,这些属性都是最常见的必不可少的,可以根据需求更改,如下代码:
//QTableWidget的初始化
void MainWindow::setTableWidget(int row,int column)
{
ui->tableWidget->resizeRowsToContents();//调整行内容大小
ui->tableWidget->setColumnCount(column);//设置列数
ui->tableWidget->setRowCount(row);//设置行数
ui->tableWidget->horizontalHeader()->setDefaultSectionSize(200);//标题头的大小
ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);//横向先自适应宽度
ui->tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents);//然后设置要根据内容使用宽度的列
//设置标题头的文字
QStringList header;
header<< tr("编号") << tr("静态数据") << tr("LED指示灯") << tr("按钮控件") << tr("Check Box控件") << "单元格改变的信号处理操作" ;
ui->tableWidget->setHorizontalHeaderLabels(header);
//设置标题头的字体样式
QFont font = ui->tableWidget->horizontalHeader()->font();
font.setBold(true);
ui->tableWidget->horizontalHeader()->setFont(font);
ui->tableWidget->horizontalHeader()->setStretchLastSection(true); //设置充满表宽度
ui->tableWidget->verticalHeader()->setDefaultSectionSize(10); //设置行距
ui->tableWidget->setFrameShape(QFrame::NoFrame); //设置无边框
ui->tableWidget->setShowGrid(true); //设置不显示格子线
ui->tableWidget->verticalHeader()->setVisible(false); //设置行号列,true为显示
ui->tableWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); //可多选(Ctrl、Shift、 Ctrl+A都可以)
ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); //设置选择行为时每次选择一行
ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); //设置不可编辑
ui->tableWidget->horizontalHeader()->resizeSection(0,100);//设置表头第一列的宽度为100
ui->tableWidget->horizontalHeader()->setFixedHeight(30); //设置表头的高度
ui->tableWidget->setStyleSheet("selection-background-color:lightblue;"); //设置选中背景色
ui->tableWidget->horizontalHeader()->setStyleSheet("QHeaderView::section{background:white;}"); //设置表头背景色
//设置水平、垂直滚动条样式,添加头文件 #include <QScrollBar>
ui->tableWidget->horizontalScrollBar()->setStyleSheet("QScrollBar{background:transparent; height:10px;}"
"QScrollBar::handle{background:lightgray; border:2px solid transparent; border-radius:5px;}"
"QScrollBar::handle:hover{background:gray;}"
"QScrollBar::sub-line{background:transparent;}"
"QScrollBar::add-line{background:transparent;}");
ui->tableWidget->verticalScrollBar()->setStyleSheet("QScrollBar{background:transparent; width: 10px;}"
"QScrollBar::handle{background:lightgray; border:2px solid transparent; border-radius:5px;}"
"QScrollBar::handle:hover{background:gray;}"
"QScrollBar::sub-line{background:transparent;}"
"QScrollBar::add-line{background:transparent;}");
ui->tableWidget->clearContents();//清除表格数据区的所有内容,但是不清除表头
}
设置好后,在构造函数中调用,设置表格为50行,6列:
setTableWidget(50,6);
运行后,效果如下:
五、 QTableWidget中批量添加数据
在添加数据时,我将每一列的索引值都用一个常量进行标识,是为了方便查询和修改。
在mainwindow.h中声明6个常量:
private:
const int sn = 0; /* 序号列 */
const int static_data = 1; /* 静态数据列 */
const int led = 2; /* LED列 */
const int btn = 3; /* 按钮列 */
const int check = 4; /* checkbox列 */
const int CellChanged = 5; /* 单元格改变时列 */
现在开始添加数据,核心代码为:
//设置数据
for(int i = 0;i < row;i++)
{
// (2.2.2)批量添加数据
//序号列,sn是在头文件中定义的常量
ui->tableWidget->setItem(i,sn,new QTableWidgetItem(QString::number(i+1)));
//内容水平垂直居中,注意一定要先设置内容,此属性才会有效
ui->tableWidget->item(i,sn)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
//静态数据列,static_data是在头文件中定义的常量
ui->tableWidget->setItem(i,static_data,new QTableWidgetItem(tr("我是静态数据 %1").arg(i + 1)));
ui->tableWidget->item(i,static_data)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
}
把这一段代码,放在 void setTableWidget(int row,int column);函数中,
//QTableWidget的初始化
void MainWindow::setTableWidget(int row,int column)
{
ui->tableWidget->resizeRowsToContents();//调整行内容大小
ui->tableWidget->setColumnCount(column);//设置列数
ui->tableWidget->setRowCount(row);//设置行数
ui->tableWidget->horizontalHeader()->setDefaultSectionSize(200);//标题头的大小
ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);//横向先自适应宽度
ui->tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents);//然后设置要根据内容使用宽度的列
//设置标题头的文字
QStringList header;
header<< tr("编号") << tr("静态数据") << tr("LED指示灯") << tr("按钮控件") << tr("Check Box控件") << "单元格改变的信号处理操作" ;
ui->tableWidget->setHorizontalHeaderLabels(header);
//设置标题头的字体样式
QFont font = ui->tableWidget->horizontalHeader()->font();
font.setBold(true);
ui->tableWidget->horizontalHeader()->setFont(font);
ui->tableWidget->horizontalHeader()->setStretchLastSection(true); //设置充满表宽度
ui->tableWidget->verticalHeader()->setDefaultSectionSize(10); //设置行距
ui->tableWidget->setFrameShape(QFrame::NoFrame); //设置无边框
ui->tableWidget->setShowGrid(true); //设置不显示格子线
ui->tableWidget->verticalHeader()->setVisible(false); //设置行号列,true为显示
ui->tableWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); //可多选(Ctrl、Shift、 Ctrl+A都可以)
ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); //设置选择行为时每次选择一行
ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); //设置不可编辑
ui->tableWidget->horizontalHeader()->resizeSection(0,100);//设置表头第一列的宽度为100
ui->tableWidget->horizontalHeader()->setFixedHeight(30); //设置表头的高度
ui->tableWidget->setStyleSheet("selection-background-color:lightblue;"); //设置选中背景色
ui->tableWidget->horizontalHeader()->setStyleSheet("QHeaderView::section{background:white;}"); //设置表头背景色
//设置水平、垂直滚动条样式,添加头文件 #include <QScrollBar>
ui->tableWidget->horizontalScrollBar()->setStyleSheet("QScrollBar{background:transparent; height:10px;}"
"QScrollBar::handle{background:lightgray; border:2px solid transparent; border-radius:5px;}"
"QScrollBar::handle:hover{background:gray;}"
"QScrollBar::sub-line{background:transparent;}"
"QScrollBar::add-line{background:transparent;}");
ui->tableWidget->verticalScrollBar()->setStyleSheet("QScrollBar{background:transparent; width: 10px;}"
"QScrollBar::handle{background:lightgray; border:2px solid transparent; border-radius:5px;}"
"QScrollBar::handle:hover{background:gray;}"
"QScrollBar::sub-line{background:transparent;}"
"QScrollBar::add-line{background:transparent;}");
ui->tableWidget->clearContents();//清除表格数据区的所有内容,但是不清除表头
//设置数据
for(int i = 0;i < row;i++)
{
// (2.2.2)批量添加数据
//序号列,sn是在头文件中定义的常量
ui->tableWidget->setItem(i,sn,new QTableWidgetItem(QString::number(i+1)));
//内容水平垂直居中,注意一定要先设置内容,此属性才会有效
ui->tableWidget->item(i,sn)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
//静态数据列,static_data是在头文件中定义的常量
ui->tableWidget->setItem(i,static_data,new QTableWidgetItem(tr("我是静态数据 %1").arg(i + 1)));
ui->tableWidget->item(i,static_data)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
}
}
运行后,效果图如下:
六、QTableWidget中批量添加控件
只列举3中控件的添加,其他控件与之一样,就不一一列举了。
QTableWidget添加控件需要用到下面方法:
1.批量添加QLable控件,制作LED指示灯
需求:批量添加50个QLable控件,制作LED指示灯,默认是红灯,使用定时器让红绿灯交替执行。
(1)在mainwindow.h中声明添加控件的函数
QWidget *CreateQLable(int flag); /* 指示灯 */
(2) 在mainwindow.cpp中添加定义
因为需要创建50个LED灯,所以需要封装一个函数,然后for循环依次创建出50个即可。
//添加QLable控件,制作LED灯
QWidget *MainWindow::CreateQLable(int flag)
{
QLabel *lab = new QLabel();
lab->setFixedSize(QSize(12,12));
switch (flag)
{
case 0:
//绿灯
lab->setStyleSheet("background-color: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5, stop:0 rgba(0, 255, 0, 255), stop:1 rgba(255, 255, 255, 255));\
border-radius: 6px;");
break;
case 1:
//红灯
lab->setStyleSheet("background-color: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5, stop:0 rgba(255, 0, 0, 255), stop:1 rgba(255, 255, 255, 255));\
border-radius: 6px;");
break;
}
QHBoxLayout *vLayout = new QHBoxLayout(); //水平布局
QWidget *Widget_lab = new QWidget(); //新建Widget
vLayout->addWidget(lab); //布局中添加了控件
vLayout->setMargin(0); //水平垂直居中必须使用此属性,不然不是想要的效果
vLayout->setAlignment(lab,Qt::AlignVCenter); //水平垂直居中
Widget_lab->setLayout(vLayout); //Widget中添加布局
// ui->tableWidget->setCellWidget(0,2,Widget_lab);//某个单元格中添加1个控件
return Widget_lab;
}
(3)使用
在 void setTableWidget(int row,int column);函数中调用。
//QTableWidget的初始化
void MainWindow::setTableWidget(int row,int column)
{
ui->tableWidget->resizeRowsToContents();//调整行内容大小
ui->tableWidget->setColumnCount(column);//设置列数
ui->tableWidget->setRowCount(row);//设置行数
ui->tableWidget->horizontalHeader()->setDefaultSectionSize(200);//标题头的大小
ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);//横向先自适应宽度
ui->tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents);//然后设置要根据内容使用宽度的列
//设置标题头的文字
QStringList header;
header<< tr("编号") << tr("静态数据") << tr("LED指示灯") << tr("按钮控件") << tr("Check Box控件") << "单元格改变的信号处理操作" ;
ui->tableWidget->setHorizontalHeaderLabels(header);
//设置标题头的字体样式
QFont font = ui->tableWidget->horizontalHeader()->font();
font.setBold(true);
ui->tableWidget->horizontalHeader()->setFont(font);
ui->tableWidget->horizontalHeader()->setStretchLastSection(true); //设置充满表宽度
ui->tableWidget->verticalHeader()->setDefaultSectionSize(10); //设置行距
ui->tableWidget->setFrameShape(QFrame::NoFrame); //设置无边框
ui->tableWidget->setShowGrid(true); //设置不显示格子线
ui->tableWidget->verticalHeader()->setVisible(false); //设置行号列,true为显示
ui->tableWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); //可多选(Ctrl、Shift、 Ctrl+A都可以)
ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); //设置选择行为时每次选择一行
ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); //设置不可编辑
ui->tableWidget->horizontalHeader()->resizeSection(0,100);//设置表头第一列的宽度为100
ui->tableWidget->horizontalHeader()->setFixedHeight(30); //设置表头的高度
ui->tableWidget->setStyleSheet("selection-background-color:lightblue;"); //设置选中背景色
ui->tableWidget->horizontalHeader()->setStyleSheet("QHeaderView::section{background:white;}"); //设置表头背景色
//设置水平、垂直滚动条样式,添加头文件 #include <QScrollBar>
ui->tableWidget->horizontalScrollBar()->setStyleSheet("QScrollBar{background:transparent; height:10px;}"
"QScrollBar::handle{background:lightgray; border:2px solid transparent; border-radius:5px;}"
"QScrollBar::handle:hover{background:gray;}"
"QScrollBar::sub-line{background:transparent;}"
"QScrollBar::add-line{background:transparent;}");
ui->tableWidget->verticalScrollBar()->setStyleSheet("QScrollBar{background:transparent; width: 10px;}"
"QScrollBar::handle{background:lightgray; border:2px solid transparent; border-radius:5px;}"
"QScrollBar::handle:hover{background:gray;}"
"QScrollBar::sub-line{background:transparent;}"
"QScrollBar::add-line{background:transparent;}");
ui->tableWidget->clearContents();//清除表格数据区的所有内容,但是不清除表头
//设置数据
for(int i = 0;i < row;i++)
{
// (2.2.2)批量添加数据
//序号列,sn是在头文件中定义的常量
ui->tableWidget->setItem(i,sn,new QTableWidgetItem(QString::number(i+1)));
//内容水平垂直居中,注意一定要先设置内容,此属性才会有效
ui->tableWidget->item(i,sn)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
//静态数据列,static_data是在头文件中定义的常量
ui->tableWidget->setItem(i,static_data,new QTableWidgetItem(tr("我是静态数据 %1").arg(i + 1)));
ui->tableWidget->item(i,static_data)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
// (2.2.3)批量添加控件
// 批量添加QLable控件,制作LED指示灯,默认是红灯,使用定时器让红绿灯交替执行
ui->tableWidget->setCellWidget(i,led,CreateQLable(1));
}
}
(4)运行效果
(5)使用定时器,让LED红绿交替闪烁(3中闪烁形式)
在mainwindow.h中声明定时器:
QTimer *led_timer;
在mainwindow.cpp中添加定义,添加头文件 #include <QTimer>:
led_timer = new QTimer(this);
要实现红绿交换,需要状态标志来表示是红色还是绿色,我这里只列举3个LED的闪烁,剩下的按着这个方法来即可。
核心代码:
头文件:
private:
QTimer *led_timer;
int CurCnt = -1;
bool flag = false;
//不同指示灯的状态标志位,只举出3个例子,其他都是相同操作,不在赘述
bool LED0_flag = false;
bool LED1_flag = false;
bool LED2_flag = false;
QVector<bool> LED_flag_vector;
在构造函数中添加以下代码,每隔1s变一次:
LED_flag_vector << LED0_flag << LED1_flag << LED2_flag ;
led_timer = new QTimer(this);
led_timer->start(1000);//1s变一次
connect(led_timer,&QTimer::timeout,this,&MainWindow::on_led_timer);
定时器信号的槽函数为:
public slots:
void on_led_timer();
void MainWindow::on_led_timer()
{
if((CurCnt >= 50) || (CurCnt == -1))
{
CurCnt = 0;
}
else
{
CurCnt++;
}
// 1)、同一时间只有一个指示灯亮
for(int j = 0; j < 50; j++)
{
if(j == CurCnt)
{
ui->tableWidget->removeCellWidget(j,led);//删除控件,防止追加
ui->tableWidget->setCellWidget(j,led,CreateQLable(0));
}
else
{
ui->tableWidget->removeCellWidget(j,led);
ui->tableWidget->setCellWidget(j,led,CreateQLable(1));
}
}
// 2)、所有指示灯同时变红变绿,解开以下注释即可查看效果
// if(flag)
// {
// for(int j = 0; j < 50; j++)
// {
// //变红
// ui->tableWidget->removeCellWidget(j,led);
// ui->tableWidget->setCellWidget(j,led,CreateQLable(1));//表格中添加Widget
// flag = false;
// }
// }
// else
// {
// for(int j = 0; j < 50; j++)
// {
// //变绿
// ui->tableWidget->removeCellWidget(j,led);
// ui->tableWidget->setCellWidget(j,led,CreateQLable(0));//表格中添加Widget
// flag = true;
// }
// }
// 3)、所有指示灯互不干扰,解开以下注释即可查看效果
// if(LED_flag_vector.at(0))
// {
// //变红
// ui->tableWidget->removeCellWidget(0,led);//删除之前的控件
// ui->tableWidget->setCellWidget(0,led,CreateQLable(1));//表格中添加Widget
// LED_flag_vector.replace(0,false);
// }
// else
// {
// //变绿
// ui->tableWidget->removeCellWidget(0,led);
// ui->tableWidget->setCellWidget(0,led,CreateQLable(0));//表格中添加Widget
// LED_flag_vector.replace(0,true);
// }
// if(CurCnt % 3 == 0)
// {
// if(LED_flag_vector.at(1))
// {
// //变红
// ui->tableWidget->removeCellWidget(1,led);//删除之前的控件
// ui->tableWidget->setCellWidget(1,led,CreateQLable(1));//表格中添加Widget
// LED_flag_vector.replace(1,false);
// }
// else
// {
// //变绿
// ui->tableWidget->removeCellWidget(1,led);
// ui->tableWidget->setCellWidget(1,led,CreateQLable(0));//表格中添加Widget
// LED_flag_vector.replace(1,true);
// }
// }
// if(CurCnt % 5 == 0)
// {
// if(LED_flag_vector.at(2))
// {
// //变红
// ui->tableWidget->removeCellWidget(2,led);//删除之前的控件
// ui->tableWidget->setCellWidget(2,led,CreateQLable(1));//表格中添加Widget
// LED_flag_vector.replace(2,false);
// }
// else
// {
// //变绿
// ui->tableWidget->removeCellWidget(2,led);
// ui->tableWidget->setCellWidget(2,led,CreateQLable(0));//表格中添加Widget
// LED_flag_vector.replace(2,true);
// }
// }
}
运行后,效果图:
2.批量添加QPushButton控件,实现“打开”/“关闭”的切换
(1)封装成一个函数。
QWidget *CreateQPushButton(); /* 批量添加QPushButton控件 */
需要注意的是:按钮点击信号的处理,
clicked信号有两个,clicked();和 clicked(bool checked);
此文章使用的是带参数的,所以还要处理函数重载,处理方法和注意事项都放在下方代码中了。
// 批量添加QPushButton控件
QWidget *MainWindow::CreateQPushButton()
{
QWidget *Widget_btn = new QWidget;
QVBoxLayout *hLayout = new QVBoxLayout();
QPushButton *btn = new QPushButton("打开");//添加头文件 #include <QCheckBox>
btn->setCheckable(true);//必须要有此属性,否则信号发送无效
// 以下3个信号都可以,选择自己习惯使用的就行
// connect(btn,&QPushButton::toggled,ui->tableWidget,[=](bool checked)
// {
// });
//注意:解决信号函数重载方法
// 1,使用QOverload
connect(btn,QOverload<bool>::of(&QPushButton::clicked),this,[=](bool checked)
{
if(checked)
{
btn->setText("关闭");
}
else
{
btn->setText("打开");
}
});
//2.使用函数指针
// void (QPushButton:: * btn_bool)(bool) = &QPushButton::clicked;
// connect(btn,btn_bool,this,[=](bool enable)
// {
// });
hLayout->addWidget(btn);
hLayout->setMargin(0);
hLayout->setAlignment(btn, Qt::AlignCenter);
Widget_btn->setLayout(hLayout);
return Widget_btn;
}
(2)使用
在 void setTableWidget(int row,int column);函数中的for循环中调用。代码如下:
//设置数据
for(int i = 0;i < row;i++)
{
// (2.2.2)批量添加数据
//序号列,sn是在头文件中定义的常量
ui->tableWidget->setItem(i,sn,new QTableWidgetItem(QString::number(i+1)));
//内容水平垂直居中,注意一定要先设置内容,此属性才会有效
ui->tableWidget->item(i,sn)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
//静态数据列,static_data是在头文件中定义的常量
ui->tableWidget->setItem(i,static_data,new QTableWidgetItem(tr("我是静态数据 %1").arg(i + 1)));
ui->tableWidget->item(i,static_data)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
// (2.2.3)批量添加控件
// 批量添加QLable控件,制作LED指示灯,默认是红灯,使用定时器让红绿灯交替执行
ui->tableWidget->setCellWidget(i,led,CreateQLable(1));
// 批量添加QPushButton控件
ui->tableWidget->setCellWidget(i, btn, CreateQPushButton());
}
(3)运行效果
3.批量添加QCheckBox控件,实现“选中”/“未选中”的切换
(1)封装成一个函数。
QWidget *CreateQCheckBox(); /* 批量添加QCheckBox控件 */
//批量添加QCheckBox控件
QWidget *MainWindow::CreateQCheckBox()
{
QWidget *Widget_ckb = new QWidget;
QVBoxLayout *hLayout = new QVBoxLayout();
// QPushButton *btn = new QPushButton(tr("按钮 %1").arg(i + 1));
QCheckBox *ckb = new QCheckBox("选中");//添加头文件 #include <QCheckBox>
connect(ckb,&QCheckBox::stateChanged,this,[=]()
{
if(ckb->checkState() == Qt::Checked)
{
ckb->setText("选中");
}
else if(ckb->checkState() == Qt::Unchecked)
{
ckb->setText("未选中");
}
});
hLayout->addWidget(ckb);
hLayout->setMargin(0);
hLayout->setAlignment(ckb, Qt::AlignCenter);
Widget_ckb->setLayout(hLayout);
return Widget_ckb;
}
(2)使用
在 void setTableWidget(int row,int column);函数中的for循环中调用。代码如下:
//设置数据
for(int i = 0;i < row;i++)
{
// (2.2.2)批量添加数据
//序号列,sn是在头文件中定义的常量
ui->tableWidget->setItem(i,sn,new QTableWidgetItem(QString::number(i+1)));
//内容水平垂直居中,注意一定要先设置内容,此属性才会有效
ui->tableWidget->item(i,sn)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
//静态数据列,static_data是在头文件中定义的常量
ui->tableWidget->setItem(i,static_data,new QTableWidgetItem(tr("我是静态数据 %1").arg(i + 1)));
ui->tableWidget->item(i,static_data)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
// (2.2.3)批量添加控件
// 批量添加QLable控件,制作LED指示灯,默认是红灯,使用定时器让红绿灯交替执行
ui->tableWidget->setCellWidget(i,led,CreateQLable(1));
// 批量添加QPushButton控件
ui->tableWidget->setCellWidget(i, btn, CreateQPushButton());
// 批量添加QCheckBox控件
ui->tableWidget->setCellWidget(i, check, CreateQCheckBox());
}
(3)运行效果
是不是很简单?!! 那么其他控件也可以添加,动手试试看。
七、QTableWidget的分页跳转
此功能,我是参考大佬的做法。
重点来了!!!!!!!!
(1)mainwindow.h中声明变量、函数、槽函数
public:
//分页显示
int pageSize; /* 每一页的行数 */
int curPage; /* 当前页 */
private:
void setCurPage(int n); /* 显示表格当前页 */
int getPageCount(const int row_count); /* 计算表格总页数 */
void setTotalPage(const int all); /* 显示表格总页数 */
void showPageData(); /* 显示每页的数据 */
private slots:
void on_PrevPageBtn_clicked(); /* 上一页 */
void on_NextPageBtn_clicked(); /* 下一页 */
void on_FirstPageBtn_clicked(); /* 首页 */
void on_LastPageBtn_clicked(); /* 尾页 */
void on_lineEdit_textChanged(const QString &arg1); /* 跳转页 */
(2)mainwindow.cpp中初始化变量、定义函数、定义槽函数
在构造函数中变量初始化,默认显示表格第一页,首页、上一页按钮禁止点击
// 变量初始化,默认显示表格第一页,首页、上一页按钮禁止点击
pageSize = 10;//每一页默认显示10行数据
curPage = 0;
setCurPage(curPage);
showPageData();
之后定义函数:
1)、控件显示页数和总页数
void MainWindow::setCurPage(int n)
{
ui->labelCurPage->setText(QString("第 %1 页").arg(n+1));
}
void MainWindow::setTotalPage(int n)
{
ui->labelTotalPage->setText(QString("共 %1 页").arg(n));
}
2)、分页显示数据(此功能的核心代码)
//分页数据
void MainWindow::showPageData()
{
int rowCount = ui->tableWidget->rowCount();
if(curPage == 0)
{
ui->PrevPageBtn->setDisabled(true);
ui->FirstPageBtn->setDisabled(true);
}
else
{
ui->PrevPageBtn->setDisabled(false);
ui->FirstPageBtn->setDisabled(false);
}
if(curPage == getPageCount(rowCount) - 1)
{
ui->NextPageBtn->setDisabled(true);
ui->LastPageBtn->setDisabled(true);
}
else
{
ui->NextPageBtn->setDisabled(false);
ui->LastPageBtn->setDisabled(false);
}
/* 以下是分页的核心代码 */
int PageStartRow = pageSize * curPage; /* 每页的起始行 */
int PageEndRow = 0; /* 每页的结束行 */
//通过判断是否超出tableWidget表格的总行数来获取每页的结束行
if(PageStartRow + pageSize < rowCount)
{
PageEndRow = PageStartRow + pageSize;
}
else
{
PageEndRow = rowCount;
}
for(int i = 0; i < rowCount; i++)
{
//显示当前页的每行数据并隐藏其他页的数据
if(i >= PageStartRow && i < PageEndRow)
{
ui->tableWidget->setRowHidden(i, false);
}
else
{
ui->tableWidget->setRowHidden(i, true);
}
}
}
int MainWindow::getPageCount(const int row_count)
{
int pageCnt = 0;
if(row_count == 0)
{
return 0;
}
else if(row_count % pageSize == 0)
{
pageCnt = row_count / pageSize;
}
else
{
pageCnt = row_count / pageSize + 1;
}
setTotalPage(pageCnt);
return pageCnt;
}
3)、上一页、下一页、首页、尾页、跳转操作
为这4个按钮添加点击clicked信号的槽函数。
添加槽函数最简单的方法就是,选中控件,鼠标右击,在弹出菜单中选择“转到槽......”,就可以在头文件和.cpp文件中添加对应的声明和定义。
跳转页的输入框也有自己的 textChanged(const QString &arg1)的信号和槽。
转到槽操作如图所示:
上一页、下一页、首页、尾页、跳转操作的核心代码如下:
//上一页
void MainWindow::on_PrevPageBtn_clicked()
{
curPage--;
if(curPage < 0)
{
curPage = 0;
}
setCurPage(curPage);
showPageData();
}
//下一页
void MainWindow::on_NextPageBtn_clicked()
{
curPage++;
setCurPage(curPage);
showPageData();
}
//首页
void MainWindow::on_FirstPageBtn_clicked()
{
curPage = 0;
setCurPage(curPage);
showPageData();
}
//尾页
void MainWindow::on_LastPageBtn_clicked()
{
curPage = getPageCount(ui->tableWidget->rowCount()) -1;
setCurPage(curPage);
showPageData();
}
//跳转页
void MainWindow::on_lineEdit_textChanged(const QString &arg1)
{
int turnPage = arg1.toInt();
if(turnPage > 0 && turnPage < getPageCount(ui->tableWidget->rowCount()) + 1)
{
curPage = turnPage -1;
setCurPage(curPage);
showPageData();
}
}
4)、效果图
分页成功!
八、通过滚动条定位到指定行
在输入框中输入你要查询的数据,当数据发生变化时QLineEdit会发出
textChanged(const QString &arg1);
的信号,为这个信号编写槽函数即可。
在设计界面选中这个输入框,鼠标右击,选择“转到槽......”,就能自动添加下方这个槽函数和定义。
void on_input_textChanged(const QString &arg1); /* 定位到某一行 */
//定位到指定行
void MainWindow::on_input_textChanged(const QString &arg1)
{
if(arg1 == "")
{
return;
}
QList<QTableWidgetItem *> items;
QTableWidgetItem *item;
items = ui->tableWidget->findItems(arg1, Qt::MatchExactly);//在表格中查找数据项
//找到了这个数据项
if(items.length() > 0)
{
item = items[0];//获取到数据项
int r = item->row();//获取所在行
curPage = r / pageSize;//计算在表格第几页
setCurPage(curPage);//定位到这一页
showPageData();//显示这页的数据
ui->tableWidget->verticalScrollBar()->setSliderPosition(r);//滚动条定位到数据所在位置
ui->tableWidget->setCurrentItem(item);//将这个数据所在行设置为表格的当前行
}
}
运行效果如下:
九、QTableWidget中添加/插入/删除行
为这三个按钮的clicked信号,添加槽函数,选中控件鼠标右击,选择“转到槽.....”,在选择“clicked()”信号,即可创建信号和槽的连接。
槽函数声明:
void on_insertBtn_clicked(); /* 插入一行 */
void on_addBtn_clicked(); /* 添加一行 */
void on_delBtn_clicked(); /* 删除一行 */
定义:
//插入
void MainWindow::on_insertBtn_clicked()
{
int curRow = ui->tableWidget->currentRow();
ui->tableWidget->insertRow(curRow); //插入一行,但不会自动为单元格创建item,需要手动创建内容
ui->tableWidget->setItem(curRow,0,new QTableWidgetItem(QString::number(curRow)));
ui->tableWidget->item(curRow,0)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
//此功能还有待完善
}
//添加
void MainWindow::on_addBtn_clicked()
{
int curRow = ui->tableWidget->rowCount();
ui->tableWidget->insertRow(curRow);//在表格尾部添加一行
ui->tableWidget->setItem(curRow,0,new QTableWidgetItem(QString::number(curRow + 1)));
ui->tableWidget->item(curRow,0)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
//此功能还有待完善
}
//删除
void MainWindow::on_delBtn_clicked()
{
int curRow=ui->tableWidget->currentRow();
ui->tableWidget->removeRow(curRow); //删除当前行及其items
}
运行效果
十、监听单元格改变信号
每次点击表格中某行数据时,就会触发currentCellChanged信号。
为这个信号编写自定义槽函数:
void GetRow(int currentRow, int currentColumn, int previousRow, int previousColumn);/* 单元格改变槽函数 */
在构造函数中连接信号
connect(ui->tableWidget,&QTableWidget::currentCellChanged,this,&MainWindow::GetRow);
自动逸槽函数实现:
//单元格变化信号槽函数
void MainWindow::GetRow(int currentRow, int currentColumn, int previousRow, int previousColumn)
{
Q_UNUSED(currentColumn);
Q_UNUSED(previousRow);
Q_UNUSED(previousColumn);
//显示当前行号,默认显示第一行
ui->currentRowLineEdit->setText(QString::asprintf("%d",currentRow + 1));
//给表格最后一列设置数据,CellChanged是最后一列的索引号
ui->tableWidget->setItem(currentRow,CellChanged,new QTableWidgetItem("检测到信号"));
ui->tableWidget->item(currentRow,CellChanged)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
//状态栏显示
statusBar()->showMessage(tr("当前单元格坐标是第 %1 行,第 %2 列").arg(currentRow).arg(currentColumn),3000);
}
效果图:
十一、源码
表格分页等操作
最后,当然是附上源码啦。
加上源码后,文章太太太长了,不方便阅读。
所以,想要源码压缩包的可以私聊我。
源码压缩包:https://download.csdn.net/download/m0_49456900/86506340