序文
最近はガジェットインターフェース上にIP編集ボックスが使われていますが、現在は編集ボックスQLineEditを直接配置していますが、個人利用なのであまり制限を書く必要はありません。ただし、時間に余裕がある場合は、公式のもの (つまり、QLineEdit に基づいて直接セットアップ)、オンラインのもの (QLineEdit によって接続されたもの)、およびカスタマイズされたもの (オンラインのものと自己改善) を使用してみてください。
効果
成し遂げる
公式 (単一の QLineEdit)
公式には単一の QLineEdit 上で正規表現とマスクを直接設定する方法があり、コードは次のとおりですが、効果はあまり良くありません。
- カーソルは太くて黒く、単一の文字を選択して変更するモードに属します。
- コンテンツがボックス全体に散らばっておらず、配置を中央に変更しても左に変更しても見栄えがよくありません。
- また、プレースホルダーをスペースにすると、今の数字が何番か分からなくなるので、2番目の数字を選択して「192」と入力すると、そのまま「19.2」になることが多いです。
QRegExp rx("((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)");
QRegExpValidator *pReg = new QRegExpValidator(rx, this);
ui->lineEdit->setValidator(pReg);
ui->lineEdit->setInputMask("000.000.000.000; ");
正規表現における各記号の説明:
- \d: [0-9] に相当する数値と一致します。
- \.: 小数点と一致します
- ?: 前の内容を 0 回または 1 回繰り返すことを示します
- 2[0-4]\\d: 200 ~ 249 の値をカバーします
- 25[0-5]: 250 ~ 255 の値をカバーします
- [01]?\\d\\d?:0~199の値をカバーします
正規表現オンライン テスト ツール:正規表現オンライン テスト | ルーキー ツール
オンライン (複数の QLineEdit スプライシング)
github で見つけたアドレスは次のとおりです: https://github.com/KingBright965/QtIPEdit/blob/master/IPEdit.cpp
- 全体とコンテンツの制御: 複数の QLineEdit と QLabel で構成され、各 QLineEdit は正規表現で設定され、同時に各部分の最大長を 3 に制御するために、エディット ボックスのコンテンツ編集を監視します現在の長さは 3 なので、次の編集ボックスに移動します。
void IPEdit::initForEdit(QLineEdit* edit)
{
edit->setFrame(false);
edit->setAlignment(Qt::AlignCenter);
edit->installEventFilter(this);
QRegExpValidator* validator = new QRegExpValidator(QRegExp("^(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)$"), this);
edit->setValidator(validator);
connect(edit, SIGNAL(textChanged(const QString&)), this, SLOT(editTextChanged(const QString&)));
}
void IPEdit::editTextChanged(const QString& text)
{
QLineEdit* curEdit = qobject_cast<QLineEdit*>(sender());
if (text.size() == 3)
{
QLineEdit* next = nextEdit(curEdit);
if (next)
{
next->setFocus();
next->selectAll();
}
}
}
- イベント応答: イベント フィルタリング、キー ポイント (Qt::Key_Period) の監視、イベントの貼り付け (QKeySequence::Paste) を追加しました。
bool IPEdit::eventFilter(QObject* object, QEvent* event)
{
if (isEdit(object))
{
if (event->type() == QEvent::KeyPress)
{
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
if (keyEvent->key() == Qt::Key_Period)
{
QLineEdit* next = nextEdit(qobject_cast<QLineEdit*>(object));
if (next)
{
next->setFocus();
next->selectAll();
}
}
else if (keyEvent->matches(QKeySequence::Paste))
{
QString clip = QApplication::clipboard()->text(QClipboard::Clipboard);
if (clip.split(".").size() == 4)
{
setText(clip);
return true;
}
}
}
}
return QWidget::eventFilter(object, event);
}
- 入出力:
QString IPEdit::text()
{
QString sec1 = m_edit1->text().isEmpty() ? "0" : m_edit1->text();
QString sec2 = m_edit2->text().isEmpty() ? "0" : m_edit2->text();
QString sec3 = m_edit3->text().isEmpty() ? "0" : m_edit3->text();
QString sec4 = m_edit4->text().isEmpty() ? "0" : m_edit4->text();
return QString("%1.%2.%3.%4").arg(sec1).arg(sec2).arg(sec3).arg(sec4);
}
void IPEdit::setText(const QString& text)
{
QRegExp reg("^((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)$");
if (!reg.exactMatch(text))
return;
QStringList ips = text.split(".");
m_edit1->setText(ips.at(0));
m_edit2->setText(ips.at(1));
m_edit3->setText(ips.at(2));
m_edit4->setText(ips.at(3));
}
- スタイル: スタイルを編集ボックスと一致させるために、描画イベントを書き換えます。
void IPEdit::paintEvent(QPaintEvent* event)
{
QPainter painter(this);
QStyleOptionFrame option;
option.initFrom(this);
option.lineWidth = 1;
style()->drawPrimitive(QStyle::PE_PanelLineEdit, &option, &painter, this);
QWidget::paintEvent(event);
}
カスタマイズ(オンラインで改善)
Windows の IP 設定のエディットボックスを参考にしましたが、インターネット上の例と比較すると、効果が若干異なります。
- タブキーのフォーカス切り替えが異なり、オンラインサンプル(QLineEdit)では各部のフォーカスが切り替わりますが、Windowsでは切り替わりません。
- 上下左右キーのカーソル位置をまたがることができます (QLineEdit に隣接) インターネット上には例がありませんが、Windows では例があります。
- バックスペース (Qt::Key_Backspace) はスパンを削除します。
これら 2 つの側面を改善しました。コードは次のとおりです。
- タブキーのフォーカス切り替え:エディットボックスはデフォルトでタブキーのフォーカス切り替えとクリック(Qt::StrongFocus)に反応するので、最初のエディットボックス以外はすべてクリックフォーカス切り替えに設定し、タブには反応しなくなりましたキーフォーカスの切り替え。
ui->lineEdit_2->setFocusPolicy(Qt::ClickFocus);
ui->lineEdit_3->setFocusPolicy(Qt::ClickFocus);
ui->lineEdit_4->setFocusPolicy(Qt::ClickFocus);
上下左右キーを使用したカーソル位置の移動:
bool MyIpLinEdit::eventFilter(QObject *object, QEvent *event)
{
if(object==ui->lineEdit||object==ui->lineEdit_2||object==ui->lineEdit_3||
object==ui->lineEdit_4)
{
if (event->type() == QEvent::KeyPress)
{
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
if(keyEvent->key()==Qt::Key_Left||keyEvent->key()==Qt::Key_Up){
cursorForwardPosition(static_cast<QLineEdit*>(object));
}else if(keyEvent->key()==Qt::Key_Right||keyEvent->key()==Qt::Key_Down){
cursorBackwardPosition(static_cast<QLineEdit*>(object));
}
...
}
}
return QWidget::eventFilter(object, event);
}
void MyIpLinEdit::cursorBackwardPosition(QLineEdit *lineEdit)
{
int pos=lineEdit->cursorPosition();
int len=lineEdit->text().length();
if(pos==len){
QLineEdit* pDestLineEdit=nullptr;
if(lineEdit==ui->lineEdit){
pDestLineEdit=ui->lineEdit_2;
}else if(lineEdit==ui->lineEdit_2){
pDestLineEdit=ui->lineEdit_3;
}else if(lineEdit==ui->lineEdit_3){
pDestLineEdit=ui->lineEdit_4;
}else if(lineEdit==ui->lineEdit_4){
pDestLineEdit=ui->lineEdit;
}
pDestLineEdit->setFocus();
pDestLineEdit->setCursorPosition(0);
}
}
void MyIpLinEdit::cursorForwardPosition(QLineEdit *lineEdit)
{
int pos=lineEdit->cursorPosition();
if(pos==0){
QLineEdit* pDestLineEdit=nullptr;
if(lineEdit==ui->lineEdit){
pDestLineEdit=ui->lineEdit_4;
}else if(lineEdit==ui->lineEdit_2){
pDestLineEdit=ui->lineEdit;
}else if(lineEdit==ui->lineEdit_3){
pDestLineEdit=ui->lineEdit_2;
}else if(lineEdit==ui->lineEdit_4){
pDestLineEdit=ui->lineEdit_3;
}
pDestLineEdit->setFocus();
int len=pDestLineEdit->text().length();
pDestLineEdit->setCursorPosition(len);
}
}
バックスペースキー:
bool MyIpLinEdit::eventFilter(QObject *object, QEvent *event)
{
....
else if(keyEvent->key()==Qt::Key_Backspace){
moveOfDeleteOnecharacter(qobject_cast<QLineEdit*>(object));
}
....
}
void MyIpLinEdit::moveOfDeleteOnecharacter(QLineEdit *lineEdit)
{
int len=lineEdit->text().length();
if(len==0){
QLineEdit* previous=previousEdit(lineEdit);
if(previous){
previous->setFocus();
int len=previous->text().length();
previous->setCursorPosition(len);
}
}
}
QLineEdit *MyIpLinEdit::previousEdit(QLineEdit *curEdit)
{
if (curEdit == ui->lineEdit_2)
return ui->lineEdit;
else if (curEdit == ui->lineEdit_3)
return ui->lineEdit_2;
else if (curEdit == ui->lineEdit_4)
return ui->lineEdit_3;
else
return NULL;
}