カスタム入力ロジックを実装しながら、QLineEdit の組み込みの元に戻す/やり直し機能を使用する方法は?
レジ係の効率的な作業のために、金額のカスタム エディターを実装しています。基本的な機能は次のとおりです。
- フォーマットは常に
^\d+,\d{2}$
; - カーソルをコンマに置いたままにすると、整数部分が編集されます (たとえば、0,00 が編集されると、最初の数字入力がゼロに置き換わります。つまり、'1' が入力された後、0,00 は 1,00 になります)。
- カンマまたはピリオドを入力すると、カーソルが小数部分に移動します。
- 削除とバックスペースはフォーマットに従います。
不必要なスペースなしで任意の長さを管理できないため、マスクを使用できません。バリデーターは、先頭のゼロを編集するロジックを処理するのに十分な柔軟性がないため、使用できません。そのためQLineEdit
、必要なロジックを自分でサブクラス化して記述しました。
問題は、QLineEdit 独自のロジックで元に戻す機能をサポートする方法はありますか? setText()
元に戻す/やり直しの履歴をリセットする を使用します。状態の 2 つのスタックを作成し、それ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);
}
}
}