第四章 实现应用程序的功能
前两章说明了如何创建Spreadsheet应用程序的用户界面。在这一章中,将通过编写它的底层功能函数来完成这个程序。此外,还将看到如何载入和保存文件,如何在内存中存储数据,如何实现剪贴板操作,以及如何向QTableWidget中添加对电子制表软件公式的支持等功能。
4.1 中央窗口部件
QMainWindow的中央区域可以被任意种类的窗口部件所占用。下面给出的是对所有可能情形的概述。
1、使用一个标准的Qt窗口部件
像QTableWidget或者QTextEdit这样的标准窗口部件可以用作中央窗口部件。在这种情况下,这个应用程序的功能,如文件的载入和保存,必须在其他地方实现(例如,在QMainWindow的子类中)。
2、使用一个自定义窗口部件
特殊的应用程序通常需要在自定义窗口部件中显示数据。例如,一个图标编辑器程序就应当使用一个IconEditor窗口部件作为自己的中央窗口部件。第5章将会说明如何在Qt中编写自定义窗口部件。
3、使用一个带布局管理器的普通QWidget
有时,应用程序的中央区域会被许多窗口部件所占用。这时可以通过使用一个作为所有这些其他窗口部件父对象的QWidget,以及通过使用布局管理器管理这些子窗口部件的大小和位置来完成这一特殊情况。
4、使用切分窗口(splitter)
多个窗口部件一起使用的另一种方法是使用QSplitter。 QSplitter会在水平方向或者竖直方向上排列它的子窗口部件,用户可以利用切分条(splitter handle)控制它们的尺寸大小。切分窗口可以包含所有类型的窗口部件,包括其他切分窗口。
5、使用多文档界面工作空间
如果应用程序使用的是多文档界面,那么它的中央区域就会被QMdiArea窗口部件所占据,并且每个多文档界面窗口都是它的一个子窗口部件。
布局、切分窗口和多文档界面工作空间都可以与标准的Qt窗口部件或者自定义窗口部件组合使用。第6章将会进一步深入地讲解这些类。对于Spreadsheet应用程序,会使用一个QTableWidget子类作为它的中央窗口部件。类QTableWidget已经提供了我们所需要的绝大多数电子制表软件的功能,但是它还不支持剪贴板操作,并且也不能理解诸如“= A1+A2+A3"这样的电子制表软件公式的意义。我们将会在Spreadsheet 类中实现这些缺少的功能。
4.2 子类化QTableWidget
类Spreadsheet派生自QTableWidget,如图4.1 所示。QTableWidget是一组格子,可以非常有效地用来表达二维稀疏数组。它可以在规定的维数内显示用户滚动到的任一单元格。当用户在一个空单元格内输入一些文本的时候,QTableWidget会自动创建一个用来存储这些文本的QTableWidgetItem。QTableWidget派生自QTableView ,它是模型/视图类之一,我们将在第10章进一步了解它。
//Spreadsheet.h
#ifndef SPREADSHEET_H
#define SPREADSHEET_H
#include <QTableWidget>
class Cell;
class SpreadsheetCompare;
/* 头文件是从Cell和SpreadsheetCompare 类的前置声明开始的。
* QTableWidget单元格的属性,比如它的文本和对齐方式等,都存储在QTableWidgetItem中。
* 与QTableWidget不同的是,QTableWidgetItem不是一个窗口部件类,而是一个纯粹的数据类。
* Cell类派生自QTableWidgetltem,会在本章的最后一节对这个Cell类进行解释。
*/
class Spreadsheet : public QTableWidget
{
Q_OBJECT
public:
Spreadsheet(QWidget *parent = 0);
bool autoRecalculate() const {
return autoRecalc; }
QString currentLocation() const;
QString currentFormula() const;
QTableWidgetSelectionRange selectedRange() const;
void clear();
bool readFile(const QString &fileName);
bool writeFile(const QString &fileName);
void sort(const SpreadsheetCompare &compare);
/* 之所以把autoRecalculate()函数实现为内联函数,是因为无论自动重新计算的标识符生效与否,它都必须要有返回值。
* 在第3章中,当实现MainWindow时,我们依赖于Spreadsheet中的一些公有函数。
* 例如,我们从MainWindow::newFile()中调用clear()来重置电子制表软件。
* 也使用了一些从QTableWidget中继承而来的函数,特别是setCurrentCell()和setShowGrid()。
*/
public slots:
void cut();
void copy();
void paste()