1

我有一个QLineEdit允许QRegularExpressionValidator输入的地方:

^(?<sign>[<>=]|>=|<=)(?<value>\d+\.?\d*)(?<unit>[mc]{0,1}m[²2]\/s|St|cSt)$

例如:

"<15m²/s"   // good
">=3.14cSt" // good
"27mm2/s"   // bad

我搜索了一种QCompleter基于此正则表达式填充 a 的方法。
因此,如果光标位于空白处,QLineEdit则完成者建议:
><、或。 在符号之后,不建议任何内容,在最后一个数字之后,建议:,,,或我的需要是 通过读取允许的和部分正则表达式来创建 a 并将其插入到中,因为它基于 a 。=>=<=

mm²/scm²/sm²/sStcSt
QStringListsignunitQStringListQCompleterQAbstractItemModel

4

1 回答 1

1

我通过子类化找到了一种解决方法,QLineEdit但这不是最好的解决方案。如果有人有更好的,我接受。
lineeditregexgroup.h

#ifndef LINEEDITREGEXGROUP_H
#define LINEEDITREGEXGROUP_H

#include <QLineEdit>
#include <QMap>

class QCompleter;
class QStringListModel;
class QRegularExpression;
class QRegularExpressionValidator;

class LineEditRegexGroup : public QLineEdit
{
    Q_OBJECT

public:
    LineEditRegexGroup(const QString pattern, QWidget *parent = Q_NULLPTR);
    ~LineEditRegexGroup();
    static QMap<QString, QStringList> mapCompleter;

public slots:
    void checkValidity(const QString &text);

protected:
    virtual void mouseReleaseEvent(QMouseEvent *e);

private:
    QString                     curGroup;
    QCompleter                  *completer;
    QStringListModel            *listCompleter;
    QRegularExpression          *regex;
    QRegularExpressionValidator *validator;

};

#endif // LINEEDITREGEXGROUP_H

lineeditregexgroup.cpp

#include "lineeditregexgroup.h"
#include <QCompleter>
#include <QStringListModel>
#include <QRegularExpression>
#include <QRegularExpressionValidator>
#include <QAbstractItemView>

QMap<QString, QStringList> LineEditRegexGroup::mapCompleter = {    
    { "sign", QStringList() << "<" << ">" << "=" << "<=" << ">=" },
    { "unit", QStringList() << "mm²/s" << "cm²/s" << "m²/s" << "St" << "cSt" }
};

LineEditRegexGroup::LineEditRegexGroup(const QString pattern, QWidget *parent)
    : QLineEdit(parent)
{
    completer = new QCompleter(this);
    listCompleter = new QStringListModel(completer);
    regex = new QRegularExpression(pattern, QRegularExpression::NoPatternOption);
    validator = new QRegularExpressionValidator(*regex, this);

    completer->setModel(listCompleter);
    completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
    setCompleter(completer);
    setValidator(validator);
    curGroup = regex->namedCaptureGroups().at(1);

    connect(this, SIGNAL(textEdited(QString)), this, SLOT(checkValidity(QString)));
}

LineEditRegexGroup::~LineEditRegexGroup()
{
    // dtor ...
}

void LineEditRegexGroup::checkValidity(const QString &text)
{
    bool valid = true;
    int nbCapture = 0;
    QRegularExpressionMatch match = regex->match(text);
    for (int i=1; i<=regex->captureCount() && valid; i++){
        /* +1 to check only groups, not the global string */
        valid &= !match.captured(i).isEmpty();
        if (valid)
            nbCapture++;
        curGroup = regex->namedCaptureGroups().at(i);
        if (curGroup == "value")
            curGroup = regex->namedCaptureGroups().at(i-1);
    }
    if (nbCapture < regex->captureCount()){
        QStringList new_model = mapCompleter.value(curGroup);
        if (curGroup == regex->namedCaptureGroups().at(regex->captureCount())){
            new_model.replaceInStrings(QRegularExpression("^(.*)$"), text+"\\1");
        }
        listCompleter->setStringList(new_model);
        completer->complete();
    }
}

void LineEditRegexGroup::mouseReleaseEvent(QMouseEvent *e)
{
    QLineEdit::mouseReleaseEvent(e);
    if (text().isEmpty())
        checkValidity("");
}

并这样称呼它:

new LineEditRegexGroup(
    "^(?:(?<sign>[<>=]|>=|<=|)"
    "(?:(?<value>\\d+\\.?\\d*)"
    "(?:(?<unit>[mc]{0,1}m[²2]\\/s|St|cSt))?)?)?$",
    parent
);

结果
LineEditRegexGroup

于 2017-07-04T07:50:54.823 回答