【问题标题】:update QStyle in EnterEvent在 EnterEvent 中更新 QStyle
【发布时间】:2021-10-23 05:31:26
【问题描述】:

我想在鼠标进入控件时更新 LineEdit 的 QStyle (enterEvent\leaveEvent ) 我试图向 drawPrimitive 函数添加一个 bool 变量,但出现此错误 TypeError: drawPrimitive(self, QStyle.PrimitiveElement, QStyleOption, QPainter, widget: QWidget = None): 'a' is not a valid keyword argument

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PushButton_2 import Push_Button_
import sys

class LineEditStyle(QProxyStyle):
    def drawPrimitive(self, element, option, painter, widget,a=None):
        if a :
            self.pen = QPen(QColor('green'))
        else :
            self.pen = QPen(QColor('red'))
        self.pen.setWidth(4)
        if element == QStyle.PE_FrameLineEdit:
            painter.setRenderHint(QPainter.Antialiasing)
            painter.setPen(self.pen)
            painter.drawRoundedRect(QRect(0,0,400,40), 10, 10)
        else:
            super().drawPrimitive(element, option, painter, widget)

        
class LineEdit(QLineEdit):
    def __init__(self,*args,**kwargs):
        QLineEdit.__init__(self,*args,**kwargs)
        self.a = 0
    
    def enterEvent(self, a0):
        self.a = 1

    def leaveEvent(self, a0):
        self.a = 0
        
    def paintEvent(self,event):
        option = QStyleOption()
        option.initFrom(self)
        self.style().drawPrimitive(QStyle.PE_FrameLineEdit,option,a=self.a)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = QMainWindow()
    window.setGeometry(500,500,400,400)
    window.setStyleSheet('background-color:#373737')
    line = LineEdit(parent=window)
    line.setGeometry(20,200,400,40)
    style = LineEditStyle()
    line.setStyle(style)
    window.show()
    sys.exit(app.exec())

【问题讨论】:

    标签: python pyqt pyside


    【解决方案1】:

    您不能将 QStyleSheet 与 QStyle 一起使用,因为它会造成混淆,您必须将默认参数 Widget 设置为 None

    from PyQt5.QtWidgets import *
    from PyQt5.QtCore import *
    from PyQt5.QtGui import *
    from PushButton_2 import Push_Button_
    import sys
    
    class LineEditStyle(QProxyStyle):
        def drawPrimitive(self, element, option, painter, widget=None,a=None):
            if a :
                self.pen = QPen(QColor('green'))
            else :
                self.pen = QPen(QColor('red'))
            self.pen.setWidth(4)
            if element == QStyle.PE_FrameLineEdit:
                painter.setRenderHint(QPainter.Antialiasing)
                painter.setPen(self.pen)
                painter.drawRoundedRect(QRect(0,0,400,40), 10, 10)
            else:
                super().drawPrimitive(element, option, painter, widget)
        
        def subElementRect(self, element, option, widget):
            if element == QStyle.SE_LineEditContents :
                return QRect(0,0,50,30)
            else :
                return super().subElementRect(element, option, widget)
        
        def drawItemText(self, painter, rect, flags, pal, enabled, text, textRole):
            rect_ = QRect(20,20,50,50)
            text = text.upper()
            painter.drawText(text,rect_,Qt.AlignCenter)
            
    class LineEdit(QLineEdit):
        def __init__(self,*args,**kwargs):
            QLineEdit.__init__(self,*args,**kwargs)
            self.a = 0
        
        def enterEvent(self, a0):
            self.a = 1
    
        def leaveEvent(self, a0):
            self.a = 0
            
        def paintEvent(self,event):
            option = QStyleOption()
            option.initFrom(self)
            painter = QPainter(self)
            self.style().drawPrimitive(QStyle.PE_FrameLineEdit,option,painter,a=self.a)
    
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        window = QMainWindow()
        window.setGeometry(500,500,400,400)
        #window.setStyleSheet('background-color:#373737')
        line = LineEdit(parent=window)
        line.setGeometry(20,200,400,40)
        style = LineEditStyle()
        line.setStyle(style)
        window.show()
        sys.exit(app.exec())
    

    【讨论】:

    • “您不能将 QStyleSheet 与 QStyle 一起使用,因为它会造成混淆”这并不完全准确:如果将样式表直接应用(并生效)到小部件,则存在问题,或者如果在父级(包括应用程序)上设置的任何样式表影响小部件,那是因为在这种情况下,实际样式集和使用的是 QStyleSheetStyle,它充当最终为小部件。在这种特定情况下,问题是鼠标悬停检查没有正确完成,这是通过验证是否option.state & QStyle.State_MouseOver
    【解决方案2】:

    您可能会发现 QStyleSheets 对这样的事情很有用。

    我通过在 styleSheet 属性中输入以下内容在 Qt Designer 中模拟了这一点(在代码中你会这样做 mywidget.setStyleSheet('<parameters>') ):

    QLineEdit {
        border: 3px solid red;
    }
    QLineEdit:focus {
        border: 3px solid green;
    }
    

    编辑:上面的 styleSheet 字符串适用于焦点,但最初的问题是关于 enterEvent/leaveEvent,它在鼠标悬停时触发。正如@musicamente 正确指出的那样,要进行鼠标悬停,可以使用:hover pseudo state 代替:focus

    QLineEdit {
        border: 3px solid red;
    }
    QLineEdit:hover {
        border: 3px solid green;
    }
    

    我用 2 个 QLineEdits 制作了一个 QMainWindow:1 个设置了 styleSheet,另一个是默认设置。当焦点移动到常规 QLineEdit 时,修改后的 QLineEdit 变为红色。

    您可以通过编辑其父级的样式表使 ALL 的 QLineEdit 行为相同。在您的情况下,您可以使用window.setStyleSheet('....。这是 Qt Designer 中的另一个模型:

    【讨论】:

    • OP没有询问焦点,而是鼠标悬停,这是使用:hover伪状态选择器实现的。
    • @musicamente。你说得对!在您发表评论之前,我没有阅读 enterEvent 的文档。 enterEvent 在鼠标悬停时触发。已编辑答案以包含 :hover
    猜你喜欢
    • 1970-01-01
    • 2016-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-22
    相关资源
    最近更新 更多