由于项目所需,自定义了一个继承自QLineEdit的实现输入自动过滤补全控件,在此贴出记录一下,以备后用。
代码比较简单易懂,并且有跟多人实现过所以就不做说明了。
.h
#ifndef COMPLETELINEEDIT_H
#define COMPLETELINEEDIT_H
#include <QLineEdit>
#include <QStringList>
class QListView;
class QStringListModel;
class QModelIndex;
class CompleteLineEdit : public QLineEdit {
Q_OBJECT
public:
CompleteLineEdit(QStringList words, QWidget *parent = 0);
void bindDataSource(QStringList source);
void popshow();
void gettext();
~CompleteLineEdit();
public slots:
void setCompleter(const QString &text); // 动态的显示完成列表
void completeText(const QModelIndex &index); // 点击完成列表中的项,使用此项自动完成输入的单词
protected:
virtual void keyPressEvent(QKeyEvent *e);
virtual void focusOutEvent(QFocusEvent *e);
virtual void focusInEvent(QFocusEvent *e);
private:
QStringList words; // 整个完成列表的单词
QListView *listView; // 完成列表
QStringListModel *model; // 完成列表的model
QWidget *parentwidget;
QString currstr;
};
#endif // COMPLETELINEEDIT_H
.cpp
#include "completelineedit.h"
#include <QKeyEvent>
#include <QListView>
#include <QStringListModel>
#include <QDebug>
CompleteLineEdit::CompleteLineEdit(QStringList words, QWidget *parent)
: QLineEdit(parent), words(words) {
parentwidget=parent;
listView = new QListView(this);
model = new QStringListModel(this);
listView->setWindowFlags(Qt::ToolTip);
listView->setFocusPolicy(Qt::NoFocus);
listView->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
connect(this, SIGNAL(textChanged(const QString &)), this, SLOT(setCompleter(const QString &)));
connect(listView, SIGNAL(clicked(const QModelIndex &)), this, SLOT(completeText(const QModelIndex &)));
}
void CompleteLineEdit::bindDataSource(QStringList source)
{
this->words = source;
}
void CompleteLineEdit::popshow()
{
setCompleter("");
}
void CompleteLineEdit::gettext()
{
if(!words.contains(this->text())){
this->setText(listView->currentIndex().data().toString());
}
}
CompleteLineEdit::~CompleteLineEdit()
{
parentwidget->clearFocus();
this->clearFocus();
delete listView;
}
void CompleteLineEdit::focusOutEvent(QFocusEvent *e) {
this->clearFocus();
if(!words.contains(this->text()))
{
this->setText(currstr);
}
listView->hide();
QLineEdit::focusOutEvent(e);
}
void CompleteLineEdit::focusInEvent(QFocusEvent *e)
{
setCompleter("");
currstr=this->text();
QLineEdit::focusInEvent(e);
}
void CompleteLineEdit::keyPressEvent(QKeyEvent *e) {
if (!listView->isHidden()) {
int key = e->key();
int count = listView->model()->rowCount();
QModelIndex currentIndex = listView->currentIndex();
if (Qt::Key_Down == key) {
int row = currentIndex.row() + 1;
if (row >= count) {
row = 0;
}
QModelIndex index = listView->model()->index(row, 0);
listView->setCurrentIndex(index);
} else if (Qt::Key_Up == key) {
int row = currentIndex.row() - 1;
if (row < 0) {
row = count - 1;
}
QModelIndex index = listView->model()->index(row, 0);
listView->setCurrentIndex(index);
} else if (Qt::Key_Escape == key) {
listView->hide();
} else if (Qt::Key_Enter == key || Qt::Key_Return == key) {
if (currentIndex.isValid()) {
QString text = listView->currentIndex().data().toString();
setText(text);
}
listView->hide();
} else {
QLineEdit::keyPressEvent(e);
}
} else {
QLineEdit::keyPressEvent(e);
}
}
void CompleteLineEdit::setCompleter(const QString &text) {
/*if (text.isEmpty()) {
listView->hide();
return;
}*/
if(!this->hasFocus())
return;
if ((text.isEmpty()) && (!listView->isHidden())) {
return;
}
QString newtext=text;
if(listView->isHidden())
newtext="";
QStringList sl;
foreach(QString word, words) {
if(newtext.isEmpty()) {
sl << word;
} else {
if (word.contains(newtext)) {
sl << word;
}
}
}
if(sl.count() == 0) {
foreach(QString word, words) {
sl << word;
}
}
model->setStringList(sl);
listView->setModel(model);
if (model->rowCount() == 0) {
return;
}
// Position the text edit
listView->setMinimumWidth(width());
listView->setMaximumWidth(width());
QPoint p(parentwidget->parentWidget()->x(), height());
int x = this->mapToGlobal(p).x();
int y = this->mapToGlobal(p).y() + 1;
int h=y;
//选择展开方向,由于我的开发板是600×800的,所以以下代码不具有通用性。
if(y>=350)
{
h=qMin((600-y),model->rowCount()*26);
}
else if((350-y)<(y-height()))
{
h=qMin((y-height()),model->rowCount()*26);
y=y-h-height();
}
else {
h=qMin((350-y),model->rowCount()*26);
}
listView->move(x,y);
listView->resize(width(),h-1);
listView->setStyleSheet("QListView::item{\
height:25px;\
}\
QListView {\
background-color: #00FF7F;\
}");
listView->show();
QModelIndex index=model->index(0,0);
listView->setCurrentIndex(index);
}
void CompleteLineEdit::completeText(const QModelIndex &index) {
QString text = index.data().toString();
setText(text);
listView->hide();
this->clearFocus();
}