双缓冲是一种图形用户界面编程技术,它包括把一个窗口部件渲染到一个脱屏像素映射中以及把这个像素映射复制到显示器上。Qt的早期版本用于 消除屏幕闪烁以及提供一个漂亮的用户界面。
Qt4开始QWidget会自己解决窗口闪烁的问题,但是如果窗口部件的绘制方非常复杂并且需要连续重复绘制时,明确指定双缓冲则非常有用。把窗口部件固定不变的存储为一个像素映射,为绘制做准备,当想要做一些小的改动时,并不需要对整个窗口部件重复绘制和计算,从而显得特别有用的嘞!!
(建议各种自定义窗口部件使用第三方库,QWT之类的。)
说了这么多,实际上所谓的双缓冲技术就是...就是...
先把所有需要绘制或者更新的内容绘制 到QPixmap上,比如drawLine之类的;
然后,再把QPixmap绘制到QWidget上面显示。=-=
Plotter窗口部件可以按照给定的矢量坐标绘制一条或者多条曲线。用户可以再图像中拖拽选择框进行放大,借此解释双缓冲技术。
Pltter窗口部件可以保存任意条曲线的数据。他还维护着一个PlotSetting堆栈对象,而这每一个堆栈对象都对应一个缩放级别。
查看这个类,头文件开始:
plotter.h
#ifndef PLOTTER_H
#define PLOTTER_H
#include <QMap>
#include <QPixmap>
#include <QVector>
#include <QWidget>
#include <QToolButton>
#include <QStylePainter>
#include <QStyleOptionFocusRect>
class PlotSettings;
class Plotter : public QWidget
{
Q_OBJECT
public:
Plotter(QWidget *parent = 0);
//三个公有函数用于创建绘图区(plot)
void setPlotSettings(const PlotSettings &settings);
void setCurveData(int id, const QVector<QPointF> &data);
void clearCurve(int id);
//重新实现QWidget的两个函数
QSize minimumSizeHint() const;
QSize sizeHint() const;
public slots:
//槽函数用于响应放大缩小操作
void zoomIn();
void zoomOut();
protected:
//所有需要重新实现的QWidget事件处理器
void paintEvent(QPaintEvent *event);
void resizeEvent(QResizeEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
void keyPressEvent(QKeyEvent *event);
void wheelEvent(QWheelEvent *event);
private:
//绘制窗口不仅的函数、常量等
void updateRubberBandRegion();
void refreshPixmap();
void drawGrid(QPainter *painter);
void drawCurves(QPainter *painter);
enum { Margin = 50 };
QToolButton *zoomInButton;
QToolButton *zoomOutButton;
QMap<int, QVector<QPointF> > curveMap;
QVector<PlotSettings> zoomStack; //保存不同缩放级别设置值
int curZoom; //当前缩放级别索引值
bool rubberBandIsShown;
QRect rubberBandRect;
//这个pixmap和屏幕上显示的图形是相同的
QPixmap pixmap;
};
//PlotSettings类给定了x、y轴范围,以及在这些刻度标记符的数量。
class PlotSettings
{
public:
PlotSettings();
void scroll(int dx, int dy);
void adjust();
double spanX() const { return maxX - minX; }
double spanY() const { return maxY - minY; }
double minX;
double maxX;
int numXTicks;
double minY;
double maxY;
int numYTicks;
private:
static void adjustAxis(double &min, double &max, int &numTicks);
};
#endif
plotter.h
#include <QtGui>
#include <cmath>
#include "plotter.h"
Plotter::Plotter(QWidget *parent)
: QWidget(parent)
{
setBackgroundRole(QPalette::Dark); //设置默认背景色
setAutoFillBackground(true); //