从 Qt 中的半透明小部件擦除绘制区域 [英] Erasing painted areas from translucent widgets in Qt
问题描述
我面临着必须擦除 Qt 小部件上先前绘制的区域的问题.
I am faced with the problem of having to erase previously painted areas on a Qt widget.
基本思想是,用户通过单击并拖动鼠标来选择屏幕的一个区域,并在所选区域上绘制一个矩形.
The basic idea is, the user selects an area of the screen by clicking and dragging the mouse and a rectangle is drawn over the selected area.
标题
class ClearBack : public QWidget
{
Q_OBJECT
public:
explicit ClearBack(const QPoint &startingPos);
bool eventFilter(QObject *obj, QEvent *event);
void paintEvent(QPaintEvent *);
void mouseMoveEvent(QMouseEvent *event);
signals:
void regionSelected(const QRect &);
private:
QRect currentRegion;
};
实施
ClearBack::ClearBack(const QPoint &startingPos)
{
setBackgroundRole(QPalette::Base);
installEventFilter(this);
currentRegion.setTopLeft(startingPos);
currentRegion.setBottomRight(startingPos);
this->setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint);
this->showMaximized();
}
void ClearBack::paintEvent(QPaintEvent * event)
{
Q_UNUSED(event);
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.setPen(Qt::black);
painter.drawRect(currentRegion);
}
void ClearBack::mouseMoveEvent(QMouseEvent *event)
{
QPoint currentPos(event->globalX(), event->globalY());
currentRegion.setBottomRight(currentPos);
this->repaint();
}
在具有纯色背景的小部件上,效果非常好,生成单个矩形.
On a widget that has a solid background the effect works quite nicely, producing a single rectangle.
但是,当背景设置为 setAttribute(Qt::WA_TranslucentBackground);
时,会发生以下情况.
However, when the background is set to setAttribute(Qt::WA_TranslucentBackground);
the following occurs.
之前绘制的矩形没有被擦除"
The rectangles that were drawn previously are not "erased"
有没有办法在半透明背景上擦除之前绘制的矩形,如果有,如何擦除?
Is there a way to erase the previously painted rectangles on a translucent background, and if so, how?
同样是加分项",为什么这种效果发生在半透明背景而不是纯色背景上?
Also for "bonus points" why does this effect occur on a translucent background and not on a solid one?
推荐答案
具有 WA_TranslucentBackground
属性的小部件不会自动清除其背景.你必须:
Widgets with WA_TranslucentBackground
attribute do not clear their backgrounds automatically. You have to:
将合成模式从默认的
SourceOver
改为Source
,
用透明画笔明确清除旧矩形,
Explicitly clear the old rectangle with a transparent brush,
绘制新矩形.
下面是一个在 Qt 5 下测试的工作示例.您必须按下鼠标绘制初始矩形并拖动它;松开鼠标时程序退出.
Below is a working example, tested under Qt 5. You have to press the mouse to draw the initial rectangle and drag it around; the program exits when you release the mouse.
#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QMouseEvent>
class ClearBack : public QWidget
{
Q_OBJECT
QRect m_currentRegion, m_lastRegion;
public:
explicit ClearBack(const QPoint &startingPos) :
m_currentRegion(startingPos, startingPos)
{
setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint);
setAttribute(Qt::WA_TranslucentBackground);
showMaximized();
}
Q_SIGNAL void regionSelected(const QRect &);
protected:
void paintEvent(QPaintEvent *) {
QPainter painter(this);
painter.setCompositionMode(QPainter::CompositionMode_Source);
painter.setRenderHint(QPainter::Antialiasing);
painter.setPen(QPen(Qt::transparent, 3));
painter.drawRect(m_lastRegion);
m_lastRegion = m_currentRegion;
painter.setPen(Qt::black);
painter.drawRect(m_currentRegion);
}
void mouseMoveEvent(QMouseEvent *event) {
m_currentRegion.setBottomRight(event->globalPos());
update();
}
void mouseReleaseEvent(QMouseEvent *) {
emit regionSelected(m_currentRegion);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
ClearBack back(QPoint(200,200));
a.connect(&back, SIGNAL(regionSelected(QRect)), SLOT(quit()));
return a.exec();
}
#include "main.moc"
这篇关于从 Qt 中的半透明小部件擦除绘制区域的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!