在不牺牲内部精度的情况下限制 pyQT QLineEdit 中显示的浮点数
Limit number of displayed float digits in pyQT QLineEdit without sacrificing internal accuracy
我在我的应用程序中使用 QLineEdit 小部件来输入和编辑数字(浮点)值。我想 显示 浮点值的舍入版本,同时保持完整的内部精度。仅在编辑QLineEdit字段时,应显示完整位数。
出于三个原因需要这样做:
对于我的 GUI
,复杂的值需要太多 space
UI 允许在对数和线性表示之间 select,我想隐藏由此产生的数字错误。
简单地四舍五入 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_())
看起来行为应该是这样的:
- 行编辑失去输入焦点时,四舍五入显示存储值
- 行编辑获得输入焦点时,完整显示存储的值
- 每当编辑完成时,以日志格式存储完整的当前值
这意味着当按下 return 或回车时,舍入 绝不能 发生(因为在这种情况下,行编辑不会失去焦点)。
可以通过以下更改实现上述行为:
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:
您可能应该在您的示例中添加一个按钮或其他东西,这样您就可以测试改变焦点的效果。
我尝试混合使用信号槽连接 (editingFinished
) 和 eventFilter。但是,我 运行 发现了一些 st运行ge 错误,这些错误可能是由某些竞争条件引起的,或者仅仅是因为代码背后的逻辑变得过于扭曲。无论如何,以下代码片段效果很好,也许对某些人有帮助:
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)
我在我的应用程序中使用 QLineEdit 小部件来输入和编辑数字(浮点)值。我想 显示 浮点值的舍入版本,同时保持完整的内部精度。仅在编辑QLineEdit字段时,应显示完整位数。
出于三个原因需要这样做:
对于我的 GUI
,复杂的值需要太多 space
UI 允许在对数和线性表示之间 select,我想隐藏由此产生的数字错误。
简单地四舍五入 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_())
看起来行为应该是这样的:
- 行编辑失去输入焦点时,四舍五入显示存储值
- 行编辑获得输入焦点时,完整显示存储的值
- 每当编辑完成时,以日志格式存储完整的当前值
这意味着当按下 return 或回车时,舍入 绝不能 发生(因为在这种情况下,行编辑不会失去焦点)。
可以通过以下更改实现上述行为:
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:
您可能应该在您的示例中添加一个按钮或其他东西,这样您就可以测试改变焦点的效果。
我尝试混合使用信号槽连接 (editingFinished
) 和 eventFilter。但是,我 运行 发现了一些 st运行ge 错误,这些错误可能是由某些竞争条件引起的,或者仅仅是因为代码背后的逻辑变得过于扭曲。无论如何,以下代码片段效果很好,也许对某些人有帮助:
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)