Qt 2D绘图 下载本文

两个例子中都使直线的长度扩大了两倍,但是第一个例子是扩大的画布的坐标系,第二个例子是扩大的窗口的坐标系,你可以看一下它们的效果。 你仔细看一下输出,两个例子中画布的大小都没有变。

如果你看过了我写的那个绘图软件的教程(链接过去),现在你就能明白我在其中讲“问题一”时说的意思了:虽然画布看起来是大了,但是其大小并没有变,其中坐标也没有变。变的是像素的大小或者说像素间的距离。

但是,有一点你一定要搞明白,这只是在QPixmap与QWidget结合时才出现的,是相对的说法。其实利用scale()函数是会让坐标变化的,我们在开始的例子已经证明了。 结论:

现在是不是已经很乱了,一会儿是窗口,一会儿是画布,一会儿坐标变化,一会儿又不变了,到底是怎么样呢?

Qt 2D绘图(九)双缓冲绘图简介

上面一节我们实现了涂鸦板的功能,但是如果我们想在涂鸦板上绘制矩形,并且可以动态地绘制这个矩形,也就是说我们可以用鼠标画出随意大小的矩形,那该怎么办呢?

我们先进行下面的三步,最后引出所谓的双缓冲绘图的概念。 第一步:

我们更改上一节的那个程序的重绘函数。

void Dialog::paintEvent(QPaintEvent *) {

QPainter painter(this); int x,y,w,h;

x = lastPoint.x(); y = lastPoint.y(); w = endPoint.x() – x; h = endPoint.y() – y; painter.drawRect(x,y,w,h); }

然后运行,效果如下。

这时我们已经可以拖出一个矩形了,但是这样直接在窗口上绘图,以前画的矩形是不能保存住的。所以我们下面加入画布,在画布上进行绘图。 第二步:

我们先在构造函数里将画布设置大点:pix = QPixmap(400,400); 然后更改函数,如下:

void Dialog::paintEvent(QPaintEvent *) {

int x,y,w,h;

x = lastPoint.x(); y = lastPoint.y(); w = endPoint.x() – x; h = endPoint.y() – y;

QPainter pp(&pix); pp.drawRect(x,y,w,h); QPainter painter(this);

painter.drawPixmap(0,0,pix); }

这时运行程序,效果如下:

现在虽然能画出矩形,但是却出现了无数个矩形,这不是我们想要的结果,我们希望能像第一步那样绘制矩形,所以我们再加入一个临时画布。 第三步:

首先,我们在dialog.h中的private里添加变量声明: QPixmap tempPix; //临时画布

bool isDrawing; //标志是否正在绘图

然后在dialog.cpp中的构造函数里进行变量初始化: isDrawing = false; 最后更改函数如下:

void Dialog::paintEvent(QPaintEvent *) {

int x,y,w,h;

x = lastPoint.x();

y = lastPoint.y(); w = endPoint.x() – x; h = endPoint.y() – y;

QPainter painter(this);

if(isDrawing) //如果正在绘图 {

tempPix = pix; //将以前pix中的内容复制到tempPix中,这样实现了交互绘图

QPainter pp(&tempPix); pp.drawRect(x,y,w,h);

painter.drawPixmap(0,0,tempPix); } else {

QPainter pp(&pix); pp.drawRect(x,y,w,h);

painter.drawPixmap(0,0,pix); } }

void Dialog::mousePressEvent(QMouseEvent *event) {

if(event->button()==Qt::LeftButton) //鼠标左键按下 {

lastPoint = event->pos(); isDrawing = true; //正在绘图 } }

void Dialog::mouseMoveEvent(QMouseEvent *event) {

if(event->buttons()&Qt::LeftButton) //鼠标左键按下的同时移动鼠标 {

endPoint = event->pos(); update(); } }

void Dialog::mouseReleaseEvent(QMouseEvent *event) {

if(event->button() == Qt::LeftButton) //鼠标左键释放 {

endPoint = event->pos();

isDrawing = false; //结束绘图 update();

} }

我们使用两个画布,就解决了绘制矩形等图形的问题。

其中tempPix = pix;一句代码很重要,就是它,才实现了消除那些多余的矩形。

双缓冲绘图简介:

根据我的理解,如果将第一步中不用画布,直接在窗口上进行绘图叫做无缓冲绘图,那么第二步中用了一个画布,将所有内容都先画到画布上,在整体绘制到窗口上,就该叫做单缓冲绘图,那个画布就是一个缓冲区。这样,第三步,用了两个画布,一个进行临时的绘图,一个进行最终的绘图,这样就叫做双缓冲绘图。 我们已经看到,利用双缓冲绘图可以实现动态交互绘制。其实,Qt中所有部件进行绘制时,都是使用的双缓冲绘图。就算是第一步中我们没有用画布,Qt在进行自身绘制时也是使用的双缓冲绘图,所以我们刚才那么说,只是为了更好地理解双缓冲的概念。

到这里,我们已经可以进行一些Qt 2D绘图方面的设计了。我这里有两个例子,一个是那个Qt涂鸦板程序 ,它是实践了我所讲的这几节的内容,可以说是对这几节内容的一个综合。还有一个例子,就是方块游戏系列 那个是对这些知识的应用。如果你有兴趣,可以看一下。