Qt QTableWidget基本操作及使用
qtablewidget 是 qt 中的表格组件类。在窗体上放置一个 qtablewidget 组件后,可以在 property editor 里对其进行属性设置,双击这个组件,可以打开一个编辑器,对其 colum、row 和 item 进行编辑。
一个 qtablewidget 组件的界面基本结构如图 1 所示,这个表格设置为 6 行 5 列。
图 1 一个 qtablewidget 表格的基本结构和工作区的行、列索引号
表格的第 1 行称为行表头,用于设置每一列的标题,第 1 列称为列表头,可以设置其标题,但一般使用缺省的标题,即为行号。行表头和列表头一般是不可编辑的。
除了行表头和列表头之外的表格区域是内容区,内容区是规则的网格状,如同一个二维数组,每个网格单元称为一个单元格。每个单元格有一个行号、列号,图 1 表示了行号、列号的变化规律。
在 qtablewidget 表格中,每一个单元格是一个 qtable widgetltem 对象,可以设置文字内容、字体、前景色、背景色、图标,也可以设置编辑和显示标记。每个单元格还可以存储一个 qvariant 数据,用于设置用户自定义数据。
图 2 实例 samp4_9 的运行时界面
实例 samp4_9 以 qtablewidget 为主要组件,演示 qtablewidget 一些主要操作的实现。实例运行时的界面如图 2 所示,该实例将演示以下功能的实现方法:
- 设置表格的列数和行数,设置表头的文字、格式等。
- 初始化表格数据,设置一批实例数据填充到表格里。
- 插入行、添加行、删除当前行的操作。
- 遍历表格所有单元格,读取表格内容到一个 qplaintextedit 里,表格的一行数据作为一行文本。
- 表格上选择的当前单元格变化时,在状态栏显示单元格存储的信息。
界面设计与初始化
samp4_9 的主窗体从 qmainwindow 继承而来。在图 2 所示的窗口上,一个 qtablewidget 组件和一个 qplaintextedit 组件组成上下分割布局 splitter。左侧的按钮都放在一个 qgroupbox 组件里,釆用 grid 布局,然后将 groupbox 与 splitter 采用左右分割布局。这是一个典型的三区分割的布局。
在主窗口类 mainwindow 里自定义了一些变量和函数,用于后面的代码实现,下面是在 mainwindow 的 private 部分自定义的变量和函数:
private: //自定义单元格type的类型,在创建单元格的item时使用 enum celltype{ctname=1000,ctsex,ctbirth,ctnation,ctpartym,ctscore}; //各字段在表格中的列号 enum fieldcolnum{colname=0,colsex,colbirth,colnation,colscore,colpartym}; qlabel *labcellindex; //状态栏上用于显示单元格的行号、列号 qlabel *labcelltype; //状态栏上用于显示单元格的type qlabel *labstudid; //状态栏上用于显示学号 void createitemsarow(int rowno,qstring name,qstring sex,qdate birth,qstring nation,bool ispm,int score) ; //为某一行创建 items
枚举类型 celltype 是用来表示单元格类型的,在创建单元格时使用。枚举类型 fieldcolnum 用枚举常量表示各字段在表格中的列号。
在 mainwindow 的构造函数里对界面进行初始化,代码如下:
mainwindow::mainwindow(qwidget *parent) : qmainwindow(parent), ui(new ui::mainwindow) { ui->setupui(this); setcentralwidget(ui->splittermain); //状态栏初始化创建 labcellindex = new qlabel ("当前单元格坐标:", this); labcellindex->setminimumwidth(250); labcelltype=new qlabel ("当前单元格类型:",this); labcelltype->setminimumwidth(200); labstudid=new qlabel ("学生id: ", this); labstudid->setminimumwidth(200); ui->statusbar->addwidget (labcellindex) ; //加到状态栏 ui->statusbar->addwidget(labcelltype); ui->statusbar->addwidget(labstudid); }
qtablewidget 基本操作
设置表头
界面上的“设置表头”按钮实现对表头的设置,其 clicked() 信号的槽函数代码如下:
mainwindow::mainwindow(qwidget *parent) : qmainwindow(parent), ui(new ui::mainwindow) { ui->setupui(this); setcentralwidget(ui->splittermain); //状态栏初始化创建 labcellindex = new qlabel ("当前单元格坐标:", this); labcellindex->setminimumwidth(250); labcelltype=new qlabel ("当前单元格类型:",this); labcelltype->setminimumwidth(200); labstudid=new qlabel ("学生id: ", this); labstudid->setminimumwidth(200); ui->statusbar->addwidget (labcellindex) ; //加到状态栏 ui->statusbar->addwidget(labcelltype); ui->statusbar->addwidget(labstudid); }
行表头各列的文字标题由一个 qstringlist 对象 headertext 初始化存储,如果只是设置行表头各列的标题,使用下面一行语句即可:
ui->tableinfo->sethorizontalheaderlabels(headertext);
如果需要进行更加具体的格式设置,需要为行表头的每个单元格创建一个 qtablewidgetitem 类型的变量,并进行相应设置。
在一个表格中,不管是表头还是工作区,每个单元格都是一个 qtablewidgetitem 对象。qtablewidgetitem 对象存储了单元格的所有内容,包括字标题、格式设置,以及关联的数据。上面程序中的 for 循环遍历 headertext 的每一行,用每一行的文字创建一个 qtablewidgetitem 对象 headerltem,然后设置 headeritem 的字体大小为 12、粗体、红色,然后将 headerltem 赋给表头的某一列:
ui->tableinfo->sethorizontalheaderitern (i, headeritem);
初始化表格数据
界面上的“初始化表格数据”按钮根据表格的行数,生成数据填充表格,并为每个单元格生成 qtablewidgetitem 对象,设置相应属性。下面是 btnlnidata 的 clicked() 信号的槽函数代码:
void mainwindow::on_btninidata_clicked() { //初始化表格内容 qstring strname,strsex; bool isparty=false; qdate birth; birth.setdate(1980,4,7);//初始化一个日期 ui->tableinfo->clearcontents();//只清除工作区,不清除表头 int rows=ui->tableinfo->rowcount(); //数据区行数, for (int i=0;i<rows;i++) //数据区第1行的编号为0,所以范围是0~rowcount()-1 { strname=qstring::asprintf("学生%d",i); //学生姓名 if ((i % 2)==0) //分奇数,偶数行设置性别,及其图标 strsex="男"; else strsex="女"; createitemsarow(i, strname, strsex, birth,"汉族",isparty,70); //为某一行创建items birth=birth.adddays(20); //日期加20天 isparty =!isparty; } }
qtablewidget::clearcontents() 函数清除表格数据区的所有内容,但是不清除表头。
qtablewidget::rowcount() 函数返回表格数据区的行数。
在 for 循环里为每一行生成需要显示的数据,然后调用自定义函数 createitemsarow(),为表格一行的各个单元格生成 qtablewidgetitem 对象。
createitemsarow() 是在窗体类里自定义的函数,其实现代码如下:
void mainwindow::createitemsarow(int rowno,qstring name,qstring sex,qdate birth,qstring nation,bool ispm,int score) { //为一行的单元格创建 items qtablewidgetitem *item; qstring str; uint studid=201605000; //学号基数 //姓名 //新建一个item,设置单元格type为自定义的mainwindow::ctname item=new qtablewidgetitem(name,mainwindow::ctname); item->settextalignment(qt::alignhcenter | qt::alignvcenter); //文本对齐格式 studid +=rowno; //学号=基数+ 行号 item->setdata(qt::userrole,qvariant(studid)); //设置studid为data ui->tableinfo->setitem(rowno,mainwindow::colname,item); //为单元格设置item //性别 qicon icon; if (sex=="男") icon.addfile(":/images/icons/boy.ico"); else icon.addfile(":/images/icons/girl.ico"); item=new qtablewidgetitem(sex,mainwindow::ctsex); //新建一个item,设置单元格type为自定义的 mainwindow::ctsex item->seticon(icon); item->settextalignment(qt::alignhcenter | qt::alignvcenter);//为单元格设置item ui->tableinfo->setitem(rowno,mainwindow::colsex,item);//为单元格设置item //出生日期 str=birth.tostring("yyyy-mm-dd"); //日期转换为字符串 item=new qtablewidgetitem(str,mainwindow::ctbirth);//新建一个item,设置单元格type为自定义的 mainwindow::ctbirth item->settextalignment(qt::alignleft | qt::alignvcenter); //文本对齐格式 ui->tableinfo->setitem(rowno,mainwindow::colbirth,item);//为单元格设置item //民族 item=new qtablewidgetitem(nation,mainwindow::ctnation); //新建一个item,设置单元格type为自定义的 mainwindow::ctnation item->settextalignment(qt::alignhcenter | qt::alignvcenter);//文本对齐格式 ui->tableinfo->setitem(rowno,mainwindow::colnation,item);//为单元格设置item //是否党员 item=new qtablewidgetitem("党员",mainwindow::ctpartym);//新建一个item,设置单元格type为自定义的 mainwindow::ctpartym item->settextalignment(qt::alignhcenter | qt::alignvcenter);//文本对齐格式 if (ispm) item->setcheckstate(qt::checked); else item->setcheckstate(qt::unchecked); item->setbackgroundcolor(qt::yellow);//qt::green lightgray yellow ui->tableinfo->setitem(rowno,mainwindow::colpartym,item);//为单元格设置item //分数 str.setnum(score); item=new qtablewidgetitem(str,mainwindow::ctscore);//新建一个item,设置单元格type为自定义的 mainwindow::ctpartym item->settextalignment(qt::alignhcenter | qt::alignvcenter);//文本对齐格式 ui->tableinfo->setitem(rowno,mainwindow::colscore,item);//为单元格设置item }
该表格的每一行有5列,为每一个单元格都创建一个 qtablewidgetitem 类型的变量 item,并做相应的设置。
创建 qtablewidgetitem 使用的构造函数的原型为:
qtablewidgetitem::qtablewidgetitem (const qstring &text, int type = type)
其中,第一个参数作为单元格的显示文字,第二个参数作为节点的类型。
例如创建“姓名”单元格对象时的语句是:
cellitem=new qtablewidgetitem(name,mainwindow::ctname);
其中,mainwindow::ctname 是定义的枚举类型 celltype 的一个常量值。
“姓名”单元格还调用 setdata() 函数设置了一个自定义的数据,存储的是学生 id。
cellitem->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):设置单元格勾选状态,单元格里出现一个qcheckbox组件。
- setflags(qt::itemflags flags):设置单元格的一些属性标记。
设置好 item 的各种属性之后,用 qtablewidget 的 setitem 函数将 item 设置为单元格的项,例如:
ui->tableinfo->setitem(rowno,mainwindow::colname,item);
其中,mainwindow::colname 是定义的枚举类型 fieldcolnum 的一个常量值。
这样初始化设置后,就可以得到如图 2 所示的运行时的表格内容。表格里并没有显示学号,学号是“姓名”单元格的关联数据。
获得当前单元格数据
当鼠标在表格上单击单元格时,被选中的单元格是当前单元格。通过 qtablewidget 的 currentcolumn() 和 currentrow() 可以获得当前单元格的列编号和行编号。
当前单元格发生切换时,会发射 currentcellchanged() 信号和 currentitemchanged() 信号,两个信号都可以利用,只是传递的参数不同。
对 currentcellchanged() 信号编写槽函数,用于获取当前单元格的数据,以及当前行的学生的学号信息,代码如下:
void mainwindow::on_tableinfo_currentcellchanged(int currentrow, int currentcolumn, int previousrow, int previouscolumn) {//当前选择单元格发生变化时的响应 q_unused(previousrow); q_unused(previouscolumn); qtablewidgetitem* item=ui->tableinfo->item(currentrow,currentcolumn); //获取单元格的 item if (item==null) return; labcellindex->settext(qstring::asprintf("当前单元格坐标:%d 行,%d 列",currentrow,currentcolumn)); int celltype=item->type();//获取单元格的类型 labcelltype->settext(qstring::asprintf("当前单元格类型:%d",celltype)); item=ui->tableinfo->item(currentrow,mainwindow::colname); //取当前行第1列的单元格的 item int id=item->data(qt::userrole).toint();//读取用户自定义数据 labstudid->settext(qstring::asprintf("学生id:%d",id));//学生id }
在 currentcellchanged() 信号中,传递的参数 currentrow 和 currentcolumn 表示当前单元格的行号和列号,通过这两个编号可以得到单元格的 qtablewidgetltem 对象 item。
获得 item 之后,通过 type() 函数得到单元格的类型参数,这个类型就是为单元格创建 qtablewidgetitem 对象时传递的类型参数。
再获取同一行的“姓名”单元格的项,用data()函数提取自定义数据,也就是创建单元格时存储的学生 id。
插入、添加、删除行
qtablewidget 处理行操作的函数如下:
- insertrow(int row):在行号为row的行前面插入一行,如果row等于或大于总行数,则在表格最后添加一行。insertrow()函数只是插入一个空行,不会为单元格创建qtablewidgetitem对象,需要手工为单元格创建。
- removerow(int row):删除行号为 row 的行。
下面是界面上“插入行” “添加行”“删除当前行”按钮的响应代码。在插入行之后,会调用 createitemsarow() 函数,为新创建的空行的各单元格构造 qtablewidgetitem 对象:
void mainwindow::on_btninsertrow_clicked() { //插入一行 //int currow; int currow=ui->tableinfo->currentrow();//当前行号 ui->tableinfo->insertrow(currow); //插入一行,但不会自动为单元格创建item createitemsarow(currow, "新学生", "男", qdate::fromstring("1990-1-1","yyyy-m-d"),"苗族",true,60 ); //为某一行创建items } void mainwindow::on_btnappendrow_clicked() { //添加一行 //int currow; int currow=ui->tableinfo->rowcount();//当前行号 ui->tableinfo->insertrow(currow);//在表格尾部添加一行 createitemsarow(currow, "新生", "女", qdate::fromstring("2000-1-1","yyyy-m-d"),"满族",false,50 ); //为某一行创建items } void mainwindow::on_btndelcurrow_clicked() {//删除当前行及其items //int currow; int currow=ui->tableinfo->currentrow();//当前行号 ui->tableinfo->removerow(currow); //删除当前行及其items }
自动调整行高和列宽
qtablewidget 有几个函数自动调整表格的行高和列宽,分别如下:
- resizecolumnstocontents():自动调整所有列的宽度,以适应其内容。
- resizecolumntocontents(int column):自动调整列号为 co/www 的列的宽度。
- resizerowstocontents():自动调整所有行的高度,以适应其内容。
- resizerowtocontents(int row):自动调整行号为 raw 的行的高度。
这几个函数实际上是 qtablewidget 的父类 qtableview 的函数。
其他属性控制
设置表格内容是否可编辑:qtablewidget 的 edittriggers 属性表示是否可编辑,以及进入编辑状态的方式。界面上的"表格可编辑"复选框的槽函数代码为:
void mainwindow::on_chkboxtabeditable_clicked(bool checked) { //设置编辑模式 if (checked) //双击或获取焦点后单击,进入编辑状态 ui->tableinfo->setedittriggers(qabstractitemview::doubleclicked | qabstractitemview::selectedclicked); else ui->tableinfo->setedittriggers(qabstractitemview::noedittriggers); //不允许编辑 }
设置行表头、列表头是否显示:horizontalheader()获取行表头,verticalheader()获取列表头,然后可设置其可见性。
void mainwindow::on_chkboxheaderh_clicked(bool checked) { //是否显示水平表头 ui->tableinfo->horizontalheader()->setvisible(checked); } void mainwindow::on_chkboxheaderv_clicked(bool checked) { //是否显示垂直表头 ui->tableinfo->verticalheader()->setvisible(checked); }
间隔行底色:setaltematingrowcolors() 函数可以设置表格的行是否用交替底色显示,若为交替底色,则间隔的一行会用灰色作为底色。具体底色的设置需要用 stylesheet,在后续章节会有介绍。
void mainwindow::on_chkboxrowcolor_clicked(bool checked) { ui->tableinfo->setalternatingrowcolors(checked); }
选择模式:setselectionbehavior() 函数可以设置选择方式为单元格选择,还是行选择:
void mainwindow::on_rbtnselectitem_clicked() {//选择行为:单元格选择 ui->tableinfo->setselectionbehavior(qabstractltemview::selectltems); } void mainwindow::on_rbtnselectrow_clicked() {//选择行为:行选择 ui->tableinfo->setselectionbehavior(qabstractltemview::selectrows); }
遍历表格读取数据
“读取表格内容到文本”按钮演示了将表格数据区的内容全部读出的方法,它将每个单元格的文字读出,同一行的单元格的文字用空格分隔开,作为文本的一行,然后将这行文字作为文本编辑器的一行内容,代码如下:
void mainwindow::on_btnreadtoedit_clicked() {//将 qtablewidget的所有行的内容提取字符串,显示在qplaintextedit里 qstring str; qtablewidgetitem *cellitem; ui->textedit->clear(); //文本编辑器清空 for (int i=0;i<ui->tableinfo->rowcount();i++) //逐行处理 { str=qstring::asprintf("第 %d 行: ",i+1); for (int j=0;j<ui->tableinfo->columncount()-1;j++) //逐列处理,但最后一列是check型,单独处理 { cellitem=ui->tableinfo->item(i,j); //获取单元格的item str=str+cellitem->text()+" "; //字符串连接 } cellitem=ui->tableinfo->item(i,colpartym); //最后一列,党员 if (cellitem->checkstate()==qt::checked) //根据check状态显示文字 str=str+"党员"; else str=str+"群众"; ui->textedit->appendplaintext(str); //添加到编辑框作为一行 } }
到此这篇关于qt qtablewidget基本操作及使用的文章就介绍到这了,更多相关qt qtablewidget内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!