Одним из возможных решений является использование QML для создания этого эффекта, а для использования его с классическими виджетами вы должны использовать QQuickWidget, как показано ниже:
main.qml
import QtQuick 2.9
import QtQuick.Controls 2.4
Button {
id: control
property color color: "white"
property color _color: down ? Qt.lighter(color, 1.1): color
property color light_color: Qt.lighter(control._color, 1.1)
property color dark_color: Qt.darker(control._color, 1.1)
contentItem: Text {
text: control.text
font: control.font
color: "white"
style: Text.Outline
styleColor: "black"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
background: Rectangle {
opacity: enabled ? 1 : 0.3
border.width: 0.7
border.color: "gray"
radius: 2
gradient: Gradient {
GradientStop { position: 0 ; color: control.pressed ? control._color : control.light_color }
GradientStop { position: 1 ; color: control.pressed ? control.dark_color : control._color }
}
}
onClicked: obj.clicked()
}
main.py
from PyQt5 import QtCore, QtGui, QtWidgets, QtQuickWidgets
class ButtonQMl(QtQuickWidgets.QQuickWidget):
clicked = QtCore.pyqtSignal()
def __init__(self, parent=None):
super(ButtonQMl, self).__init__(parent)
self.setSource(QtCore.QUrl.fromLocalFile("main.qml"))
self.setResizeMode(QtQuickWidgets.QQuickWidget.SizeRootObjectToView)
self.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
self.engine().rootContext().setContextProperty("obj", self)
self.setFixedHeight(50)
def text(self):
return self.rootObject().property("text") if self.rootObject() else ""
def setText(self, text):
if self.rootObject() and self.text() != text:
self.rootObject().setProperty("text", text)
def color(self):
return self.rootObject().property("color") if self.rootObject() else ""
def setColor(self, color):
color = QtGui.QColor(color)
if self.rootObject() and self.color() != color:
self.rootObject().setProperty("color", color)
def font(self):
return self.rootObject().property("font") if self.rootObject() else ""
def setFont(self, font):
if self.rootObject() and self.font() != font:
self.rootObject().setProperty("font", font)
class MyButton(ButtonQMl):
def __init__(self, parent=None):
super(MyButton, self).__init__(parent)
self.clicked.connect(self.change_color)
self.setupFont()
def change_color(self):
color = QtWidgets.QColorDialog.getColor()
if color.isValid():
self.setColor(color)
def setupFont(self):
fnt = self.font()
fnt.setFamily('Palatino')
fnt.setPointSize(20)
self.setFont(fnt)
def mousePressEvent(self, event):
print("event: ", event)
super(MyButton, self).mousePressEvent(event)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = QtWidgets.QWidget()
lay = QtWidgets.QVBoxLayout(w)
btn1 = MyButton()
btn1.setText("Hello World");
btn1.setColor(QtCore.Qt.yellow)
btn2 = QtWidgets.QPushButton("Click me")
btn2.setFixedHeight(50)
btn2.setStyleSheet("color: white; background-color: yellow")
lay.addWidget(btn1)
lay.addWidget(btn2)
w.show()
sys.exit(app.exec_())