在不牺牲内部精度的情况下,限制pyQT QLineEdit中显示的浮点数的数量

时间:2016-07-22 07:46:13

标签: python floating-point pyqt qlineedit

我在我的应用程序中使用QLineEdit小部件来输入和编辑数字(浮点)值。我想显示浮点值的圆形版本,同时保持完整的内部精度。仅在编辑QLineEdit字段时,才会显示完整的位数。

这需要三个原因:

  • 复杂的值需要为我的GUI提供太多空间

  • 用户界面允许在日志和线性表示之间进行选择,我希望隐藏产生的数字不准确性。

  • 简单地舍入QLineEdit中包含和显示的值不是一个选项,因为在编辑显示值时我会失去准确性

有人知道这个问题的简洁解决方案吗?

下面你找到一个MWE,完整的代码(pyfda)使用小部件和其他丑陋的东西的动态实例化。

# -*- coding: utf-8 -*-
from __future__ import print_function, division
import numpy as np
import sys
from PyQt4 import QtGui

class InputNumFields(QtGui.QWidget):

    def __init__(self, parent):
        super(InputNumFields, self).__init__(parent)
        self.edit_input_float = 10*np.log10(np.pi) # store in log format
        self._init_UI()

    def _init_UI(self):    
        self.edit_input = QtGui.QLineEdit()
        self.edit_input.editingFinished.connect(self.store_entries)
        self.lay_g_main = QtGui.QGridLayout()
        self.lay_g_main.addWidget(self.edit_input, 0, 0)
        self.setLayout(self.lay_g_main)
        self.get_entries()

    def store_entries(self):
        """ Store text entry as log float"""
        self.edit_input_float = 10*np.log10(float(self.edit_input.text()))
        self.get_entries()

    def get_entries(self):
        """ Retrieve float value, delog and convert to string """
        self.edit_input.setText(str(10**(self.edit_input_float/10)))

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    mainw = InputNumFields(None)
    app.setActiveWindow(mainw) 
    mainw.show()
    sys.exit(app.exec_())

2 个答案:

答案 0 :(得分:0)

似乎行为应该是这样的:

  • 当行编辑丢失输入焦点时,显示存储的值圆整
  • 当行修改获得输入焦点时,以完整
  • 显示存储的值
  • 每当编辑完成,请以日志格式存储完整的当前值

这意味着当按下return或enter时,舍入不得(因为在这种情况下,行编辑不会失去焦点)。

通过以下更改可以实现上述行为:

from PyQt4 import QtCore, QtGui

class InputNumFields(QtGui.QWidget):
    ...

    def _init_UI(self):
        self.edit_input = QtGui.QLineEdit()
        self.edit_input.installEventFilter(self)
        ...

    def eventFilter(self, source, event):
        if (event.type() == QtCore.QEvent.FocusIn and
            source is self.edit_input):
            self.get_entries()
        return super(InputNumFields, self).eventFilter(source, event)

    def get_entries(self):
        value = 10**(self.edit_input_float/10)
        if not self.edit_input.hasFocus():
            value = round(value, 3)
        self.edit_input.setText(str(value))

PS:

您可能应该在示例中添加一个按钮或其他内容,以便测试更改焦点的效果。

答案 1 :(得分:0)

我尝试使用信号槽连接(editingFinished)和eventFilter的混合。但是,我遇到了一些奇怪的错误,这些错误可能是由某些竞争条件引起的,或者仅仅是因为代码背后的逻辑变得过于扭曲。无论如何,以下片段效果很好,也许对某些人有用:

def eventFilter(self, source, event):
    """
    Filter all events generated by the QLineEdit widgets. Source and type
    of all events generated by monitored objects are passed to this eventFilter,
    evaluated and passed on to the next hierarchy level.

    - When a QLineEdit widget gains input focus (QEvent.FocusIn`), display
      the stored value with full precision
    - When a key is pressed inside the text field, set the `spec_edited` flag
      to True.
    - When a QLineEdit widget loses input focus (QEvent.FocusOut`), store
      current value in linear format with full precision (only if
      `spec_edited`== True) and display the stored value in selected format
    """
    if isinstance(source, QtGui.QLineEdit): # could be extended for other widgets
        if event.type() == QEvent.FocusIn:
            self.spec_edited = False
            self.get_entries()
        elif event.type() == QEvent.KeyPress:
            self.spec_edited = True
        elif event.type() == QEvent.FocusOut:
            self._store_entries(source)
    # Call base class method to continue normal event processing:
    return super(InputAmpSpecs, self).eventFilter(source, event)