カスタムコンプリートの例
カスタム・コンプリターの例は、モデルによって提供されたデータに基づいて、入力ウィジェットに文字列補完機能を提供する方法を示しています。このコンプリターは、ユーザーが入力した最初の3文字に基づいて、候補となる単語をポップアップ表示し、ユーザーが選択した単語は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
's widget として設定する。補完モードと大文字小文字の区別も設定し、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
この2つの値の差はextra
、3である。これは、右から最後の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()
という2つのプライベート関数と、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()
関数は、"File" と "Help" メニューに必要な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(); }
©2024 The Qt Company Ltd. 本書に含まれる文書の著作権は、それぞれの所有者に帰属します。 ここで提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。