我有一个应用程序,人们可以在其中输入表格中的地点名称。在欧洲,我们必须处理包括奥尔良,科隆,列日,沙托鲁等变音符号的名称。当人们输入姓名时,我希望他们能够输入不带变音符号的字符,但仍然会提供包含姓名的姓名列表,以便他们可以选择适当的重音名称。该程序具有很长但不完整的名称列表(人们可以随时输入他们喜欢的任何名称)。
我已经有一个基于非音素匹配来查找名称的函数。因此,“ 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);
}
我测试了它的完美表现。注意在实践中,我在这里粘贴了完整的代码(只是省略了一些明显的东西),因此解决方案非常简单。