사용자 정의 완성기 예제
사용자 정의 완성기 예제는 모델에서 제공한 데이터를 기반으로 입력 위젯에 문자열 완성 기능을 제공하는 방법을 보여줍니다. 완성기는 사용자가 입력한 처음 세 문자를 기반으로 가능한 단어에 대한 제안을 팝업으로 표시하고 사용자가 선택한 단어는 QTextCursor 을 사용하여 TextEdit
에 삽입됩니다.
리소스 파일 설정하기
사용자 정의 완성기 예제에는 QCompleter 단어 완성에 도움이 되는 단어 목록이 있는 리소스 파일인 wordlist.txt가 필요합니다. 이 파일에는 다음이 포함되어 있습니다:
<!DOCTYPE RCC><RCC version="1.0"> <qresource prefix="/"> <file>resources/wordlist.txt</file> </qresource> </RCC>
TextEdit 클래스 정의
TextEdit
클래스는 사용자 정의 insertCompletion()
슬롯이 있는 QTextEdit 의 하위 클래스이며 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
을 생성하고 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); }
그런 다음 c
를 completer 로 인스턴스화하고 TextEdit
의 위젯으로 설정합니다. 완성 모드와 대소문자 구분도 설정한 다음 activated() 신호를 insertCompletion()
슬롯에 연결합니다.
completer()
함수는 c
을 반환하는 게터 함수입니다.
QCompleter *TextEdit::completer() const { return c; }
완성기는 wordlist.txt의 내용에 따라 사용 가능한 옵션을 팝업으로 표시하지만, 텍스트 커서는 사용자가 선택한 단어에 따라 누락된 문자를 채우는 역할을 담당합니다.
사용자가 "ACT"를 입력하고 작성자가 제안한 "ACTUAL"을 수락한다고 가정해 보겠습니다. 그러면 완성자의 activated() 신호에 의해 completion
문자열이 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
클래스는 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
을 생성하고 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()
함수는 사용자 정의 컴파일러 예제에 대한 간략한 설명을 제공합니다.
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(); }
© 2025 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.