(转)5.4 双缓冲技术(Double Buffering)-4

来源:互联网 发布:软件开发工程师前景 编辑:程序博客网 时间:2024/05/20 19:18

(转)5.4 双缓冲技术(Double Buffering)-4

标签: qtalignment网格plotjava
2422人阅读 评论(0)收藏举报
本文章已收录于:
分类:
作者同类文章X
    以下是私有函数的实现: 

    void Plotter::updateRubberBandRegion()

    {

        QRect rect = rubberBandRect.normalized();

        update(rect.left(), rect.top(), rect.width(), 1);
        update(rect.left(), rect.top(), 1, rect.height());
        update(rect.left(), rect.bottom(), rect.width(), 1);
        update(rect.right(), rect.top(), 1, rect.height());
    }
    函数updateRubberBand()在mousePressEvent(),mouseMoveEvent()和mouseReleaseEvent()中被调用,用来删除或者重新绘制橡皮线。函数中调用了四次update(),用四个绘制事件完成由橡皮线(两条垂直和水平的线)组成的四个小矩形的绘制。Qt也提供了一个类QRubberBand用来绘制橡皮线,但是控件自己提供的绘制函数会更好
    void Plotter::refreshPixmap()
    {
        pixmap = QPixmap(size());
        pixmap.fill(this, 0, 0);
        QPainter painter(&pixmap);
        painter.initFrom(this);
        drawGrid(&painter);
        drawCurves(&painter);
        update();
    }
    函数refreshPixmap()把plot绘制到图片上,并且更新显示。首先我们把图片的大小调整为和当前控件大小相同,然后用控件的背景颜色填充整个图片。这个颜色是当前调色版的“dark”部分,因为在Plotter构造函数中调用setBackgroundRole() 。如果背景用的刷子是非实心的(solid brush,刷子的样式,只有颜色,没有花纹的那种最简单的),QPixmap::fill()需要知道控件中刷子的偏移量,以便图片对齐刷子模式。这里图片对应整个控件,因此偏移位置为(0,0)。
    接下来我们创建了一个QPainter对象来绘制图片,QPainter::initFrom()设置绘制图片所需画笔,背景和字体,参数this表示这些设置和Plotter控件的相应设置是一致的。然后我们调用drawGrid(),drawCurves()绘制网格和曲线。最后,update()函数安排整个控件的绘制事件,在painteEvent()函数中把图片拷贝到控件上。
    void Plotter::drawGrid(QPainter *painter)
    {
       QRect rect(Margin, Margin,
                   width() - 2 * Margin, height() - 2 * Margin);
        if (!rect.isValid())
            return;
        PlotSettings settings = zoomStack[curZoom];
        QPen quiteDark = palette().dark().color().light();
        QPen light = palette().light().color();
        for (int i = 0; i <= settings.numXTicks; ++i) {
            int x = rect.left() + (i * (rect.width() - 1)
                                     / settings.numXTicks);
            double label = settings.minX + (i * settings.spanX()
                                              / settings.numXTicks);
            painter->setPen(quiteDark);
            painter->drawLine(x, rect.top(), x, rect.bottom());
            painter->setPen(light);
            painter->drawLine(x, rect.bottom(), x, rect.bottom() + 5);
            painter->drawText(x - 50, rect.bottom() + 5, 100, 15,
                              Qt::AlignHCenter | Qt::AlignTop,
                              QString::number(label));
        }
        for (int j = 0; j <= settings.numYTicks; ++j) {
            int y = rect.bottom() - (j * (rect.height() - 1)
                                       / settings.numYTicks);
            double label = settings.minY + (j * settings.spanY()
                                              / settings.numYTicks);
            painter->setPen(quiteDark);
            painter->drawLine(rect.left(), y, rect.right(), y);
            painter->setPen(light);
            painter->drawLine(rect.left() - 5, y, rect.left(), y);
            painter->drawText(rect.left() - Margin, y - 10, Margin - 5, 20,
                              Qt::AlignRight | Qt::AlignVCenter,
                              QString::number(label));
        }
        painter->drawRect(rect.adjusted(0, 0, -1, -1));
    }
    函数drawGrid()在坐标轴和曲线的下面绘制网格。这个区域由一个矩形确定,如果控件太小,则不绘制立即返回。第一个循环绘制网格的垂直线,及沿x坐标轴的刻度。第二个循环绘制网格的水平线,及沿y坐标轴的刻度。最后,沿边界绘制一个矩形。drawText()绘制数字,对应两个坐标轴上刻度的标记。
    函数painter->drawText()语法如下:
    painter->drawText(x, y, width, height, alignment, text);
    其中(x,y,width,height)所确定的矩形,alignment确定文字在矩形中的位置。
    void Plotter::drawCurves(QPainter *painter)
    {
        static const QColor colorForIds[6] = {
            Qt::red, Qt::green, Qt::blue, Qt::cyan, Qt::magenta, Qt::yellow
        };
        PlotSettings settings = zoomStack[curZoom];
        QRect rect(Margin, Margin,
                   width() - 2 * Margin, height() - 2 * Margin);
        if (!rect.isValid())
            return;
        painter->setClipRect(rect.adjusted(+1, +1, -1, -1));
        QMapIterator<int, QVector<QPointF> > i(curveMap);
        while (i.hasNext()) {
            i.next();
            int id = i.key();
            const QVector<QPointF> &data = i.value();
            QPolygonF polyline(data.count());
            for (int j = 0; j < data.count(); ++j) {
                double dx = data[j].x() - settings.minX;
                double dy = data[j].y() - settings.minY;
                double x = rect.left() + (dx * (rect.width() - 1)
                                             / settings.spanX());
                double y = rect.bottom() - (dy * (rect.height() - 1)
                                               / settings.spanY());
                polyline[j] = QPointF(x, y);
            }
            painter->setPen(colorForIds[uint(id) % 6]);
            painter->drawPolyline(polyline);
        }
    }
    函数drawCurves()在网格的上层绘制曲线。调用了QPainter::setClipRect()函数设置QPainter的剪切区域为包含曲线的矩形区域(不包括四周的间隙和图片的外框)。QPainter会忽略这个区域外的象素。
    然后我们使用Java风格的迭代器,遍历所有的曲线,对每一条曲线,遍历它所有的QPointF点。函数key()得到曲线的id,value()函数得到曲线的QVector<QPointF>类型的数据。内层循环把每个QPointF记录的plotter坐标转换为控件坐标,把结果保存在polyline变量中。
    转换坐标后,我们设置画笔的颜色(使用函数前面预定义的颜色),调用drawPolyline()绘制曲线,经过所有的曲线上的点。
    1
    0
     
     

    我的同类文章

    http://blog.csdn.net
    • (转)利用Qt的qmake创建vc工程2009-08-28
    • (转)QT中画图方法的不同2009-06-18
    • (转)5.4 双缓冲技术(Double Buffering)-32008-05-20
    • (转)双缓冲技术12008-05-20
    • (转)5.2从QWidget派生(Subclassing QWidget)2008-05-12
    • (转)QT事件机制2009-06-20
    • (转)5.4 双缓冲技术(Double Buffering)-52008-05-20
    • (转)5.4 双缓冲技术(Double Buffering)-22008-05-20
    • (转) 5.3把自定义控件集成到Qt Designer中(Integrating Custom Widgets with Qt Designer)2008-05-12
    • (转)5.1自定义Qt控件(Customizing Qt Widgets)2008-05-12
    更多文章
    0 0
    原创粉丝点击