我需要像这样的东西!但在我的测试中,我注意到了一些问题。有些东西可以被删除(例如,
QString post 实际上并没有被使用,可以删除)。此外,从我的测试来看,你的实现中似乎存在一个 bug,如果你输入一系列单词,然后回到中间某个位置输入一个单词,如果你使用箭头键上下移动自动完成列表,第一个高亮显示的单词将被放在正确的位置,但之后光标会跳到末尾(不管是哪个 onLineEditTextChanged() 插槽),然后它开始用自动更正列表中的单词替换最后一个单词。
我创建了自己的实现,其中一个主要区别是我的实现需要一个
delimiter 字符,并且该字符用于代替始终使用空格的情况,我修复了上述描述的 bug。你会发现我的实现非常简单:
DelimitedCompleter.hpp
#ifndef DELIMITEDCOMPLETER_HPP
#define DELIMITEDCOMPLETER_HPP
#include <QCompleter>
class QString;
class QStringList;
class DelimitedCompleter : public QCompleter {
Q_OBJECT
public:
DelimitedCompleter(QLineEdit *parent, char delimiter);
DelimitedCompleter(QLineEdit *parent, char delimiter, QAbstractItemModel *model);
DelimitedCompleter(QLineEdit *parent, char delimiter, const QStringList &list);
QString pathFromIndex(const QModelIndex &index) const;
QStringList splitPath(const QString &path) const;
private:
char delimiter;
mutable int cursor_pos = -1;
void connectSignals();
private slots:
void onActivated(const QString &text);
void onCursorPositionChanged(int old_pos, int new_pos);
};
#endif
DelimitedCompleter.cpp
#include "DelimitedCompleter.hpp"
#include <QDebug>
#include <QLineEdit>
#include <QStringList>
DelimitedCompleter::DelimitedCompleter(QLineEdit *parent, char delimiter)
: QCompleter(parent), delimiter(delimiter) {
parent->setCompleter(this);
connectSignals();
}
DelimitedCompleter::DelimitedCompleter(QLineEdit *parent, char delimiter, QAbstractItemModel *model)
: QCompleter(model, parent), delimiter(delimiter) {
parent->setCompleter(this);
connectSignals();
}
DelimitedCompleter::DelimitedCompleter(QLineEdit *parent, char delimiter, const QStringList &list)
: QCompleter(list, parent), delimiter(delimiter) {
parent->setCompleter(this);
connectSignals();
}
QString DelimitedCompleter::pathFromIndex(const QModelIndex &index) const {
QString auto_string = index.data(Qt::EditRole).toString();
QLineEdit *line_edit = qobject_cast<QLineEdit*>(parent());
QString str = line_edit->text();
if(cursor_pos != -1) line_edit->setCursorPosition(cursor_pos);
else cursor_pos = line_edit->cursorPosition();
int cur_index = line_edit->cursorPosition();
int prev_delimiter_index = str.mid(0, cur_index).lastIndexOf(delimiter);
while(str.at(prev_delimiter_index + 1).isSpace()) prev_delimiter_index++;
int next_delimiter_index = str.indexOf(delimiter, cur_index);
if(next_delimiter_index == -1) {
next_delimiter_index = str.size();
}
QString part1 = str.mid(0, prev_delimiter_index + 1);
QString pre = str.mid(prev_delimiter_index + 1, cur_index - prev_delimiter_index - 1);
QString part2 = str.mid(next_delimiter_index);
return part1 + auto_string + part2;
}
QStringList DelimitedCompleter::splitPath(const QString &path) const {
QLineEdit *line_edit = qobject_cast<QLineEdit*>(parent());
QStringList string_list;
int index = path.mid(0,line_edit->cursorPosition()).lastIndexOf(delimiter) + 1;
QString str = path.mid(index, line_edit->cursorPosition()-index).trimmed();
string_list << str;
return string_list;
}
void DelimitedCompleter::connectSignals() {
connect(this, SIGNAL(activated(const QString &)), this, SLOT(onActivated(const QString &)));
connect(qobject_cast<QLineEdit*>(parent()), SIGNAL(cursorPositionChanged(int, int)),
this, SLOT(onCursorPositionChanged(int, int)));
}
void DelimitedCompleter::onActivated(const QString &text) {
cursor_pos = -1;
}
void DelimitedCompleter::onCursorPositionChanged(int old_pos, int new_pos) {
if(old_pos != cursor_pos) cursor_pos = -1;
}
QLineEdit
的源代码(http://code.woboq.org/qt5/qtbase/src/widgets/widgets/qlineedit.cpp.html),然后从那里开始。 - Kuba hasn't forgotten Monica