사용자 정의 자동 완성 예제
'사용자 정의 완성기' 예제는 모델에서 제공하는 데이터를 기반으로 입력 위젯에 문자열 완성 기능을 제공하는 방법을 보여줍니다. 이 완성기는 사용자가 입력한 첫 세 글자를 바탕으로 가능한 단어 후보를 표시하며, 사용자가 선택한 단어는 ` QTextCursor`를 사용하여 ` TextEdit `에 삽입됩니다.

리소스 파일 설정
사용자 정의 자동 완성 예제에서는 ` QCompleter `이 단어를 완성하는 데 도움이 되는 단어 목록이 포함된 ` wordlist.txt` 리소스 파일이 필요합니다. 이 파일에는 다음 내용이 포함되어 있습니다:
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/">
<file>resources/wordlist.txt</file>
</qresource>
</RCC>TextEdit 클래스 정의
TextEdit 클래스는 QTextEdit 의 서브클래스로, 사용자 정의 insertCompletion() 슬롯을 가지고 있으며 keyPressEvent() 및 focusInEvent() 함수를 재구현합니다. TextEdit 에는 또한 비공개 함수 textUnderCursor() 와 QCompleter 의 비공개 인스턴스인 c 가 포함되어 있습니다.
class TextEdit : public QTextEdit
{
Q_OBJECT
public:
TextEdit(QWidget *parent = nullptr);
~TextEdit();
void setCompleter(QCompleter *c);
QCompleter *completer() const;
protected:
void keyPressEvent(QKeyEvent *e) override;
void focusInEvent(QFocusEvent *e) override;
private slots:
void insertCompletion(const QString &completion);
private:
QString textUnderCursor() const;
private:
QCompleter *c = nullptr;
};TextEdit 클래스 구현
TextEdit 의 생성자는 부모를 가진 TextEdit 를 생성하고 c 를 초기화합니다. setPlainText() 함수를 사용하여 TextEdit 객체에 완성기 사용 방법에 대한 안내를 표시합니다.
TextEdit::TextEdit(QWidget *parent)
: QTextEdit(parent)
{
setPlainText(tr("This TextEdit provides autocompletions for words that have more than"
" 3 characters. You can trigger autocompletion using ") +
QKeySequence("Ctrl+E").toString(QKeySequence::NativeText));
}또한, TextEdit 에는 기본 소멸자도 포함되어 있습니다.
TextEdit::~TextEdit()
{
}setCompleter() 함수는 completer 를 인수로 받아 이를 설정합니다. if (c) 를 사용하여 c 가 초기화되었는지 확인합니다. 초기화된 경우, QObject::disconnect() 함수를 호출하여 슬롯에서 신호를 분리합니다. 이는 이전 컴플리터 객체가 슬롯에 여전히 연결되어 있지 않도록 보장하기 위함입니다.
void TextEdit::setCompleter(QCompleter *completer)
{
if (c)
c->disconnect(this);
c = completer;
if (!c)
return;
c->setWidget(this);
c->setCompletionMode(QCompleter::PopupCompletion);
c->setCaseSensitivity(Qt::CaseInsensitive);
QObject::connect(c, QOverload<const QString &>::of(&QCompleter::activated),
this, &TextEdit::insertCompletion);
}그런 다음 completer 을 사용하여 c 를 인스턴스화하고, 이를 TextEdit 의 위젯으로 설정합니다. 또한 완성 모드와 대소문자 구분 설정도 지정하고, activated() 신호를 insertCompletion() 슬롯에 연결합니다.
completer() 함수는 c 를 반환하는 게터 함수입니다.
QCompleter *TextEdit::completer() const
{
return c;
}이 자동 완성 기능은 wordlist.txt의 내용을 기반으로 사용 가능한 옵션들을 표시하지만, 사용자가 선택한 단어에 따라 누락된 문자를 채워 넣는 역할은 텍스트 커서가 담당합니다.
사용자가 "ACT"를 입력하고 완성기의 제안인 "ACTUAL"을 수락한다고 가정해 봅시다. 그러면 completion 문자열은 완성기의 activated() 신호를 통해 insertCompletion() 로 전송됩니다.
insertCompletion() 함수는 QTextCursor 객체인 tc 을 사용하여 단어를 완성하는 역할을 합니다. 이 함수는 tc 을 사용하여 단어를 완성하기 위해 추가 문자를 삽입하기 전에, 컴플리터의 위젯이 TextEdit 상태인지 유효성을 확인합니다.
void TextEdit::insertCompletion(const QString &completion)
{
if (c->widget() != this)
return;
QTextCursor tc = textCursor();
int extra = completion.length() - c->completionPrefix().length();
tc.movePosition(QTextCursor::Left);
tc.movePosition(QTextCursor::EndOfWord);
tc.insertText(completion.right(extra));
setTextCursor(tc);
}아래 그림은 이 과정을 보여줍니다:

completion.length() = 6
c->completionPrefix().length()=3
이 두 값의 차이는 extra, 즉 3입니다. 이는 오른쪽에서 세 번째부터 마지막 세 글자인 "U", "A", "L"이 tc 에 의해 삽입될 것임을 의미합니다.
textUnderCursor() 함수는 QTextCursor( tc)를 사용하여 커서 아래에 있는 단어를 선택하고 반환합니다.
QString TextEdit::textUnderCursor() const
{
QTextCursor tc = textCursor();
tc.select(QTextCursor::WordUnderCursor);
return tc.selectedText();
}TextEdit 클래스는 위젯에 대한 키보드 포커스 이벤트를 수신하는 데 사용되는 이벤트 핸들러인 focusInEvent() 함수를 재구현합니다.
void TextEdit::focusInEvent(QFocusEvent *e)
{
if (c)
c->setWidget(this);
QTextEdit::focusInEvent(e);
}keyPressEvent()은 Qt::Key_Enter, Qt::Key_Return, Qt::Key_Escape, Qt::Key_Tab, Qt::Key_Backtab 과 같은 키 이벤트를 무시하도록 재구현되어, 완성기가 해당 이벤트를 처리할 수 있게 합니다.
활성화된 자동 완성기가 있는 경우, Ctrl+E 단축키를 처리할 수 없습니다.
void TextEdit::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;
}
}
const bool isShortcut = (e->modifiers().testFlag(Qt::ControlModifier) && e->key() == Qt::Key_E); // CTRL+E
if (!c || !isShortcut) // do not process the shortcut when we have a completer
QTextEdit::keyPressEvent(e);또한, 컴플리터가 반응하지 않도록 하고 싶은 다른 수정 키와 단축키도 처리합니다.
const bool ctrlOrShift = e->modifiers().testFlag(Qt::ControlModifier) ||
e->modifiers().testFlag(Qt::ShiftModifier);
if (!c || (ctrlOrShift && e->text().isEmpty()))
return;
static QString eow("~!@#$%^&*()_+{}|:\"<>?,./;'[]\\-="); // end of word
const bool hasModifier = (e->modifiers() != Qt::NoModifier) && !ctrlOrShift;
QString completionPrefix = textUnderCursor();
if (!isShortcut && (hasModifier || e->text().isEmpty()|| completionPrefix.length() < 3
|| eow.contains(e->text().right(1)))) {
c->popup()->hide();
return;
}
if (completionPrefix != c->completionPrefix()) {
c->setCompletionPrefix(completionPrefix);
c->popup()->setCurrentIndex(c->completionModel()->index(0, 0));
}
QRect cr = cursorRect();
cr.setWidth(c->popup()->sizeHintForColumn(0)
+ c->popup()->verticalScrollBar()->sizeHint().width());
c->complete(cr); // popup it up!
}마지막으로, 컴플리터를 팝업으로 표시합니다.
MainWindow 클래스 정의
MainWindow 클래스는 QMainWindow 의 서브클래스이며, 비공개 슬롯인 about() 을 구현합니다. 또한 이 클래스에는 createMenu() 와 modelFromFile() 이라는 두 개의 비공개 함수와 QCompleter 및 TextEdit 의 비공개 인스턴스가 있습니다.
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
private slots:
void about();
private:
void createMenu();
QAbstractItemModel *modelFromFile(const QString& fileName);
QCompleter *completer = nullptr;
TextEdit *completingTextEdit;
};MainWindow 클래스 구현
생성자는 부모를 가진 MainWindow 객체를 생성하고 completer 를 초기화합니다. 또한 TextEdit 객체를 인스턴스화하고 그 컴플리터를 설정합니다. modelFromFile() 에서 얻은 QStringListModel 는 completer 를 채우는 데 사용됩니다. MainWindow 의 중앙 위젯은 TextEdit 로 설정되며, 크기는 500 x 300으로 설정됩니다.
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
createMenu();
completingTextEdit = new TextEdit;
completer = new QCompleter(this);
completer->setModel(modelFromFile(":/resources/wordlist.txt"));
completer->setModelSorting(QCompleter::CaseInsensitivelySortedModel);
completer->setCaseSensitivity(Qt::CaseInsensitive);
completer->setWrapAround(false);
completingTextEdit->setCompleter(completer);
setCentralWidget(completingTextEdit);
resize(500, 300);
setWindowTitle(tr("Completer"));
}createMenu() 함수는 "파일" 및 "도움말" 메뉴에 필요한 QAction 객체를 생성하며, 이들의 triggered() 신호는 각각 quit(), about() 및 aboutQt() 슬롯에 연결됩니다.
void MainWindow::createMenu()
{
QAction *exitAction = new QAction(tr("Exit"), this);
QAction *aboutAct = new QAction(tr("About"), this);
QAction *aboutQtAct = new QAction(tr("About Qt"), this);
connect(exitAction, &QAction::triggered, qApp, &QApplication::quit);
connect(aboutAct, &QAction::triggered, this, &MainWindow::about);
connect(aboutQtAct, &QAction::triggered, qApp, &QApplication::aboutQt);
QMenu *fileMenu = menuBar()->addMenu(tr("File"));
fileMenu->addAction(exitAction);
QMenu *helpMenu = menuBar()->addMenu(tr("About"));
helpMenu->addAction(aboutAct);
helpMenu->addAction(aboutQtAct);
}modelFromFile() 함수는 fileName 를 인수로 받아 이 파일의 내용을 QStringListModel 로 추출하려고 시도합니다. QStringList 와 words 를 채우는 동안 Qt::WaitCursor 를 표시하고, 작업이 완료되면 마우스 커서를 원래 상태로 복원합니다.
QAbstractItemModel *MainWindow::modelFromFile(const QString& fileName)
{
QFile file(fileName);
if (!file.open(QFile::ReadOnly))
return new QStringListModel(completer);
#ifndef QT_NO_CURSOR
QGuiApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
#endif
QStringList words;
while (!file.atEnd()) {
QByteArray line = file.readLine();
if (!line.isEmpty())
words << QString::fromUtf8(line.trimmed());
}
#ifndef QT_NO_CURSOR
QGuiApplication::restoreOverrideCursor();
#endif
return new QStringListModel(words, completer);
}about() 함수는 ‘Custom Completer’ 예제에 대한 간략한 설명을 제공합니다.
void MainWindow::about()
{
QMessageBox::about(this, tr("About"), tr("This example demonstrates the "
"different features of the QCompleter class."));
}main() 함수
main() 함수는 ` MainWindow `를 인스턴스화하고 ` show()` 함수를 호출합니다.
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow window;
window.show();
return app.exec();
}© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.