是否可以在 PyQt/PySide2 中为 QLineEdit 的文本制作“破碎”边框

Posted

技术标签:

【中文标题】是否可以在 PyQt/PySide2 中为 QLineEdit 的文本制作“破碎”边框【英文标题】:Is it possible to make a 'broken' border with text for QLineEdit in PyQt/PySide2 【发布时间】:2020-08-09 07:34:34 【问题描述】:

是否可以将 PyQt5/PySide2 中的输入字段设置为如下所示: input field

关于样式 QLineEdit (https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qlineedit) 的官方文档没有提供很多示例。 到目前为止,我尝试弄乱边框属性,但我无法得到任何与我想要的东西密切相关的东西。 我的另一个想法是将上面的图片用作背景图片,并从 qlineedit 中删除边框和背景,使其看起来像是图片的一部分。这种方法的问题是它不再是可拉伸的。

是否有可能让我的 qlineedit 看起来像图片中的那样,还是我应该放弃这个想法?

【问题讨论】:

【参考方案1】:

您可以通过继承 QLineEdit 并定义一个自定义的paintEvent 来实现这一点。 QFontMetrics 将获取要作为标签添加到 QLineEdit 上的文本的宽度和高度。然后它可以用来定义一个想要的margin-top 和剪裁的边框空间。可以使用画家路径绘制边界线,以获得真正透明的破碎区域。

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

class NewLineEdit(QLineEdit):

    def __init__(self, label, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.label = label
        self.lrect = self.fontMetrics().boundingRect(label)
        self.setStyleSheet(f'''
        QLineEdit 
            background-color: rgba(0, 0, 0, 0%);
            border: none;
            padding: 9px;
            margin-top: self.lrect.height() / 2px;
            color: blue;
        ''')
        self.setAttribute(Qt.WA_MacShowFocusRect, False)
        self.setMinimumWidth(self.lrect.width() + 52)

    def paintEvent(self, event):
        super().paintEvent(event)
        w, h = self.width(), self.height()
        lh = self.lrect.height() / 2
    
        path = QPainterPath()
        path.moveTo(30, lh + 3)
        path.lineTo(9, lh + 3)
        path.quadTo(3, lh + 3, 3, lh + 9)
        path.lineTo(3, h - 9)
        path.quadTo(3, h - 3, 9, h - 3)
        path.lineTo(w - 9, h - 3)
        path.quadTo(w - 3, h - 3, w - 3, h - 9)
        path.lineTo(w - 3, lh + 9)
        path.quadTo(w - 3, lh + 3, w - 9, lh + 3)
        path.lineTo(42 + self.lrect.width(), lh + 3)

        qp = QPainter(self)
        qp.setRenderHint(QPainter.Antialiasing)
        qp.setPen(QPen(QColor('#aaa'), 3))
        qp.drawPath(path)
        qp.setPen(Qt.black)
        qp.drawText(36, self.lrect.height(), self.label)

您将创建新对象,而不是创建 QLineEdit,例如 NewLineEdit('Input Field')

结果:

【讨论】:

快速提问。当我使用这个类时,文本周围有一个灰色矩形 (imgur.com/a/VH5fMBa)。有没有办法让背景透明?我检查了 drawText() 的文档,但它似乎只需要位置和对齐标签 @afaf 那是因为必须以某种方式覆盖边界线的一部分,所以我选择了父窗口颜色以显示透明。虽然似乎并非在所有情况下都有效,所以我编辑了答案以手动绘制线条,现在试试吧。 编辑后的版本似乎不起作用(PySide2 5.14、python 3.6、macos catalina)文本后面可见边框。 def paintEvent(self, event): super().paintEvent(event) w, h = self.lrect.width(), self.lrect.height() qp = QPainter(self) qp.setPen(Qt.NoPen) qp .setBrush(self.parent().palette().color(QPalette.Window)) qp.drawRect(self.width() / 5 - 6, 0, w + 20, h) qp.setPen(Qt.black) qp.drawText(self.width() / 5, h, self.label) 我更改了父小部件的背景,这似乎解决了问题。 @afaf 复制整个类而不仅仅是paintEvent,我的看起来像这样prnt.sc/twtpax 你是对的,编辑后的版本确实有效。非常感谢您的帮助。除了官方文档之外,还有什么资源可以让我了解更多关于 PyQt 样式的信息吗?

以上是关于是否可以在 PyQt/PySide2 中为 QLineEdit 的文本制作“破碎”边框的主要内容,如果未能解决你的问题,请参考以下文章

如何在 PyQt5 / PySide2 中从一个类访问属性到另一个类

QTableView 在 PyQt5/PySide2 中的每个选择上加载数据时锁定主窗体 [重复]

能够在 PyQt5 中一次打开多个对话框的单窗口模式?

text 电流项目和下降(QLI)

是否可以在 NestJs 中为 DTO 进行继承?

是否可以在 ExpandableListView 中为子项放置不同的布局?