我有一个应用程序,人们可以在其中输入表格中的地点名称。在欧洲,我们必须处理包括奥尔良,科隆,列日,沙托鲁等变音符号的名称。当人们输入姓名时,我希望他们能够输入不带变音符号的字符,但仍然会提供包含姓名的姓名列表,以便他们可以选择适当的重音名称。该程序具有很长但不完整的名称列表(人们可以随时输入他们喜欢的任何名称)。

我已经有一个基于非音素匹配来查找名称的函数。因此,“ orle”将返回“Orléans”,“ kol”将返回“Köln”,等等。

我尝试了两件事:

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

我还玩了一个QAbstractItemModel,直到意识到QCompleter对Model返回的数据进行了字符串匹配,所以再次使用'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]应该是当我找到一些比赛时,但是a。

最佳答案

这应该工作:

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


我测试了它的完美表现。注意在实践中,我在这里粘贴了完整的代码(只是省略了一些明显的东西),因此解决方案非常简单。

10-07 12:43