TrakJohnson
TrakJohnson

Reputation: 2097

Activating QPainter upon hover event

Here is some code that illustrates my problem:

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_())

The goal is to make a button using QPainter that can be modified when the HoverMove event is detected. However, I get the following errors upon hovering:

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

From what I've understood from the docs (here) I can use .begin() to activate the QPainter; however as the error message shows this isn't the case and the second rectangle does not get drawn. How should I use QPainter to achieve the desired output ?

Upvotes: 1

Views: 1964

Answers (2)

ecstrema
ecstrema

Reputation: 691

@ekhumoro's answer above can be rewritten more simply with QWidget::underMouse(). the docs

    def paintEvent(self, event):
        if underMouse():
            # do hover stuff ...
        else:
            # do normal stuff ...

Upvotes: 0

ekhumoro
ekhumoro

Reputation: 120798

You need to detect the hover inside paintEvent and act accordingly:

    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 and its subclasses contain all the information that QStyle functions need to draw a graphical element. The QPaintEvent only contains information about what area needs to be updated.

Upvotes: 2

Related Questions