首页 文章

QLineEdit / QComboBox搜索忽略变音符号

提问于
浏览
3

我有一个应用程序,人们可以在表单中输入地点的名称 . 这是欧洲,我们必须处理包括奥尔良,科隆,列日,沙托鲁等变音符号在内的名称 . 当人们输入名字时,我希望他们能够在没有变音符号的情况下输入字符,但仍然会提供包含它们的名称列表,以便他们可以选择正确的重音名称 . 该程序有一个很长但没有详尽的名单(人们可以随时输入他们喜欢的任何名字) .

我已经有一个函数可以根据非变音符号匹配查找名称 . 所以'orle'将返回'Orléans','kol'找到'Köln'等 .

我尝试了两件事:

1:带有QCompleter的 QLineEdit ,使用QStringListModel填充匹配器中的列表 . 不幸的是,这不起作用,因为列表将包含名称的重音版本,该版本与用户输入的值不匹配,因此QLineEdit不会在弹出窗口中显示名称(如果有的话) .

我还使用了QAbstractItemModel,直到我意识到QCompleter对模型返回的数据进行了字符串匹配,所以再次'orle'!='orlé' .

2:可编辑的 QComboBox 哪个列表会根据到目前为止输入的文本动态填充 . 以下代码是从QComboBox :: editTextChanged(QString)连接()编辑的:

void TripFormCargoHelper::fromEdited (const QString &str)
{
  if (str.length () >= 3)
  {
    QStringList flist = m_database->findLocationStrings (str);
    flist.push_front (str); // add the text we're editing first
    bool b = box->blockSignals (true); // prevent recursive signals
    box->clear ();
    box->addItems (flist);
    box->blockSignals (b);
    box->showPopup ();
  }
  else
  {
    box->clear ();
    box->hidePopup ();
  }

}

这有效,但只有一半...我想在输入一些字符时显示弹出窗口[1],但这会从行编辑中删除焦点 . 单击行编辑将关闭弹出窗口,因此我最终得到了一个catch-22(人们应该能够继续键入字符,缩小搜索范围) .

任何关于如何使这项工作的建议将不胜感激 . 我更喜欢使用QLineEdit的解决方案 . 版本是Qt 5.4 .

[1]应该是我找到一些比赛,但唉 .

1 回答

  • 1

    这应该有效:

    使用 QCompleter 解决方案 .
    创建继承此 QCompleter 的类并重新实现 QCompleter::splitPath

    DiacriticFreeCompleter::DiacriticFreeCompleter(QObject *parent)
        : QCompleter(parent)
    {
    }
    
    QStringList DiacriticFreeCompleter::splitPath(const QString &path) const
    {
        return QStringList() << ClearedFromDiacritic(path);
    }
    
    QString DiacriticFreeCompleter::pathFromIndex(const QModelIndex &index) const
    {
        // needed to use original value when value is selected
        return index.data().toString();
    }
    

    现在包含所有城市(包含变音符号的单词)和一些自定义角色编号返回字符串的crate数据模型是免费的变音符号(子类QStringListModel可能是最简单的方法,只需重新实现data来专门处理这个角色值):

    DiactricFreeStringListModel::DiactricFreeStringListModel(QObject *parent)
        : QStringListModel(parent)
    {
        setDiactricFreeRole(Qt::UserRole+10);
    }
    
    QVariant DiactricFreeStringListModel::data(const QModelIndex &index, int role) const
    {
        if (role==diactricFreeRole()) {
            QString value = QStringListModel::data(index, Qt::DisplayRole).toString();
            return ClearedFromDiacritic(value);
        } else {
            return QStringListModel::data(index, role);
        }
    }
    
    void DiactricFreeStringListModel::setDiactricFreeRole(int role)
    {
        mDiactricFreeRole = role;
    }
    
    int DiactricFreeStringListModel::diactricFreeRole() const
    {
        return mDiactricFreeRole;
    }
    

    现在连接此模型与 QCompleter 将此特殊角色值设置为completionRole,一切都应该完美 .

    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        DiacriticFreeCompleter *completer = new DiacriticFreeCompleter(this);
        DiactricFreeStringListModel *model = new DiactricFreeStringListModel(this);
        completer->setModel(model);
        completer->setCompletionRole(model->diactricFreeRole());
        model->setStringList(QStringList()
                             << "Kraków"
                             << "Łba"
                             << "Żarów"
                             << "Źródło"
                             << "Łęg"
                             << "London"
                             << "München"
                             << "Orléans"
                             << "Köln"
                             << "Liège"
                             << "Châteauroux");
        ui->lineEdit->setCompleter(completer);
    }
    

    我测试过它完美无缺 . 注意在实践中我已经粘贴了完整的代码(只是省略了一些明显的东西),所以解决方案非常简单 .

相关问题