Я пытаюсь создать подкласс для QCombobox
и QCompleter
для достижения следующего:
Я хочу создать редактируемый комбинированный список, который всплывает в списке завершения, когда пользователь начинает печатать.
Пример: список завершения - QStringList<<"manual"<<"anual"
Когда я набираю 'anu'
, я хочу, чтобы и "manual"
, и "anual"
появлялись в раскрывающемся списке завершения, поскольку оба они содержат "anu"
.Но вместо этого я получаю только **anu**al
с al
в качестве встроенного завершения, поэтому в списке завершения я получил только "anual"
.Когда я удаляю встроенное предложение с помощью backspace, я получаю полный список, как и ожидалось.
Почему появляется встроенное завершение по умолчанию?
linecompleter.h
#ifndef LINECOMPLETER_H
#define LINECOMPLETER_H
#include <QtGui>
#include <QtWidgets>
class QKeyEvent;
class LineCompleter : public QCompleter
{
Q_OBJECT
public:
inline LineCompleter(const QStringList& words, QObject * parent) :
QCompleter(parent), m_list(words), m_model()
{
setModel(&m_model);
}
inline void update(QString word)
{
// Do any filtering you like.
// Here we just include all items that contain word.
QStringList filtered = m_list.filter(word, caseSensitivity());
m_model.setStringList(filtered);
m_word = word;
complete();
}
inline QString word()
{
return m_word;
}
private:
QStringList m_list;
QStringListModel m_model;
QString m_word;
};
class PageLineEdit : public QComboBox
{
Q_OBJECT
public:
PageLineEdit(QWidget *parent = 0);
~PageLineEdit();
void setCompleter(LineCompleter *c);
LineCompleter *completer() const;
protected:
void keyPressEvent(QKeyEvent *e);
private slots:
void insertCompletion(const QString &completion);
private:
LineCompleter *c;
};
#endif // LINECOMPLETER_H
linecompleter.cpp
#include "linecompleter.h"
PageLineEdit::PageLineEdit(QWidget *parent)
: QComboBox(parent), c(0)
{
}
PageLineEdit::~PageLineEdit()
{
}
void PageLineEdit::setCompleter(LineCompleter *completer)
{
if (c)
QObject::disconnect(c, 0, this, 0);
c = completer;
if (!c)
return;
c->setWidget(this);
c->setCompletionMode(QCompleter::PopupCompletion);
c->setCaseSensitivity(Qt::CaseInsensitive);
QObject::connect(c, SIGNAL(activated(QString)),
this, SLOT(insertCompletion(QString)));
}
LineCompleter *PageLineEdit::completer() const
{
return c;
}
void PageLineEdit::insertCompletion(const QString& completion)
{
lineEdit()->setText(completion);
lineEdit()->selectAll();
}
void PageLineEdit::keyPressEvent(QKeyEvent *e)
{
if (c && c->popup()->isVisible())
{
// The following keys are forwarded by the completer to the widget
switch (e->key())
{
case Qt::Key_Enter:
case Qt::Key_Return:
case Qt::Key_Escape:
case Qt::Key_Tab:
case Qt::Key_Backtab:
e->ignore();
return; // Let the completer do default behavior
default:
break;
}
}
bool isShortcut = (e->modifiers() & Qt::ControlModifier) && e->key() == Qt::Key_E;
if (!isShortcut)
QComboBox::keyPressEvent(e); // Don't send the shortcut (CTRL-E) to the text edit.
if (!c)
return;
bool ctrlOrShift = e->modifiers() & (Qt::ControlModifier | Qt::ShiftModifier);
if (!isShortcut && !ctrlOrShift && e->modifiers() != Qt::NoModifier)
{
c->popup()->hide();
return;
}
c->update(lineEdit()->text());
c->popup()->setCurrentIndex(c->completionModel()->index(0, 0));
}
Я реализовал это используя этот центральный поток Qt
Я использую Qt 4.8у которого нет setFilterMode()
для QCompleter
.
Как правильно создать подкласс QCombobox
для достижения этой необходимой функции?