如何在实现自定义输入逻辑的同时使用QLineEdit内置的撤消/重做功能?
我正在为收银员的高效工作实现一个金额的自定义编辑器。基本功能有:
- 格式始终为
^d+,d{2}$
- 当光标保留为逗号时,它会编辑整数部分(例如,当编辑0,00时,第一个数字输入将替换零;即,在输入"1"后,0,00变为1,00)
- 输入的逗号或句点将光标移动到小数部分
- 删除和退格遵循格式
我不能使用口罩,因为如果没有不必要的空间,口罩就无法管理任意长度。我不能使用验证器,因为它们不够灵活,无法处理在位编辑前导零的逻辑。这就是为什么我扬弃了QLineEdit
,并自己编写了必要的逻辑。
问题是:有没有一种方法可以在QLineEdit自己的逻辑上支持撤消功能?我使用setText()
,它重置撤消/重做历史。我可以制作两个状态堆栈,并相应地覆盖undo()
和redo()
,或者制作选择和插入/删除的序列(这可能会导致不必要的闪烁),但我觉得可能有更简单的方法。
class MoneyLineEdit : public QLineEdit {
Q_OBJECT
public:
MoneyLineEdit(QWidget *parent = 0);
protected:
void keyPressEvent(QKeyEvent * event);
};
void MoneyLineEdit::keyPressEvent(QKeyEvent *event) {
if (event->key() == Qt::Key_Comma || event->key() == Qt::Key_Period) {
setCursorPosition(text().length() - 2);
} else {
QString text = this->text();
int pos = cursorPosition();
if (event->key() == Qt::Key_Backspace) {
if (pos == text.length()) {
text.replace(text.length() - 1, 1, QChar('0'));
--pos;
} else if (pos == text.length() - 1) {
text.replace(text.length() - 2, 1, text.at(text.length() - 1));
text.replace(text.length() - 1, 1, QChar('0'));
--pos;
} else if (pos == text.length() - 2) {
--pos;
} else if (text.length() == 4 && pos == 1) {
text.replace(0, 1, QChar('0'));
}
setText(text);
setCursorPosition(pos);
} else if ((pos == text.length() - 3 || pos == text.length() - 2) && event->key() == Qt::Key_Delete && selectionStart() == -1){
text.replace(text.length() - 2, 1, text.at(text.length() - 1));
text.replace(text.length() - 1, 1, QChar('0'));
setText(text);
setCursorPosition(pos);
} else if (pos >= text.length() - 2 && pos <= text.length() - 1 && !event->text().isEmpty()){
text.replace(cursorPosition(), 1, event->text());
++pos;
setText(text);
setCursorPosition(pos);
} else if ((pos == 0 || pos == 1) && !text.isEmpty() && text.length() == 4 && text.at(0) == QChar('0') && !event->text().isEmpty()) {
text.replace(0, 1, event->text());
setText(text);
setCursorPosition(1);
} else {
QLineEdit::keyPressEvent(event);
}
}
}
显然,undo()/redo()
过载的两个Pair堆栈(text,cursorPosition)就足够了。