使用QPainter::CompositionMode_Clear可以实现橡皮擦功能,删除其他QPainter绘画的方法如下:
在QWidget上创建一个缓存pixmap对象,并将其初始化为和QWidget一样大小,用于保存所有绘制的内容;
在鼠标按下事件中记录当前位置pos,并调用update()强制刷新;
在paintEvent中根据pos和当前鼠标位置绘制一条线段并保存到缓存pixmap中;
当需要橡皮擦时,在paintEvent中先将缓存pixmap绘制到QWidget上,然后使用QPainter::CompositionMode_Clear来清除被覆盖的区域。
代码示例:
class MyWidget : public QWidget
{
public:
explicit MyWidget(QWidget *parent = nullptr);
protected:
void paintEvent(QPaintEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
private:
QPixmap m_pixmap; // 缓存 pixmap 对象
QPoint m_lastPos; // 上一个鼠标位置
};
MyWidget::MyWidget(QWidget *parent)
: QWidget(parent)
{
setAttribute(Qt::WA_StaticContents); // 设置静态背景,避免闪烁
m_pixmap = QPixmap(size());
m_pixmap.fill(Qt::transparent); // 初始化为透明
}
void MyWidget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
// 先将缓存 pixmap 绘制到 QWidget 上
painter.drawPixmap(rect(), m_pixmap, rect());
if (event->type() == QEvent::Paint) {
// 如果是 Paint 事件,说明需要更新画笔位置
QPoint curPos = mapFromGlobal(QCursor::pos());
if (curPos != m_lastPos) {
// 绘制一条线段并保存到缓存 pixmap 中
QPainter pixPainter(&m_pixmap);
pixPainter.setRenderHint(QPainter::Antialiasing, true);
pixPainter.drawLine(m_lastPos, curPos);
// 记录当前位置为上一个位置
m_lastPos = curPos;
}
}
}
void MyWidget::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
// 鼠标按下时记录当前位置,并强制刷新界面
m_lastPos = event->pos();
update();
}
}
void MyWidget::mouseMoveEvent(QMouseEvent *event)
{
if ((event->buttons() & Qt::LeftButton)) {
// 鼠标移动时不断绘制线段并保存到缓存 pixmap 中,并强制刷新界面
QPoint curPos = event->pos();
QPainter pixPainter(&m_pixmap);
pixPainter.setRenderHint(QPainter::Antialiasing, true);
pixPainter.drawLine(m_lastPos, curPos);
m_lastPos = curPos;
update();
}
}
在需要橡皮擦的时候,可以通过设置QPainter的合成模式为QPainter::CompositionMode_Clear来清除被覆盖的区域:
void MyWidget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
// 先将缓存 pixmap 绘制到 QWidget 上
painter.drawPixmap(rect(), m_pixmap, rect());
if (needErase) {
// 需要橡皮擦时,设置合成模式为 CompositionMode_Clear
painter.setCompositionMode(QPainter::CompositionMode_Clear);
QPoint curPos = mapFromGlobal(QCursor::pos());
int radius = 20; // 橡皮擦的半径
QRectF eraseRect(curPos - QPointF(radius, radius), QSizeF(radius * 2, radius * 2));
painter.drawEllipse(eraseRect);
}
}