Можно ли как-то кастомизировать QLineEdit не только с помощью css и без модификации метода paintEvent?

Я хочу кастомизировать QLineEdit:

  • сделать закругленные углы;
  • задать цвет заднего фона,

с чем справляется CSS.

Но насколько мне известно, в CSS нет анимации (речь о библиотеке PyQt5).

Возможно ли реализовать плавную смену цвета заднего фона на более светлый при наведении курсора мыши c помощью CSS?

Или же реализовать каким-то иным способом?


Ответы (2 шт):

Автор решения: S. Nick

Возможное решение выглядит примерно так:

import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.Qt import *


class LineEdit(QLineEdit):    
    def __init__(self, text):
        super().__init__(text)
        self.setPlaceholderText('Please enter your username') # +

    def _set_color(self, col):
        self.setStyleSheet(f"""
            QLineEdit {{ background-color: {col.name()}; }} """)
# !!!                 ^^                   ^..........^  ^^         # <---- !!!            

    background = pyqtProperty(QColor, fset=_set_color)              # <---- !!!
        

class Example(QWidget):
    def __init__(self):
        super().__init__()

        self.button = QPushButton("Button", self)
        self.button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.button.clicked.connect(self.anim_start)

        hbox = QHBoxLayout(self)        
        hbox.addWidget(self.button)
        hbox.addSpacing(40)

        self.lineEdit = LineEdit("LineEdit")
        hbox.addWidget(self.lineEdit)

        self.anim = QPropertyAnimation(self.lineEdit, b"background")      # <---- !!!
        self.anim.setDuration(1000)
        self.anim.setStartValue(QColor('#3422A1'))           #344FA1  
        self.anim.setEndValue(QColor('#3D84B8'))
        
        self.lineEdit.installEventFilter(self)
        
    def eventFilter(self, obj, event):
        if self.lineEdit is obj:
            if event.type() == event.Enter: 
                self.anim.start()
            elif event.type() == event.Leave:  
                self.lineEdit.setStyleSheet('background-color: #344FA1;')
        return super().eventFilter(obj, event)        

    def anim_start(self):   
        self.anim.start()
    

qss = """
QLineEdit {
    font: 30pt "MS Shell Dlg 2";
    background-color: #344FA1;
    border-radius: 15px;
    border: 2px solid rgb(55, 55, 55);
    padding-left: 10px;
    padding-right: 10px;
}
"""
    
    
if __name__ == "__main__":
    app = QApplication(sys.argv)
#    app.setStyle('Fusion')
    app.setStyleSheet(qss)
  
    w = Example()
    w.resize(500, 200)
    w.show()
    sys.exit(app.exec_())

введите сюда описание изображения

→ Ссылка
Автор решения: Lo_okiMan

Вот как сделал это я:

import sys

from PyQt5.QtWidgets import QApplication, QWidget, QLineEdit

from PyQt5.QtCore import (QPropertyAnimation, pyqtProperty, QEasingCurve, 
    QParallelAnimationGroup, QSequentialAnimationGroup, pyqtSlot, pyqtSignal)

from PyQt5.QtGui import QColor


class LineEdit(QLineEdit):
    """  """
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.setAcceptDrops(True)
        self.createStandardContextMenu()

        self._leave_background_color = QColor('#545454')
        self._enter_background_color = QColor('#C7C7C7')

        self._leave_color = QColor('white')
        self._enter_color = QColor('black')

        self._background_color = self._leave_background_color
        self._color = self._leave_color 

        self.style_mask = ""\
            "border: 1px solid %s;"\
            "padding-left: 5px;"\
            "border-radius: 4px;"\
            "color: %s;"\
            "background-color: %s;"\

        self.setStyleSheet(self.style_mask % (self._background_color.name(), 
            self._color.name(), self._background_color.name()))

        self.background_animation = QPropertyAnimation(self, b"backgroundColor", self)
        self.background_animation.setEasingCurve(QEasingCurve.Linear)
        self.background_animation.setDuration(450)

        self.color_animation = QPropertyAnimation(self, b"color", self)
        self.color_animation.setEasingCurve(QEasingCurve.Linear)
        self.color_animation.setDuration(450)

        self.animations_group = QParallelAnimationGroup()
        self.animations_group.addAnimation(self.background_animation)
        self.animations_group.addAnimation(self.color_animation)

    def update(self):
        """  """
        self.setStyleSheet(self.style_mask % (self._background_color.name(), 
            self._color.name(), self._background_color.name()))

        super().update()

    @pyqtProperty(QColor)
    def backgroundColor(self):
        return self._background_color

    @backgroundColor.setter
    def backgroundColor(self, color: QColor):
        self._background_color = color
        self.update()

    @pyqtProperty(QColor)
    def enterBackgroundColor(self):
        return self._enter_background_color

    @enterBackgroundColor.setter
    def enterBackgroundColor(self, color: QColor):
        self._enter_background_color = color
        self.update()

    @pyqtProperty(QColor)
    def leaveBackgroundColor(self):
        return self._leave_background_color

    @leaveBackgroundColor.setter
    def leaveBackgroundColor(self, color: QColor):
        self._leave_background_color = color
        self.update()

    @pyqtProperty(QColor)
    def color(self):
        return self._color

    @color.setter
    def color(self, color: QColor):
        self._color = color
        self.update()

    @pyqtProperty(QColor)
    def enterColor(self):
        return self._enter_color

    @enterColor.setter
    def enterColor(self, color: QColor):
        self._enter_color = color
        self.update()

    @pyqtProperty(QColor)
    def leaveColor(self):
        return self._leave_color

    @leaveColor.setter
    def leaveColor(self, color: QColor):
        self._leave_color = color
        self.update()

    def setEnterBackgroundColor(self, color: QColor):
        """ """
        self._enter_background_color = color

    def setLeaveBackgroundColor(self, color: QColor):
        """ """
        self._leave_background_color = color

    def setEnterColor(self, color: QColor):
        """ """
        self._enter_color = color
    
    def setLeaveColor(self, color: QColor):
        """ """
        self._leave_color = color

    def enterEvent(self, event):
        """  """
        self.animations_group.stop()
        self.background_animation.setStartValue(self._background_color)
        self.background_animation.setEndValue(self._enter_background_color)
        self.color_animation.setStartValue(self._color)
        self.color_animation.setEndValue(self._enter_color)
        self.animations_group.start()

    def leaveEvent(self, event):
        """ """
        self.animations_group.stop()
        self.background_animation.setStartValue(self._background_color)
        self.background_animation.setEndValue(self._leave_background_color)
        self.color_animation.setStartValue(self._color)
        self.color_animation.setEndValue(self._leave_color)
        self.animations_group.start()


class Example(QWidget):
    def __init__(self):
        super().__init__()

        self.lineEdit = LineEdit(self)
        self.lineEdit.move(20, 20)


if __name__ == "__main__":
    app = QApplication(sys.argv)
  
    ui = Example()
    ui.resize(150, 50)
    ui.show()

    sys.exit(app.exec_())
→ Ссылка