使用箭头键时根据光标位置更改 QDoubleSpinBox 中的 singleStep
Change singleStep in a QDoubleSpinBox depending on the cursor position when using arrow keys
我想使 QDoubleSpinBox
可通过箭头键控制,即在选中框时按下向上键时增加值,按下时减小值。我目前通过将 singleStep
设置为某个值来做到这一点。但是,我希望能够在编辑字段时根据光标位置更改 singleStep
的值。
例如一个有两位小数的框,1.23
,如果光标|
在第一位小数1.2|3
我想增加或减少0.1
但是如果光标位于小数点后第二位 1.23|
我只想 increase/decrease 乘以 0.01.
注意:不确定是否相关,但我目前将 keyboardTracking
设置为 False
以避免在通过数字键输入值编辑值时发出信号。使用错误键时仍会发出这些值。
实现这一点的最简单方法可能是创建 QDoubleSpinBox 的子类并覆盖虚拟 stepBy() 方法。每次要增加或减少该值时都会调用它。这是一个简单的示例,展示了如何为整数旋转框执行此操作。对于浮点值,只需将 singleStep 大小固定为最小小数步长,并在 stepBy() 中更仔细地解析文本,将小数点考虑在内。
class MySpinBox : public QSpinBox
{
public:
explicit MySpinBox(QWidget *parent = nullptr)
: QSpinBox(parent) {
setMaximum(9999);
setValue(5000);
};
void stepBy(int steps) override {
const int cursorPos = qMax(lineEdit()->cursorPosition(), 1);
const int textLen = lineEdit()->text().length();
for (int i = textLen - cursorPos; i > 0; i--)
steps *= 10;
QAbstractSpinBox::stepBy(steps);
lineEdit()->setCursorPosition(cursorPos);
}
};
继 之后,我也在 PyQt 中重新定义了 stepBy
。由于我正在寻找适用于浮点数和负值的解决方案,因此我必须处理一些特殊情况,并通过重新定义 textFromValue
来显示正值的 + 号。特殊情况在下面的解决方案中评论:
import sys
from PyQt5.QtWidgets import QDoubleSpinBox, QMainWindow, QApplication, QLabel
class MyQDoubleSpinBox(QDoubleSpinBox):
def textFromValue(self, value):
# show + sign for positive values
text = super().textFromValue(value)
if value >= 0:
text = "+" + text
return text
def stepBy(self, steps):
cursor_position = self.lineEdit().cursorPosition()
# number of characters before the decimal separator including +/- sign
n_chars_before_sep = len(str(abs(int(self.value())))) + 1
if cursor_position == 0:
# set the cursor right of the +/- sign
self.lineEdit().setCursorPosition(1)
cursor_position = self.lineEdit().cursorPosition()
single_step = 10 ** (n_chars_before_sep - cursor_position)
# Handle decimal separator. Step should be 0.1 if cursor is at `1.|23` or
# `1.2|3`.
if cursor_position >= n_chars_before_sep + 2:
single_step = 10 * single_step
# Change single step and perform the step
self.setSingleStep(single_step)
super().stepBy(steps)
# Undo selection of the whole text.
self.lineEdit().deselect()
# Handle cases where the number of characters before the decimal separator
# changes. Step size should remain the same.
new_n_chars_before_sep = len(str(abs(int(self.value())))) + 1
if new_n_chars_before_sep < n_chars_before_sep:
cursor_position -= 1
elif new_n_chars_before_sep > n_chars_before_sep:
cursor_position += 1
self.lineEdit().setCursorPosition(cursor_position)
class Window(QMainWindow):
def __init__(self):
super().__init__()
self.setGeometry(100, 100, 600, 400)
self.UiComponents()
self.show()
def UiComponents(self):
self.spin = MyQDoubleSpinBox(self)
self.spin.setGeometry(100, 100, 150, 40)
self.spin.setRange(-10000, 10000)
self.spin.setValue(50)
self.spin.setKeyboardTracking(False)
if __name__ == "__main__":
App = QApplication(sys.argv)
window = Window()
sys.exit(App.exec())
我想使 QDoubleSpinBox
可通过箭头键控制,即在选中框时按下向上键时增加值,按下时减小值。我目前通过将 singleStep
设置为某个值来做到这一点。但是,我希望能够在编辑字段时根据光标位置更改 singleStep
的值。
例如一个有两位小数的框,1.23
,如果光标|
在第一位小数1.2|3
我想增加或减少0.1
但是如果光标位于小数点后第二位 1.23|
我只想 increase/decrease 乘以 0.01.
注意:不确定是否相关,但我目前将 keyboardTracking
设置为 False
以避免在通过数字键输入值编辑值时发出信号。使用错误键时仍会发出这些值。
实现这一点的最简单方法可能是创建 QDoubleSpinBox 的子类并覆盖虚拟 stepBy() 方法。每次要增加或减少该值时都会调用它。这是一个简单的示例,展示了如何为整数旋转框执行此操作。对于浮点值,只需将 singleStep 大小固定为最小小数步长,并在 stepBy() 中更仔细地解析文本,将小数点考虑在内。
class MySpinBox : public QSpinBox
{
public:
explicit MySpinBox(QWidget *parent = nullptr)
: QSpinBox(parent) {
setMaximum(9999);
setValue(5000);
};
void stepBy(int steps) override {
const int cursorPos = qMax(lineEdit()->cursorPosition(), 1);
const int textLen = lineEdit()->text().length();
for (int i = textLen - cursorPos; i > 0; i--)
steps *= 10;
QAbstractSpinBox::stepBy(steps);
lineEdit()->setCursorPosition(cursorPos);
}
};
继 stepBy
。由于我正在寻找适用于浮点数和负值的解决方案,因此我必须处理一些特殊情况,并通过重新定义 textFromValue
来显示正值的 + 号。特殊情况在下面的解决方案中评论:
import sys
from PyQt5.QtWidgets import QDoubleSpinBox, QMainWindow, QApplication, QLabel
class MyQDoubleSpinBox(QDoubleSpinBox):
def textFromValue(self, value):
# show + sign for positive values
text = super().textFromValue(value)
if value >= 0:
text = "+" + text
return text
def stepBy(self, steps):
cursor_position = self.lineEdit().cursorPosition()
# number of characters before the decimal separator including +/- sign
n_chars_before_sep = len(str(abs(int(self.value())))) + 1
if cursor_position == 0:
# set the cursor right of the +/- sign
self.lineEdit().setCursorPosition(1)
cursor_position = self.lineEdit().cursorPosition()
single_step = 10 ** (n_chars_before_sep - cursor_position)
# Handle decimal separator. Step should be 0.1 if cursor is at `1.|23` or
# `1.2|3`.
if cursor_position >= n_chars_before_sep + 2:
single_step = 10 * single_step
# Change single step and perform the step
self.setSingleStep(single_step)
super().stepBy(steps)
# Undo selection of the whole text.
self.lineEdit().deselect()
# Handle cases where the number of characters before the decimal separator
# changes. Step size should remain the same.
new_n_chars_before_sep = len(str(abs(int(self.value())))) + 1
if new_n_chars_before_sep < n_chars_before_sep:
cursor_position -= 1
elif new_n_chars_before_sep > n_chars_before_sep:
cursor_position += 1
self.lineEdit().setCursorPosition(cursor_position)
class Window(QMainWindow):
def __init__(self):
super().__init__()
self.setGeometry(100, 100, 600, 400)
self.UiComponents()
self.show()
def UiComponents(self):
self.spin = MyQDoubleSpinBox(self)
self.spin.setGeometry(100, 100, 150, 40)
self.spin.setRange(-10000, 10000)
self.spin.setValue(50)
self.spin.setKeyboardTracking(False)
if __name__ == "__main__":
App = QApplication(sys.argv)
window = Window()
sys.exit(App.exec())