Qt4_实现其他菜单

实现其他菜单

我们将要实现对Tools和Options菜单做出响应的槽。
在这里插入图片描述

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()把它们标记为需要重新计算。为了在电子制表软件中显示一个Cell对象的值,QTableWidget会再次对该对象调用text()以获得其值,从而使该值重新计算一次。

然后,对这个视口调用update()来重新绘制整个电子制表软件。QTableWidget 中的重绘代码就又会对每一个可见单元格调用text()来获得它们中要显示的值。因为在每一个单元格上都调用了setDirty(),所以这些对text()的调用将会使用重新计算过的值。该计算可能需要重新计算那些不可见的单元格,这就会造成一个级联计算,直到每一个需要被重新计算的单元格能够在刚才刷新过的视口中重新得到计算,从而使它们也能够显示正确的文本。这一计算是由Cell类执行的。

void Spreadsheet::setAutoRecalculate(bool recalc)
{
    autoRecalc = recalc;
    if (autoRecalc)
        recalculate();
}

setAutoRecalculate()槽对Options->Auto-Recalculate菜单选项做出响应。如果启用了这个特性,则会立即重新计算整个电子制表软件以确保它是最新的,然后,recalculate()会自动在somethingChanged()中得到调用。

因为QTableWidget已经提供了一个从QTableView 中继承而来的setShowGrid()槽,所以不需要再对Options->Show Grid菜单选项编写任何代码。所有要保留的东西就是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对象中的排序键和排序顺序重新排列这些行。我们使用一个QStringList来重新表示每一行数据,并且把该选择存储在一个行列表中。我们使用Qt的qStableSort()算法,并且根据公式而不是根据值来进行简单排序。
在这里插入图片描述
qStableSort()函数可以接受一个开始迭代器、一个终止迭代器和一个比较函数。这个比较函数是一个带两个参数(两个QStringList)的函数,并且如果第一个参数"小于"第二个参数,它就返回true,否则返回falsle。传递的作为比较函数的这个compare对象并不是一个真正的函数,但是它可以用作一个函数,将会很快看到这一点。

在执行完qStableSort()之后,我们把数据移回到这个表中,接着清空这一选择,并且调用somethingChanged()函数。

在这个头文件的最后,给出了SpreadsheetCompare类的定义

class SpreadsheetCompare
{
public:
    bool operator()(const QStringList &row1,
                    const QStringList &row2) const;

    enum { KeyCount = 3 };
    int keys[KeyCount];
    bool ascending[KeyCount]; 
};

SpreadsheetCompare类有些特殊,因为它实现了一个"()"操作符。这样就允许把这个类像函数一样使用。把这样的类称为函数对象(function object),或者称为仿函数(functor)。

为了理解仿函数是如何工作的,首先从一个简单的例子开始:

class Square :
{
pubtic:
	int operator()(int x) const { return x* x; }
}

Square类提供了一个函数,operator()(int)函数,它返回其参数的平方值。通过把这个函数命名为operator()(int),而不是将其命名为compute(int)之类的函数,就可以把一个类型Square的对象当作一个函数。

Square square;
int y = square(5); //y equals 25

现在,让我们来看一个包括 SpreadsheetCompare的实例:

QStringList row1, row2;
SpreadsheetCompare compare;
...
if(compare(row1, row2)){
   //row1 is less than row2
}

使用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;
}

如果第1行小于第2行,该仿函数就返回true;否则,就返回false。 qStableSort()函数会使用这个函数的结果来执行排序操作。

SpreadsheetCompare对象的key与ascending数组和MainWindow::sort()函数一起配合使用。每个键都保存一个列索引,或者- 1(为"None"时)。

我们按键顺序比较两行中相应的单元格条目。一旦发现有不同之处,就返回一个适当的true或者false值。如果所有的比较关系都证明两者是相等的,就返回false。qStableSort()函数会使用这里给出的顺序来解决这种平局情形。如果一开始的时候row1在row2之前,并且它们都不"小于"对方,那么,在结果中row1还在row2前面。这就是qStableSort()与它很相似的非稳定版本的qSort()函数之间的区别。

现在已经完成了这个Spreadsheet类。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阳光开朗男孩

你的鼓励是我最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值