更改 QLineEdit 的文本显示方式

问题描述 投票:0回答:1

我想更改一些

QLineEdit
的文本显示。 文本应显示为欧元金额。

QLineEdits 似乎不是这种显示的合适选择。因此,我将代码改编为 QDoubleSpinBox。

简短地说明上下文:

我有几个 QTableWidget,其中使用自定义委托,例如:

class EuroDelegate(QStyledItemDelegate):
    def displayText(self, value, locale):
        if value is not None:
            value = float(value)
            return locale.toCurrencyString(value, '€', 2)
        else:
            return super().displayText(value, locale)

将文本显示为欧元金额。

一些 QLineEdit 还包含欧元金额,我希望它们“感觉”尽可能相似。因此,我将那些 QLineEdits 更改为 QDoubleSpinBoxes

因此,一些所需的特性很快就实现了。
列表中的被击中的项目已在下面的代码片段中实现:

  1. 金额后显示“€”。
  2. '€' 不应成为
    LineEdit.text()
    的一部分。
  3. QLineEdit 的行为与委托类似:当 QLineEdit 获得焦点时,“€”字符消失,当它失去焦点时,它会重新出现。
  4. 单击/聚焦 QDoubleSpinbox 应选择完整内容。
  5. QDoubleSpinBox 应自动设置“,”。理想情况下,诸如“0050”之类的条目应直接在条目上显示(在“Enter”键之前)为:“00,50”,在“Enter”键之后(QDoubleSpinBox 的默认值)为“0,50”。 这同样适用于诸如“-1050”=>“-10,50”的条目,其中“99”+ Enter 等条目应继续产生“99,00”。因此,该框应识别输入将超出或低于其“最小/最大范围”,然后自动设置小数点。 (在我的国家/地区,使用“,”(=>“欧元,美分”)进行分隔,并且 QDoubleSpinBox 已经尊重这一点。)

可以使用的代码片段:

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QDoubleSpinBox, QLineEdit, QPushButton
from PyQt5.QtCore import QTimer

class EuroDoubleSpinBox(QDoubleSpinBox):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setButtonSymbols(QDoubleSpinBox.NoButtons)
        self.normalSuffix = ''
        self.currencySuffix = ' €'
        self.setSuffix(self.currencySuffix)

    def focusInEvent(self, event):
        self.setSuffix(self.normalSuffix)
        QTimer.singleShot(0, self.selectAll)
        super().focusInEvent(event)

    def focusOutEvent(self, event):
        self.setSuffix(self.currencySuffix)
        super().focusOutEvent(event)


class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        layout = QVBoxLayout()
        self.pushbutton = QPushButton('Print DoubleSpinBox Value')
        self.lineedit = QLineEdit() # added for focus toggling
        self.doubleSpinBox = EuroDoubleSpinBox()
        self.doubleSpinBox.setRange(-99.99, 99.99)
        self.doubleSpinBox.setSingleStep(0.01)
        layout.addWidget(self.lineedit)
        layout.addWidget(self.doubleSpinBox)
        layout.addWidget(self.pushbutton)
        self.setLayout(layout)

        self.pushbutton.clicked.connect(lambda: print(self.doubleSpinBox.cleanText()))

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    window.setGeometry(100, 100, 200, 100)
    window.setWindowTitle('Euro DoubleSpinBox')
    window.show()
    sys.exit(app.exec_())

我正在使用 python 3.10.13 和 PyQt5 5.15.9

python pyqt5 python-3.10
1个回答
0
投票

QAbstractSpinBox 子类提供了一个

validate()
函数来调用内部验证器,类似于 QValidator 的
validate()
的功能。

解决方案是根据您的需要覆盖该函数。

对于这样一个简单的要求(在输入第三位数字时添加小数点),以下内容可能就足够了:

class EuroDoubleSpinBox(QDoubleSpinBox):
    ...
    def validate(self, text, pos):
        if 2 < len(text.lstrip('-')) < 5:
            if text.isdecimal():
                p = 2
            elif text.startswith('-') and text[1:].isdecimal() and len(text) > 3:
                p = 3
            else:
                return super().validate(text, pos)
            value = float('{}.{}'.format(text[:p], text[p:]))
            if self.minimum() <= value <= self.maximum():
                return (
                    QValidator.Acceptable, 
                    text[:p] + QLocale().decimalPoint() + text[p:], 
                    pos + 1
                )
        return super().validate(text, pos)

程序如下:

  1. 检查键入文本的长度(不带前导减号)是否为 3 或 4 个字符;
  2. 如果文本是十进制(仅限
    0-9
    范围内的字符,类似于正则表达式的
    \d?
    ),则假设小数点位于第二位数字之后;
  3. 如果文本以减号开头且后面的字符代表小数并且长度至少为3个字符,则将小数点位置设置在第第三个数字之后;
  4. 如果2和3失败,则返回默认验证;
  5. 通过在第二个或第三个位置后插入小数点来构建可能的浮点值;
  6. 如果值在旋转框的最小/最大范围之间,则返回
    QValidator.Acceptable
    ,即带有区域设置定义的小数点的文本,并将光标位置增加 1;
  7. 作为最终回退,返回默认验证;

上述内容几乎适用于任何情况,包括从键盘粘贴。如果您还想支持使用点作为小数点粘贴浮点值,而系统使用不同的符号(如您的情况),则可能需要进行更多微调。

© www.soinside.com 2019 - 2024. All rights reserved.