我需要這樣的東西!但是在我的測試中,我注意到了一些東西,有些東西可以被刪除(例如,QString文章未被實際使用,它可以被刪除)。另外,如果你輸入一個單詞列表,那麼在你的實現中似乎存在一個錯誤(至少從我的測試中),如果你使用箭頭鍵上/下,回去在中間的某個地方輸入一個單詞在自動完成列表中,第一個突出顯示的單詞將被放置在正確的位置,但在此之後,光標跳轉到結尾(不管onLineEditTextChanged()槽位),然後它開始用自動更正列表中的單詞替換最後一個單詞。
我創造了我自己的實現,主要的區別是我的執行需要一個分隔人物之一,該字符代替總是使用白色空間,我固定的,我上面描述的錯誤。你會發現我的實現是相當更加簡單:
DelimitedCompleter.hpp
#ifndef DELIMITEDCOMPLETER_HPP
#define DELIMITEDCOMPLETER_HPP
#include <QCompleter>
class QString;
class QStringList;
/**
* class DelimitedCompleter
*
* QCompleter that supports completing multiple words in a QLineEdit, completed words are separated
* by delimiter.
*/
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 PUBLIC METHODS *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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 position was saved, restore it, else save it
if(cursor_pos != -1) line_edit->setCursorPosition(cursor_pos);
else cursor_pos = line_edit->cursorPosition();
// Get current prosition
int cur_index = line_edit->cursorPosition();
/**
* NOTE
*
* prev_delimiter_index should actually point at final white space AFTER the delimiter.
*/
// Get index of last delimiter before current position
int prev_delimiter_index = str.mid(0, cur_index).lastIndexOf(delimiter);
while(str.at(prev_delimiter_index + 1).isSpace()) prev_delimiter_index++;
// Get index of first delimiter after current position (or EOL if no delimiter after cursor)
int next_delimiter_index = str.indexOf(delimiter, cur_index);
if(next_delimiter_index == -1) {
next_delimiter_index = str.size();
}
// Get part of string that occurs before cursor
QString part1 = str.mid(0, prev_delimiter_index + 1);
// Get string value from before auto finished string is selected
QString pre = str.mid(prev_delimiter_index + 1, cur_index - prev_delimiter_index - 1);
// Get part of string that occurs AFTER cursor
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;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* DELIMITEDCOMPLETER PRIVATE METHODS *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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 then we are cycling through autocomplete list
// If not cycling through autocomplete list, then make sure cursor_pos is reset to -1
if(old_pos != cursor_pos) cursor_pos = -1;
}
用於QLineEdit的QCompleter不檢查每個單詞,而是檢查整個內容。如果你的字符串是「alpha歐米茄」,完成者會給你一個這個字符串的命中。您最終應該繼承QLineEdit並設置實現,以在每個單詞上使用QCompleter而不是整個內容。 –
以及如何設置QLineEdit的實現,QCompleter會檢查除整個內容以外的每個單詞? –
我很抱歉,但我沒有時間給你一個QLineEdit-Subclass的完整實現。除此之外,你可以學習更多的形式,它自己做。最終,您可以設置QLineEdits完成程序,以識別用QCompleter :: setCompletionPrefix(const QString&前綴)編寫的最後一個單詞;其中前綴只是您要完成的最後一個單詞 –