void MyPaint::paintEvent(QPaintEvent *event) { if(_openflag == 0)//不是打开图片的,每一次新建一个空白的画布 { _pixmap = QPixmap(size());//新建pixmap _pixmap.fill(Qt::white);//背景色填充为白色 } QPixmap pix = _pixmap;//以_pixmap作为画布 QPainter p(&pix);//将_pixmap作为画布 unsigned int i1=0,i2=0,i3=0,i4=0,k=0;//各种图形的索引 Q_UNUSED(event); QPen pen; pen.setColor(color); for(int c = 0;c<_shape.size();++c)//控制用户当前所绘图形总数 { if(_shape.at(c) == 1)//线条 { const QVector<QPoint>& line = _lines.at(i1++);//取出一条线条 for(int j=0; j<line.size()-1; ++j)//将线条的所有线段描绘出 { p.drawLine(line.at(j), line.at(j+1)); } } else if(_shape.at(c) == 2)//矩形 { p.drawRect(_rects.at(i2++)); } else if(_shape.at(c) == 3)//椭圆 { p.drawEllipse(_ellipse.at(i3++)); } else if(_shape.at(c) == 4)//直线 { p.drawLine(_line.at(i4).topLeft(),_line.at(i4).bottomRight()); i4++; } } p.end(); p.begin(this); // 将当前窗体作为画布 p.drawPixmap(0, 0, pix); // 绘制之前的 pixmap }使用双缓冲技术实现在绘制新的图形时只更新变化的部分而不重新绘制整个画布
时间: 2024-04-12 22:33:05 浏览: 97
根据您提供的代码,您已经在 `paintEvent` 函数中使用了双缓冲技术来绘制图形。每次绘制新的图形时,只更新变化的部分而不重新绘制整个画布。
在代码中,您创建了一个 `_pixmap` 对象作为画布,并在需要绘制的时候使用 `QPainter` 对象 `p` 在 `_pixmap` 上进行绘制操作。
然后,您在最后使用 `p.drawPixmap(0, 0, pix)` 将 `_pixmap` 的内容绘制到窗口上,实现了只更新变化的部分而不重新绘制整个画布。
请注意,在每次 `paintEvent` 被调用时,都会重新绘制整个窗口的内容。通过使用双缓冲技术,您可以在内存中构建一个临时的缓冲区 `_pixmap`,在其上进行绘制操作,并在最后一次性地将其内容绘制到窗口上,从而减少了频繁的重绘操作。
如果您还有其他问题或需要进一步的帮助,请随时提问。
相关问题
void MyPaint::paintEvent(QPaintEvent *event) { if(_openflag == 0)//不是打开图片的,每一次新建一个空白的画布 { _pixmap = QPixmap(size());//新建pixmap _pixmap.fill(Qt::white);//背景色填充为白色 } QPixmap pix = _pixmap;//以_pixmap作为画布 QPainter p(&pix);//将_pixmap作为画布 unsigned int i1=0,i2=0,i3=0,i4=0,k=0;//各种图形的索引 Q_UNUSED(event); QPen pen; pen.setColor(color); for(int c = 0;c<_shape.size();++c)//控制用户当前所绘图形总数 { if(_shape.at(c) == 1)//线条 { const QVector<QPoint>& line = _lines.at(i1++);//取出一条线条 for(int j=0; j<line.size()-1; ++j)//将线条的所有线段描绘出 { p.drawLine(line.at(j), line.at(j+1)); } } else if(_shape.at(c) == 2)//矩形 { p.drawRect(_rects.at(i2++)); } else if(_shape.at(c) == 3)//椭圆 { p.drawEllipse(_ellipse.at(i3++)); } else if(_shape.at(c) == 4)//直线 { p.drawLine(_line.at(i4).topLeft(),_line.at(i4).bottomRight()); i4++; } } p.end(); p.begin(this); // 将当前窗体作为画布 p.drawPixmap(0, 0, pix); // 绘制之前的 pixmap }使用双缓冲技术实现在绘制新的图形时只更新变化的部分而不重新绘制整个画布
在这段代码中,双缓冲技术可以通过使用一个额外的 QPixmap 对象来实现。具体的实现方式如下:
1. 在类的成员变量中定义一个额外的 QPixmap 对象,命名为 bufferPixmap。
2. 在 paintEvent 函数的开头判断 _openflag 的值,如果为 0,则表示不是打开图片,需要新建一个空白的画布。在这种情况下,将 bufferPixmap 初始化为和当前窗体大小一致,并用白色填充。
3. 将 bufferPixmap 赋值给局部变量 pix,并使用 pix 作为绘图的画布。
4. 在绘制各种图形之前,创建一个 QPainter 对象,将其关联到 pix 上。
5. 根据 _shape 数组中的值来确定需要绘制的图形类型,并根据相应的索引取出对应的图形数据进行绘制。
6. 在所有图形都绘制完成后,调用 p.end() 结束对 pix 的绘制。
7. 调用 p.begin(this) 开始对当前窗体进行绘制。
8. 调用 p.drawPixmap(0, 0, pix) 绘制之前绘制在 bufferPixmap 上的内容。
通过使用双缓冲技术,只有在需要更新部分内容时才进行重新绘制,从而提高了绘图性能。
void MyPaint(HDC hdc) { SelectObject(bufdc, bg); BitBlt(mdc, 0, 0, 800, 600, bufdc, 0, 0, SRCCOPY); //重贴背景,没有残影 // 随机生成水果的总数 static int j=0; for (int i = 0; i < num; i++) { // 随机生成水果的位置和贴图 SelectObject(bufdc, res[index[i]]); MyTransparentBlt(mdc, x[i], y[i], 100, 100, bufdc, 0, j, 100, 100, RGB(255, 0, 255)); } j = j + 100; if (j >= 1500) j = 0; BitBlt(hdc,0,0,800,600,mdc,0,0,SRCCOPY); for(int i=0;i<3;i++){ if(y[i]>300&&flag[i]==0) { x[i] += vx; //计算X轴方向贴图坐标,每调用一次MyPiant(),x坐标就加上一个恒定不变的vx,相当于匀速运动 vy = vy -gy; //计算Y轴方向速度分量,vy随着每一次MyPiant()函数的调用就加上一个gy(重力加速度) y[i] += vy; } else{ flag[i]=1; x[i] += vx; //计算X轴方向贴图坐标,每调用一次MyPiant(),x坐标就加上一个恒定不变的vx,相当于匀速运动 vy = vy +gm; //计算Y轴方向速度分量,vy随着每一次MyPiant()函数的调用就加上一个gy(重力加速度) y[i] += vy; } if(y[i]>550&&flag[i]==1){ num = rand() % 5 + 1; srand(time(NULL)); for(int m=0;m<3;m++){ x[m]=rand()%500+80; y[m]=rand()%50+650; index[m]=rand()%8; } vx=3; vy=0; gy=1.4; gm=1.4; flag[i]=0; } } //计算Y轴方向贴图坐标,每调用一次MyPiant(),y坐标就加上一个刚改变过后的vy,相当于加速运动 tPre = GetTickCount(); //记录上次的绘图时间 }可以帮我添加功能,让图和图之间不会重合吗
可以添加一个碰撞检测的功能,当两个图像的位置重合时,将其中一个图像的位置微调一下,使它们不再重合。可以在每次更新图像位置时,通过比较所有图像之间的距离来检测是否有重合,如果有重合,就将其中一个图像的位置向左或向右微调一些像素,使它们不再重合。以下是修改后的代码:
```
void MyPaint(HDC hdc) {
SelectObject(bufdc, bg);
BitBlt(mdc, 0, 0, 800, 600, bufdc, 0, 0, SRCCOPY); //重贴背景,没有残影
// 随机生成水果的总数
static int j = 0;
for (int i = 0; i < num; i++) {
// 随机生成水果的位置和贴图
SelectObject(bufdc, res[index[i]]);
MyTransparentBlt(mdc, x[i], y[i], 100, 100, bufdc, 0, j, 100, 100, RGB(255, 0, 255));
}
// 检测图像之间是否有重合
for (int i = 0; i < num; i++) {
for (int j = i + 1; j < num; j++) {
int dx = abs(x[i] - x[j]);
int dy = abs(y[i] - y[j]);
if (dx < 100 && dy < 100) {
if (x[i] < x[j]) {
x[i] -= 5;
x[j] += 5;
} else {
x[i] += 5;
x[j] -= 5;
}
}
}
}
j = j + 100;
if (j >= 1500)
j = 0;
BitBlt(hdc, 0, 0, 800, 600, mdc, 0, 0, SRCCOPY);
for (int i = 0; i < 3; i++) {
if (y[i] > 300 && flag[i] == 0) {
x[i] += vx; //计算X轴方向贴图坐标,每调用一次MyPiant(),x坐标就加上一个恒定不变的vx,相当于匀速运动
vy = vy - gy; //计算Y轴方向速度分量,vy随着每一次MyPiant()函数的调用就加上一个gy(重力加速度)
y[i] += vy; //计算Y轴方向贴图坐标,每调用一次MyPiant(),y坐标就加上一个刚改变过后的vy,相当于加速运动
} else {
flag[i] = 1;
x[i] += vx; //计算X轴方向贴图坐标,每调用一次MyPiant(),x坐标就加上一个恒定不变的vx,相当于匀速运动
vy = vy + gm; //计算Y轴方向速度分量,vy随着每一次MyPiant()函数的调用就加上一个gy(重力加速度)
y[i] += vy; //计算Y轴方向贴图坐标,每调用一次MyPiant(),y坐标就加上一个刚改变过后的vy,相当于加速运动
}
if (y[i] > 550 && flag[i] == 1) {
num = rand() % 5 + 1;
srand(time(NULL));
for (int m = 0; m < 3; m++) {
x[m] = rand() % 500 + 80;
y[m] = rand() % 50 + 650;
index[m] = rand() % 8;
}
vx = 3;
vy = 0;
gy = 1.4;
gm = 1.4;
flag[i] = 0;
}
}
tPre = GetTickCount(); //记录上次的绘图时间
}
```
阅读全文