You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

鼠标进出QLineEdit时更新QStyle调用drawPrimitive传参报错如何解决?

错误原因

drawPrimitive是Qt原生定义的虚函数,接口签名固定,不允许自行新增参数或传入未声明的关键字参数,你自定义方法时额外添加的a参数不符合Qt的接口规范,调用时传入a=self.a就会触发类型错误。

解决方法

不需要修改drawPrimitive的接口签名,调用该方法时会传入当前控件实例作为widget参数,直接从控件实例中读取你定义的状态属性即可,同时修复原有代码中缺少重绘触发、漏传参数、尺寸写死的问题。

修改后完整可运行代码:

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

class LineEditStyle(QProxyStyle):
    # 保持原生drawPrimitive的参数签名不变
    def drawPrimitive(self, element, option, painter, widget=None):
        # 从传入的widget参数直接读取悬停状态
        border_color = 'green' if (widget and getattr(widget, 'hover_flag', 0)) else 'red'
        pen = QPen(QColor(border_color))
        pen.setWidth(4)
        if element == QStyle.PE_FrameLineEdit:
            painter.setRenderHint(QPainter.Antialiasing)
            painter.setPen(pen)
            # 用option.rect适配控件实际尺寸,不要写死宽高
            painter.drawRoundedRect(option.rect.adjusted(0,0,-1,-1), 10, 10)
        else:
            super().drawPrimitive(element, option, painter, widget)

        
class LineEdit(QLineEdit):
    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)
        self.hover_flag = 0
    
    def enterEvent(self, a0):
        self.hover_flag = 1
        self.update() # 修改状态后触发重绘
        super().enterEvent(a0)

    def leaveEvent(self, a0):
        self.hover_flag = 0
        self.update() # 修改状态后触发重绘
        super().leaveEvent(a0)
        
    def paintEvent(self,event):
        # 先绘制原生输入框的文本、光标等内容
        super().paintEvent(event)
        # 再绘制自定义边框
        option = QStyleOption()
        option.initFrom(self)
        # 补齐drawPrimitive需要的所有参数:painter、当前控件实例
        self.style().drawPrimitive(QStyle.PE_FrameLineEdit, option, self.painter(), self)


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

核心修改点

  • 保留drawPrimitive原生接口签名,直接从widget参数读取悬停状态属性
  • 鼠标进入/离开事件中调用update()触发控件重绘,确保样式实时更新
  • 补全drawPrimitive调用所需的painter、widget参数
  • 用option.rect获取控件实际尺寸,适配不同大小的输入框
  • 先调用父类paintEvent绘制输入框原生的文本、光标内容,再绘制自定义边框,避免文本被边框覆盖

内容的提问来源于stack exchange,提问作者BADAOUI Aymen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 19:57:01