现在的位置: 首页 > 综合 > 正文

(转)4.5实现其它菜单

2013年01月30日 ⁄ 综合 ⁄ 共 3839字 ⁄ 字号 评论关闭
在这一节我们将会实现Tools和Options菜单的相应槽。
Figure 4.7. The Spreadsheet application's Tools and Options menus

void Spreadsheet::recalculate()

{

    for (int row = 0; row < RowCount; ++row) {
        for (int column = 0; column < ColumnCount; ++column) {
            if (cell(row, column))
                cell(row, column)->setDirty();
        }
    }
    viewport()->update();
}
槽函数recalculate()对应Tools|Recalculate菜单,当有必要时Spreadsheet也会自动调用这个函数。遍历所有的行和列,在每一个单元格上调用setDirty()给他们设置重新计算的状态,然后QTableWidget在每一个单元格上调用text()函数重新在表格中更新单元格显示值,这个值是重新计算过的。
调用视图的update()重新绘制表格。QTableWidget的重绘代码中会在每一个可见单元格上调用text()函数得到需要显示的值,因为前面调用过setDirty(),所以显示值会重新计算。计算时也可能需要其他不可见单元格项的值,这些不可见单元格的值也会重新计算。这个计算是由Cell类实现的。
void Spreadsheet::setAutoRecalculate(bool recalc)
{
    autoRecalc = recalc;
    if (autoRecalc)
        recalculate();
}
上面这个槽函数对应了菜单Options|Auto-Recalculate。如果它设置为开,那么立即重新计算全部表格更新。在程序运行的其他时间,如果somethingChanged(),recalculate()也会自动被调用。
我们不需要为菜单Options|Show Grid写任何代码,因为QTableWidget有setShowGrid()槽,它是从QTableView继承的,已经为我们实现了。需要实现的是Spreadsheet::sort(),由MainWindow::sort()调用。
void Spreadsheet::sort(const SpreadsheetCompare &compare)
{
    QList<QStringList> rows;
    QTableWidgetSelectionRange range = selectedRange();
    int i;
    for (i = 0; i < range.rowCount(); ++i) {
        QStringList row;
        for (int j = 0; j < range.columnCount(); ++j)
            row.append(formula(range.topRow() + i,
                                range.leftColumn() + j));
        rows.append(row);
    }
    qStableSort(rows.begin(), rows.end(), compare);
    for (i = 0; i < range.rowCount(); ++i) {
        for (int j = 0; j < range.columnCount(); ++j)
            setFormula(range.topRow() + i, range.leftColumn() + j,
                        rows[i][j]);
    }
    clearSelection();
    somethingChanged();
}

对当前选择排序,根据保存在compare对象里的排序Key及排序次序,来对各行进行重新排序。我们把每一行的数据用QStringList的形式保存在列表中,为了简单起见,我们使用了QtqStableSort()算法,并且只对公式排序而不是对值排序。Qt的标准算法和数据结构在第十一章介绍。 

 

Figure 4.8. Storing the selection as a list of rows
 
函数qStableSort()接受一个起始遍历器和一个结束遍历器和一个比较函数。这个比较函数有两个参数(两个字符串),如果第一个参数小于第二个,返回true,否则返回false。我们传递的比较对象作为比较函数实际不是一个函数,但是它当函数使用
Figure 4.9. Putting the data back into the table after sorting
 

用qStableSort()排序后,把数据再写回到表格中,清空选择集,然后调用somethingChanged()。
在spreadsheet.h中,我们这样定义SpreadsheetCompare类:
class SpreadsheetCompare
{
public:
    bool operator()(const QStringList &row1,
                    const QStringList &row2) const;
    enum { KeyCount = 3 };
    int keys[KeyCount];
    bool ascending[KeyCount];
};
类SpreadsheetCompare的特殊地方是它实现了一个()操作符重载。这允许我们把类作为一个函数使用,这样的类被称为函数类(functors)。为了理解这个函数类的工作情况,首先举一个简单的例子:
class Square
{
public:
    int operator()(int x) const { return x * x; }
}
Square类只提供一个函数,operator()(int)。返回其参数int的平方。把这个函数命名为operator()(int)而不是其他如compute(int)这样子,我们可以得到一个特殊的用途,可以把这个类的对象象函数一样使用。
Square square;
int y = square(5);
现在我们看一个使用SpreassheetCompare的例子:
QStringList row1, row2;
QSpreadsheetCompare compare;
...
if (compare(row1, row2)) {
    // row1 is less than row2
}
这个compare对象就想一个compare()函数一样,另外我们还可以得到所有的排序关键字和排序顺序,它们做为数据成员保存在compare对象中。
另一个实现的方式就是在全局变量中保存排序键和排序顺序信息,直接使用比较函数compare()。但是使用全局变量进行交流在程序设计中是不提倡的,这有可能导致一些问题。函数类在使用模板函数qStableSort()交换信息时是一个更有效的方式。
下面是这个操作符函数的实现:
bool SpreadsheetCompare::operator()(const QStringList &row1,
                                    const QStringList &row2) const
{
   for (int i = 0; i < KeyCount; ++i) {
        int column = keys[i];
        if (column != -1) {
            if (row1[column] != row2[column]) {
                if (ascending[i]) {
                    return row1[column] < row2[column];
                } else {
                    return row1[column] > row2[column];
                }
            }
        }
    }
    return false;
}
如果第一个行小于第二行,函数返回TRUE,否则返回FALSE。qStableSort()函数就使用这个结果执行排序操作。
SpreadsheetCompare对象中的keysascending数组是在MainWindow::sort()中初始化的。每一个键都包含一个列索引,或者为-1(空值)。
我们按照顺序对每个key比较两行中的相应的单元格对象。只要发现不同,就返回true或者false。如果两行都相等,也返回false。qStableSort()使用排序前的顺序解决这个问题。如果排序前的顺序是row1和row2,且经比较相等,在结果中row1始终就排在row2前面。这就是qStableSort()和qSort()之间的不同。
我们已经实现了类Spreadsheet。在下一节中我们实现Cell类。这个类用来存贮单元格项的公式,重新实现了QTableWidgetItem::data()函数,Spreadsheet间接调用了这个函数,通过QTableWidgetItem::text()函数,显示单元格的公式计算出的结果。本。

抱歉!评论已关闭.