qt - QPainter 忽略paintEvent 内部的剪辑
问题描述
每当它获得焦点时,我都会尝试在 a QPushButton
(按钮边界之外)下方绘制文本。为此,我进行了子类化QPushButton
,并且正在使用QPainter
drawText 方法paintEvent
在QPushButton
. 在绘制之前,我设置QPainter::setClipping(false)
启用文本绘制侧按钮的边界。但不知何故QPainter::setClipping(false)
不起作用,文本没有被绘制到按钮边界之外。
解决方案
画家的绘画引擎本身在较低级别实现了裁剪,小部件画家默认不裁剪。换句话说:不可能关闭此剪辑。以下成立:
void Class::paintEvent(QPaintEvent *ev) {
Parent::paintEvent(ev);
QPainter p(this);
Q_ASSERT(!p.hasClipping());
// and now you do:
p.setClipping(false); // this is a no-op!
}
一个简单的解决方案是添加一个小部件,该小部件将文本绘制为按钮的兄弟,并将其定位在按钮下方。该小部件可以是QLabel
.
static const char kLabelSibling[] = "qq_labelSibling";
static const char kTrackedSibling[] = "qq_trackedSibling";
void setTextBelow(QWidget *widget, const QString &text) {
Q_ASSERT(widget->parent);
class Filter : QObject {
static QLabel *getLabel(QObject *sibling) {
return widget->property(kLabelSibling).value<QLabel*>();
}
static void updateLabel(QWidget *label) {
auto *sibling = label->property(kTrackedSibling).value<QWidget*>();
Q_ASSERT(sibling);
label->setParent(sibling->parent());
label->move(sibling->bottomLeft());
label->setVisible(sibling->hasFocus());
}
bool eventFilter(QObject *obj, QEvent *ev) override {
if (auto *label = getLabel(obj))
if (ev->type() == QEvent::Resize || ev->type() == QEvent::Move
|| ev->type() == QEvent::ParentChange || ev->type() == QEvent::FocusIn
|| ev->type() == QEvent::FocusOut)
updateLabel(label);
return false;
}
public:
using QObject::QObject;
};
auto *label = Filter::getLabel(widget);
if (!label) {
label = new QLabel(widget->parent());
label->setProperty(kTrackedSibling, QVariant::fromValue(widget));
widget->setProperty(kLabelSibling, QVariant::fromValue(label));
widget->installEventFilter(new Filter(widget));
QObject::connect(widget, &QObject::destroyed, label, [widget, label]{
widget->setProperty(kLabelSibling, {});
label->setProperty(kTrackedSibling, {});
label->deleteLater();
});
}
label->setText(text);
Filter::updateLabel(label);
}
(对不起,以上内容未经测试,凭记忆编写)
推荐阅读
- rxjs - 如何知道 switchMap 是否取消了内部 Observable 的订阅?
- java - 使用 Tasklet 删除 Spring Batch 中的文件,但需要上一步的退出状态
- javascript - 单击传单弹出窗口内的按钮时显示执行功能的问题
- node.js - Express 的绝对类型定义不起作用
- c# - 没有异常对象时的 Application Insights TrackException ExceptionTelemetry
- azure-active-directory - 如何验证用户是否属于 Azure AD 中的组?
- ios - 如何通过 UIkit 将组件嵌套到组件?
- google-cloud-platform - Google Stackdriver 默认端口被防火墙规则阻止
- abap - 如何将函数的结果写到屏幕上?
- keras - 使用 Keras 使用泊松采样标签提高 MLP 性能(用于多类分类)