qt - 忽略变音符号的 QLineEdit/QComboBox 搜索

标签 qt qt5 qcombobox non-ascii-characters

我有一个应用程序,人们可以在其中输入地名。这是欧洲,我们必须处理包含变音符号的名称,例如 Orléans、Köln、Liège、Châteauroux。当人们输入名字时,我希望他们能够在没有变音符号的情况下键入字符,但仍然会列出包含这些名字的名字,以便他们可以选择正确重音的名字。该程序有一个很长但并不详尽的名称列表(人们可以随时输入他们喜欢的任何名称)。

我已经有了一个基于非变音符号匹配查找名称的函数。所以 'orle' 会返回 'Orléans','kol' 会找到 'Köln',等等。

我尝试了两件事:

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

我还玩过 QAbstractItemModel,直到我意识到 QCompleter 对模型返回的数据进行了字符串匹配,所以又是 'orle' != 'orlé'。

2:一个可编辑的QComboBox,该列表根据目前输入的文本动态填充。以下代码是从 QComboBox::editTextChanged(QString) connected() 得到的:

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] 应该是当我找到一些匹配的时候,但是唉。

最佳答案

这应该有效:

使用 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();
}

现在创建包含所有城市(带变音符号的单词)的数据模型,并在一些自定义角色编号下返回不含变音符号的字符串(子类 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);
}

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

关于qt - 忽略变音符号的 QLineEdit/QComboBox 搜索,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31465850/

相关文章:

qt - 如何从 Qt Designer/.ui 文件将项目数据添加到 QComboBox

qt - QProgressDialog 不立即显示

c++ - Qt 5.7 堆叠条形图在数据更新时自动重新缩放 y 轴

c++ - 在 QTreeview 中使用 QCombobox 委托(delegate)项

c++ - 如何在 QML 中显示 QSqlQueryModel?

c++ - Qprocess 参数回显和管道

Qt - 如何在 QComboBox 中使用富文本?

c++ - 从 Qt4 中的文本文件中逐字读取

Qt Creator 帮助 : Font size is too small

python - 有没有办法在 PySide 中设置 QtabWidget 上的选项卡按钮的样式?