5-4 双缓冲技术(Double Buffering)(5、类PlotSettings实现)

 
下面是PlotSettings的实现:
PlotSettings::PlotSettings()
{
    minX = 0.0;
    maxX = 10.0;
    numXTicks = 5;
    minY = 0.0;
    maxY = 10.0;
    numYTicks = 5;
}
在构造函数中,把两个坐标轴的初始化为从0到10,分为5个刻度。
void PlotSettings::scroll(int dx, int dy)
{
    double stepX = spanX() / numXTicks;
    minX += dx * stepX;
    maxX += dx * stepX;
    double stepY = spanY() / numYTicks;
    minY += dy * stepY;
    maxY += dy * stepY;
}
函数scroll()增加或者减少minX,maxX,minY,maxY的值,放大或缩小控件的尺寸为给定的偏移值乘以坐标刻度的两倍。这个函数在Plotter::keyPressEvent()函数中调用。
void PlotSettings::adjust()
{
    adjustAxis(minX, maxX, numXTicks);
    adjustAxis(minY, maxY, numYTicks);
}
函数adjust()在Plotter::mouseReleaseEvent()中调用。重新计算minX,maxX,minY,maxY的值,重新得到坐标轴刻度的个数。私有函数adjustAxis()一次计算一个坐标轴。
void PlotSettings::adjustAxis(double &min, double &max,
                              int &numTicks)
{
    const int MinTicks = 4;
    double grossStep = (max - min) / MinTicks;
    double step = pow(10.0, floor(log10(grossStep)));
    if (5 * step < grossStep) {
        step *= 5;
    } else if (2 * step < grossStep) {
        step *= 2;
    }
    numTicks = int(ceil(max / step) - floor(min / step));
    if (numTicks < MinTicks)
        numTicks = MinTicks;
    min = floor(min / step) * step;
    max = ceil(max / step) * step;
}
函数adjustAxis()修正minX,maxX,minY,maxY的值,根据给定的最大最小范围值计算刻度的个数。函数修改了参数的值(成员变量的值),所以没有使用常引用。
前部分代码主要是确定坐标轴上单位刻度的值(step)。为了得到合理的刻度数,必须得到准确的步长值。例如,一个坐标轴步长为3.8,坐标轴上其他的刻度值都是3.8的倍数,在用户很不习惯,对于一个整数坐标值,合理的步长应给为10 n, 2·10 n, 或者5·10 n
首先我们计算最大步长(gross step),然后计算小于或者等于这个步长的 10n,通过计算这个步长的以十为底的对数,然后计算这个值的10次方。例如,如果最大步长为236,log (236)为2.37291…,四舍五入为2,得到10 2 = 100作为候选的步长值。
有了第一个值以后,我们再继续计算其他的候选值2·10 n 和 5·10 n。如上例中,另外两个可能的值为200和500。500大于最大的步长值不能使用,200小于236,使用200作为步长的值。
接着计算刻度数,min和max就很容易了。新的min值为原来的min值和步长乘积的较小整数值,新的max为原来的max值和步长乘积的较大整数值。新的numTicks为新的min和max的间隔数。例如,输入的min值为240,max为1184,新的值就会变成200,1200,200为步长,就有numTicks值为5;
有时这个算法并不是最优的。一个更加复杂的算法是Paul S. Heckbert在Graphics Gem上发表的一篇名为“Nice Numbers for Graph Labels”(ISBN 0-12-286166-3)
这一章是第一部分的最后一章。介绍了怎样从现有的Qt控件基础上得到一个新的控件,和以QWidget作为基类得到一个新的控件。在第二章我们看到了怎么在一个控件中对其他控件进行组合,在第六章中我们将会继续介绍。
到此为止,我们已经介绍了很多Qt GUI编程方面的知识。在第二部分和第三部分中,我们将会深入介绍Qt编程的其他方面。
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值