Как установить маску ввода и QValidator для QLineEdit одновременно в Qt?
Я хочу редактировать строку, которая принимает IP-адрес. Если я дам маску ввода как:
ui->lineEdit->setInputMask("000.000.000.000");
Он принимает значения больше 255. Если я даю валидатор, мы должны ставить точку (.) После каждых трех цифр. Какой лучший способ справиться с этим?
4 ответа
Он принимает значение больше 255.
Абсолютно, потому что "0" означает это:
ASCII digit permitted but not required.
Как видите, это не ваша чашка чая. Есть как минимум следующие способы обойти это:
Написать собственный валидатор
Используйте регулярное выражение
Разделите входные данные на четыре записи и проверьте каждую запись самостоятельно, при этом все еще сохраняя визуальные разделители между записями.
Решение регулярных выражений будет, вероятно, быстрым, но и самым уродливым ИМХО:
QString ipRange = "(?:[0-1]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])";
// You may want to use QRegularExpression for new code with Qt 5 (not mandatory).
QRegExp ipRegex ("^" + ipRange
+ "\\." + ipRange
+ "\\." + ipRange
+ "\\." + ipRange + "$");
QRegExpValidator *ipValidator = new QRegExpValidator(ipRegex, this);
lineEdit->setValidator(ipValidator);
Отказ от ответственности: это будет правильно проверять только IP4-адреса, поэтому он не будет работать для IP6, если вам это понадобится в будущем.
Более простой способ - попробовать опцию inputmask
ui->lineEdit_IP->setInputMask( "000.000.000.000" );
и в вашем коде проверки используйте следующее простое условие
QHostAddress myIP;
if( myIP.setAddress( ui->lineEdit_IP->text()) )
qDebug()<<"Valid IP Address";
else
qDebug()<<"Invalid IP address";
Привет у меня была почти такая же проблема. Решения с inputmask или regExp были неудовлетворительными. Я решил сделать свой собственный велосипед.
Заголовок:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QLineEdit>
#include <QFrame>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
//=============================================================================
class CustomIpEditor : public QFrame
{
Q_OBJECT
public:
explicit CustomIpEditor(QWidget *parent = 0);
virtual ~CustomIpEditor() {}
};
//=============================================================================
class CustomLineEdit : public QLineEdit
{
Q_OBJECT
public:
explicit CustomLineEdit(const QString & contents = "", QWidget *parent = 0);
virtual ~CustomLineEdit() {}
signals:
void jumpForward();
void jumpBackward();
public slots:
void jumpIn();
protected:
virtual void focusInEvent(QFocusEvent *event);
virtual void keyPressEvent(QKeyEvent * event);
virtual void mouseReleaseEvent(QMouseEvent *event);
private:
bool selectOnMouseRelease;
};
#endif // MAINWINDOW_H
Источник:
#include <QVBoxLayout>
#include <QKeyEvent>
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
centralWidget()->setLayout(new QVBoxLayout);
CustomIpEditor *myed = new CustomIpEditor;
centralWidget()->layout()->addWidget(myed);
}
MainWindow::~MainWindow()
{
delete ui;
}
//=============================================================================
CustomLineEdit::CustomLineEdit(const QString & contents, QWidget *parent) :
QLineEdit(contents, parent), selectOnMouseRelease(false)
{
QIntValidator *valid = new QIntValidator(0, 255, this);
setValidator(valid);
}
void CustomLineEdit::jumpIn()
{
setFocus();
selectOnMouseRelease = false;
selectAll();
}
void CustomLineEdit::focusInEvent(QFocusEvent *event)
{
QLineEdit::focusInEvent(event);
selectOnMouseRelease = true;
}
void CustomLineEdit::keyPressEvent(QKeyEvent * event)
{
int key = event->key();
int cursorPos = cursorPosition();
// Jump forward by Space
if (key == Qt::Key_Space) {
emit jumpForward();
event->accept();
return;
}
// Jump Backward only from 0 cursor position
if (cursorPos == 0) {
if ((key == Qt::Key_Left) || (key == Qt::Key_Backspace)) {
emit jumpBackward();
event->accept();
return;
}
}
// Jump forward from last postion by right arrow
if (cursorPos == text().count()) {
if (key == Qt::Key_Right) {
emit jumpForward();
event->accept();
return;
}
}
// After key is placed cursor has new position
QLineEdit::keyPressEvent(event);
int freshCurPos = cursorPosition();
if ((freshCurPos == 3) && (key != Qt::Key_Right))
emit jumpForward();
}
void CustomLineEdit::mouseReleaseEvent(QMouseEvent *event)
{
if(!selectOnMouseRelease)
return;
selectOnMouseRelease = false;
selectAll();
QLineEdit::mouseReleaseEvent(event);
}
//=============================================================================
void makeCommonStyle(QLineEdit* line) {
line->setContentsMargins(0, 0, 0, 0);
line->setAlignment(Qt::AlignCenter);
line->setStyleSheet("QLineEdit { border: 0px none; }");
line->setFrame(false);
line->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
}
QLineEdit* makeIpSpliter() {
QLineEdit *spliter = new QLineEdit(".");
makeCommonStyle(spliter);
spliter->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
spliter->setMaximumWidth(10);
spliter->setReadOnly(true);
spliter->setFocusPolicy(Qt::NoFocus);
return spliter;
}
CustomIpEditor::CustomIpEditor(QWidget *parent) :
QFrame(parent)
{
setContentsMargins(0, 0, 0, 0);
setStyleSheet("QFrame { background-color: white; border: 1px solid white; border-radius: 15px; }");
QList <CustomLineEdit *> lines;
QList <CustomLineEdit *>::iterator linesIterator;
lines.append(new CustomLineEdit);
lines.append(new CustomLineEdit);
lines.append(new CustomLineEdit);
lines.append(new CustomLineEdit);
QHBoxLayout *mainLayout = new QHBoxLayout;
mainLayout->setSpacing(0);
setLayout(mainLayout);
for (linesIterator = lines.begin(); linesIterator != lines.end(); ++linesIterator) {
makeCommonStyle(*linesIterator);
mainLayout->addWidget(*linesIterator);
if (*linesIterator != lines.last()) {
connect(*linesIterator, &CustomLineEdit::jumpForward,
*(linesIterator+1), &CustomLineEdit::jumpIn);
mainLayout->addWidget(makeIpSpliter());
}
if (*linesIterator != lines.first()) {
connect(*linesIterator, &CustomLineEdit::jumpBackward,
*(linesIterator-1), &CustomLineEdit::jumpIn);
}
}
}
Для тех, кто интересуется следующей подсказкой в доку QT:
Чтобы получить контроль диапазона (например, для IP-адреса), используйте маски вместе с валидаторами.
В этом случае валидатор должен позаботиться о пробелах. Поэтому мое решение, адаптированное из ответа lpapp и этого сообщения на форуме Qt, гласит:
QString ipRange = "(([ 0]+)|([ 0]*[0-9] *)|([0-9][0-9] )|([ 0][0-9][0-9])|(1[0-9][0-9])|([2][0-4][0-9])|(25[0-5]))";
// You may want to use QRegularExpression for new code with Qt 5 (not mandatory).
QRegExp ipRegex ("^" + ipRange
+ "\\." + ipRange
+ "\\." + ipRange
+ "\\." + ipRange + "$");
QRegExpValidator *ipValidator = new QRegExpValidator(ipRegex, this);
lineEdit->setValidator(ipValidator);
lineEdit->setInputMask("000.000.000.000");
// Avoid having to move cursor before typing
linEdit->setCursorPosition(0);
Я новичок в использовании регулярных выражений, поэтому не стесняйтесь рекомендовать улучшения.
Согласно ответу Аруна Кумара К.С.:
Если myIP.setAddress()
был успешным, вы можете записать ip обратно в строку редактирования в виде форматированной строки:
ui->lineEdit->setText(myIP->toString());
Следовательно, вам не обязательно устанавливать маску (ни валидатор, ни регулярное выражение).
Обратите внимание, что setAddress() записывает / перезаписывает ваш myIP также, если он не может прочитать IP. Таким образом, вызов toString() в этом случае приводит к пустой строке.