在悬停事件时激活 QPainter
Posted
技术标签:
【中文标题】在悬停事件时激活 QPainter【英文标题】:Activating QPainter upon hover event 【发布时间】:2017-02-09 19:10:38 【问题描述】:这里有一些代码可以说明我的问题:
import sys
from PyQt4 import QtGui, QtCore
class CustomButton(QtGui.QAbstractButton):
def __init__(self, *__args):
super().__init__(*__args)
self.setFixedSize(190, 50)
self.installEventFilter(self)
def paintEvent(self, event):
painter = QtGui.QPainter(self)
painter.setBrush(QtGui.QColor(136, 212, 78))
painter.setPen(QtCore.Qt.NoPen)
painter.drawRect(QtCore.QRect(0, 0, 100, 48))
def eventFilter(self, object, event):
if event.type() == QtCore.QEvent.HoverMove:
painter = QtGui.QPainter(self)
painter.begin(self)
painter.drawRect(QtCore.QRect(0, 0, 100, 48))
painter.end()
return True
return False
app = QtGui.QApplication(sys.argv)
window = QtGui.QWidget()
layout = QtGui.QGridLayout(window)
button = CustomButton()
layout.addWidget(button, 0, 0)
window.show()
sys.exit(app.exec_())
目标是使用QPainter
制作一个可以在检测到HoverMove
事件时修改的按钮。但是,悬停时出现以下错误:
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::drawRects: Painter not active
QPainter::end: Painter not active, aborted
根据我从文档 (here) 中了解到的信息,我可以使用 .begin()
来激活 QPainter
;但是,正如错误消息显示的那样,情况并非如此,并且第二个矩形没有被绘制。我应该如何使用QPainter
来实现所需的输出?
【问题讨论】:
正如文档所说:“警告:当paintdevice是一个小部件时,QPainter只能在paintEvent()函数或由paintEvent()调用的函数中使用; 除非设置了 Qt.WA_PaintOutsidePaintEvent 小部件属性。在 Mac OS X 和 Windows 上,无论该属性的设置如何,您都只能在 paintEvent() 函数中进行绘制。" 糟糕,我的错,错过了最重要的部分:/。如果它只能在paintEvent()
中使用,是否可以从带有参数的事件处理程序中调用此方法?
【参考方案1】:
您需要检测到paintEvent
内的悬停并采取相应措施:
def paintEvent(self, event):
option = QtGui.QStyleOptionButton()
option.initFrom(self)
painter = QtGui.QPainter(self)
if option.state & QtGui.QStyle.State_MouseOver:
# do hover stuff ...
else:
# do normal stuff ...
QStyleOption 及其子类包含QStyle 函数绘制图形元素所需的所有信息。 QPaintEvent 仅包含有关需要更新哪些区域的信息。
【讨论】:
谢谢!这似乎可以解决问题。但是,最好在函数结束时准确地指出painter.end()
,否则程序将崩溃。在我接受之前,您介意解释一下QStyleOptionButton
的使用而不是检查事件的类型吗?
我已经添加了一些进一步的解释,但所有细节都可以在 Qt 文档中找到。没有必要显式调用end()
,因为它是由析构函数自动调用的。检查事件的类型是没有意义的,因为它只能是QPaintEvent
。
调用option.initFrom(self)
只是将self.underMouse()
的结果添加到option.state
@MarcheRemi 这不是这样做的重点。绘制自定义小部件比获取鼠标悬停状态要多得多。样式选项提供了一种非常有效的方式,可以在一个步骤中获取所有相关信息。
@ekhumoro,这个问题是关于悬停的。【参考方案2】:
@ekhumoro's answer above 可以用QWidget::underMouse()
更简单地重写。 the docs
def paintEvent(self, event):
if underMouse():
# do hover stuff ...
else:
# do normal stuff ...
【讨论】:
以上是关于在悬停事件时激活 QPainter的主要内容,如果未能解决你的问题,请参考以下文章