关于Subclassing QTableWidget中QTableWidget继承

移动开发
QTableWidget是一个表示二维离散数组的表格。它在给定维度里显示当前用户滚动的单元格。当用户在一个空的单元格中输入一些文本时,QTableWidget自动创建一个QTableWidgetItem对象保存输入的文本。

对于Qt 类前面已经介绍的很详细了,在本篇文章中就不多介绍了。那么本文讲述的内容是关于Subclassing QTableWidgetQTableWidget继承。QTableWidget是一个表示二维离散数组的表格。它在给定维度里显示当前用户滚动的单元格。当用户在一个空的单元格中输入一些文本时,QTableWidget自动创建一个QTableWidgetItem对象保存输入的文本。

现在我们来实现这个类,首先是头文件spreadsheet.h,首先前向声明两个类Cell和SpreadsheetCompare。

  1. #ifndef SPREADSHEET_H  
  2. #define SPREADSHEET_H  
  3. #include <QTableWidget> 
  4. class Cell;  
  5. class SpreadsheetCompare;  
  6. class Spreadsheet : public QTableWidget{     
  7.    Q_OBJECTpublic:      
  8.       Spreadsheet(QWidget *parent = 0);      
  9.       bool autoRecalculate() const { return autoRecalc; }//内联函数      
  10.       QString currentLocation() const;      
  11.       QString currentFormula() const;      
  12.       QTableWidgetSelectionRange selectedRange() const;      
  13. void clear();      
  14.       bool readFile(const QString &fileName);      
  15.       bool writeFile(const QString &fileName);     
  16.       void sort(const SpreadsheetCompare &compare);  
  17. public slots:     
  18.     void cut();      
  19.     void copy();      
  20.     void paste();      
  21.     void del();      
  22.     void selectCurrentRow();      
  23.     void selectCurrentColumn();      
  24.     void recalculate();      
  25.     void setAutoRecalculate(bool recalc);      
  26.     void findNext(const QString &str, Qt::CaseSensitivity cs);      
  27.     void findPrevious(const QString &str, Qt::CaseSensitivity cs);signals:      
  28.     void modified();private slots:     
  29.     void somethingChanged();  
  30. private:      
  31.     enum { MagicNumber = 0x7F51C883RowCount = 999ColumnCount = 26 };      
  32.     Cell *cell(int row, int column) const;      
  33.     QString text(int row, int column) const;      
  34.     QString formula(int row, int column) const;      
  35.     void setFormula(int row, int column, const QString &formula);      
  36.     bool autoRecalc;};class SpreadsheetCompare{public:      
  37.     bool operator()(const QStringList &row1,                      
  38.     const QStringList &row2) const;     
  39.    enum { KeyCount = 3 };      
  40.      int keys[KeyCount];      
  41.       bool ascending[KeyCount];  
  42. };  
  43. #endif 

文本,对齐等这个QTableWidget单元格的属性存储在QTableWidgetItem类里。QTableWidgetItem类不是一个控件类,而是一个单纯保存数据的类。

实现MainWindow类的时候我们用到了Spreadsheet的一些公有函数。如在MainWindow::newFile中调用clear()将表格置空。我们也用到了QTableWidget继承来的一些函数,如setCurrentCell()和setShowGrid()就多次调用过。

 #p#

Spreadsheet提供了很多槽函数来相应Edit,Tools和Options等菜单的动作。信号modified()在表格发生变化时给出通知。私有槽函数somethingChanged()在Speadsheet类内部使用。

在类的私有部分,我们声明了三个常数,四个函数和一个变量。在头文件的最后定义了类SpreadsheetCompare

现在我们看一下源文件 spreadsheet.cpp:

  1. #include <QtGui> 
  2. #include "cell.h"  
  3. #include "spreadsheet.h"  
  4. Spreadsheet::Spreadsheet(QWidget *parent)  
  5.     : QTableWidget(parent)  
  6. {  
  7.     autoRecalc = true;  
  8.     setItemPrototype(new Cell);  
  9.     setSelectionMode(ContiguousSelection);  
  10.     connect(this, SIGNAL(itemChanged(QTableWidgetItem *)),  
  11.             this, SLOT(somethingChanged()));  
  12.     clear();  
  13. }  
  14. void Spreadsheet::clear()  
  15. {  
  16.     setRowCount(0);  
  17.     setColumnCount(0);  
  18.     setRowCount(RowCount);  
  19.     setColumnCount(ColumnCount);  
  20.     for (int i = 0; i < ColumnCount; ++i) {  
  21.         QTableWidgetItem *item = new QTableWidgetItem;  
  22.         item->setText(QString(QChar('A' + i)));  
  23.         setHorizontalHeaderItem(i, item);  
  24.     }  
  25.     setCurrentCell(0, 0);  
  26. }  
  27. Cell *Spreadsheet::cell(int row, int column) const  
  28. {  
  29.     return static_cast<Cell *>(item(row, column));  
  30. }  
  31. QString Spreadsheet::text(int row, int column) const  
  32. {  
  33.     Cell *c = cell(row, column);  
  34.     if (c) {  
  35.         return c->text();  
  36.     } else {  
  37.         return "";  
  38.     }  
  39. }  
  40. QString Spreadsheet::formula(int row, int column) const  
  41. {  
  42.     Cell *c = cell(row, column);  
  43.     if (c) {  
  44.         return c->formula();  
  45.     } else {  
  46.         return "";  
  47.     }  
  48. }  
  49. void Spreadsheet::setFormula(int row, int column,  
  50.                              const QString &formula)  
  51. {  
  52.     Cell *c = cell(row, column);  
  53.     if (!c) {  
  54.         c = new Cell;  
  55.         setItem(row, column, c);  
  56.     }  
  57.     c->setFormula(formula);  
  58. }  
  59. QString Spreadsheet::currentLocation() const  
  60. {  
  61.     return QChar('A' + currentColumn())  
  62.            + QString::number(currentRow() + 1);  
  63. }  
  64. QString Spreadsheet::currentFormula() const  
  65. {  
  66.     return formula(currentRow(), currentColumn());  
  67. }  
  68. void Spreadsheet::somethingChanged()  
  69. {  
  70.     if (autoRecalc)  
  71.         recalculate();  
  72.     emit modified();  

通常,用户在一个空的单元格中输入文本时,QTableWidget将会自动创建 QTableWidgetItem对象来保存这些文本。然而在 spreadsheet程序中,我们通过创建Cell 代替QTableWidgetItem。在构造函数中,通过调用setItemProtoType()来实现。实际上是每次当需要创建一个新的项目时,QTableWidget 拷贝传递给setItemProtoType() 函数中的项目。

#p#

在构造函数中,我们设置选择方式QAbstractItemView::ContiguousSelection允许单一的矩形选择。连接表格控件的信号itemChanged()和私有的somethingChanged()槽函数,这样当用户编辑了一个单元格时,somethingChanged()能够被调用。最后,我们调用clear()清空表格,设置列标头。

在构造函数中调用 clear()用来初始化表格。在MainWindow::newFile() 中也调用了这个函数。本来可以使用函数QTableWidget::clear()清除所有项和选择,但这样不能改变当前大小的标题头。因此我们首先把表格重新定义为 0×0,这样全部清除了表格和标题头。然后把表格重新定义为ColumnCount×RowCount(26× 999),让水平标题头为QTableWidgetItem 类型,文本为"A"到"Z "。垂直标题栏会自动设置为1,2,到999。最后把光标移动到 A1。

QTableWidget由几个子控件组成。它在最上面有一个水平的QHeaderView,最左边有一个垂直的QHeaderView和两个QScrollBars。中间区域是一个特殊的viewport控件,这个控件可以显示网格。这些子控件可以通过QTableView和QAbstractScrollArea的函数进行操作。QAbstractScrollArea提供了一个可以滚动的viewport和两个滚动条。它的子类是 QScrollArea。

关于Subclassing QTableWidget中QTableWidget继承

在 Items中保存数据:

在 Spreadsheet应用程序中,每一个非空的单元格都作为一个独立的 QTableWidgetItem对象被存放在内存中。这种在 Item中保存数据的方法被QListWidget 和QTreeWidget所采用,对应这两个控件的Item类分别为QListWidgetItem和QTreeWidgetItem。

Qt的Item类还可以作为数据存储器使用。比如,QTableWidgetItem也保存了一些属性如文本,字体,颜色,图标等,还有一个指向QTableWidget的指针。这个Item还可以保存QVariant类型的数据,包括注册的自定义类型。从这个类派生子类,我们还可以提供其他功能。

其他的工具是在它们的 item类中提供一个空指针来保存用户数据。在 Qt中更加好用的方法是使用setData() ,把QVariant类型的数据保存起来。如果需要一个空类型指针,也可以从item类派生,在派生类中添加一个空类型指针成员变量。

对于那些更为复杂的数据处理,如大量的数据,复杂的数据项,数据库数据和多种数据显示方式,Qt提供了一套model/view类将数据和显示分离出来,第十章介绍了这个特性。

私有函数 cell()返回指定的行数和列数的Cell对象。它和QTableWidget::item()是一样的,只是它返回的是Cell类型的指针,QTableWidget::item()返回的是QTableWidgetItem类型的指针。
私有函数 text()返回指定的单元格的文本。如果cell() 返回空指针,该单元格为空,则返回空字符。

函数 formula()返回的是单元格的公式。大多数情况下,单元格的公式和文本是一样的。例如,公式" hello"和字符"hello"是一样的,如果用户输入了"hello",网格的文本就显示为hello。但是下面会是例外:

1、如果公式是一个数字,那么单元格的文本也是数字。

2、如果公式是单引号开头,公式的其他部分就是文本。如公式'12345,等价于串就是"12345" 。

3、如果公式由等号"="开头,代表一个数学公式。如果A1为12, A2为6,那么公式"=A1+A2 "就是18。

把公式转换为值的任务是由类 Cell完成的。此时需要记住的是单元格中显示的文本是经过公式计算的结果,而不是公式本身。

私有函数 setFormula()用来给一个指定的单元格设置公式。如果该单元格有 Cell对象,那就使用这个对象。否则,我们创建一个新的 Cell对象,然后我们调用QTableWidget::setItem() 函数把它插入到表格中,最后调用单元格自己的setFormula()函数,在单元格上显示公式结果。我们不用删除Cell对象,在适当的时候,QTableWidget会自动删除这些对象。

函数 currentLocation()返回当前单元格的位置,字母显示的列和行号,被 MainWindow::updateStatusBar()调用在状态条上显示位置。

函数 currentFormula()返回当前单元格的公式。 MainWindow::updateStatusBar()调用了这个函数。

私有槽函数 somethingChanged()中,如果 auto-recalculate为真,那么重新计算整个表格。然后发送 modified()信号。

小结:想了解Qt更多的类,请到网上搜集就可以。关于Subclassing QTableWidget中从QTableWidget继承的内容介绍完了。希望本文对你有帮助!

【编辑推荐】

新手须知 QT类大全

在 Qt学习 QTableItem 类

PyQt学习笔记之QTableWidget

QT中建立Python GUI应用程序

利用Qt绘图实现QWT绘制科学图表

责任编辑:zhaolei 来源: 互联网
相关推荐

2011-06-30 16:38:07

Qt QTableWidg

2011-06-15 11:09:48

Qt PyQt

2011-06-30 14:34:17

QT Tablewidge QTableWidg

2009-08-27 16:30:10

interface继承

2009-06-18 09:51:25

Java继承

2011-06-16 11:01:56

PHP继承

2023-05-09 12:42:51

Java继承多态

2017-02-06 13:31:19

Android样式继承关系

2011-07-15 15:47:02

JAVA

2022-12-14 09:10:06

JAVA注解继承

2009-10-23 13:40:09

VB.NET基类

2009-07-14 17:36:28

Jython的继承

2011-07-08 10:25:55

JavaScript

2011-07-14 11:08:30

C#继承

2010-06-18 15:15:13

UML

2009-07-02 13:25:00

消除实现继承面向接口编程Java

2020-03-02 00:32:08

Python列表for循环

2013-08-13 13:31:34

AndroidAsyncTaskcancel

2011-08-24 13:56:27

JavaScript

2017-08-03 15:54:50

Kotlin继承
点赞
收藏

51CTO技术栈公众号