テキストファインダー

QUiLoader を使って .ui ファイルを動的にロードする。

TextFinderの例では、ライブラリの一部であるQUiLoader クラスを使用して、.ui ファイルを動的にロードしてセットアップする方法を示しています。 Qt UI Toolsライブラリの一部です。

このプログラムでは、ユーザーがテキストの内容から特定の単語を検索することができます。ユーザー・インターフェースの視覚的要素とレイアウトは、プログラム・リソースから実行時にロードされます。

リソース・ファイルのセットアップ

この例で必要なリソースは以下の通りです:

  • textfinder.ui -Qt Widgets Designerで作成したユーザーインターフェイスファイル
  • input.txt - に表示するテキストを含むテキストファイル。QTextEdit

textfinder.ui には、テキスト・ファインダーに必要な オブジェクトがすべて含まれています。 はユーザー入力に使われ、 は の内容を表示するのに使われ、 は「キーワード」というテキストを表示するのに使われ、 は ボタンに使われます。すべてのウィジェットには、 'が割り当てられています。これらは、ウィジェットを識別するためにコードで使用されます。QWidget QLineEdit QTextEdit input.txt QLabel QPushButton Find objectName

下のスクリーンショットは、Qt Widgets Designerで得られたプレビューです。

この例では、textfinder.qrc ファイルをインクルードすることで、両方のリソースをアプリケーションの実行ファイルに格納します。あるいは、ファイルはファイルシステムから、または外部のバイナリリソース.rcc ファイルから実行時にロードすることもできます。リソースファイルの詳細については、Qt Resource Systemを参照してください。

textfinder.qrc ファイルには、リソースとして含めるべきすべてのファイルがリストされています:

<!DOCTYPE RCC><RCC version="1.0">
<qresource>
    <file>forms/textfinder.ui</file>
    <file>forms/input.txt</file>
</qresource>
</RCC>

実行時にフォームを生成するために、サンプルはQt UI Toolsライブラリにリンクされています。これはtextfinder.pro ファイルで行われます:

QT += widgets uitools

HEADERS = textfinder.h
SOURCES = textfinder.cpp main.cpp
RESOURCES = textfinder.qrc

テキストファインダーのクラス定義

TextFinder クラスはメインのユーザー・インターフェースを含んでいます。QPushButtonQTextEditQLineEdit の各要素へのポインタを宣言しています。ユーザー・インターフェースのQLabel は、コードからアクセスする必要がないので、ここでは宣言しません。

class TextFinder : public QWidget
{
    Q_OBJECT

public:
    explicit TextFinder(QWidget *parent = nullptr);

private slots:
    void on_findButton_clicked();

private:
    QPushButton *ui_findButton;
    QTextEdit *ui_textEdit;
    QLineEdit *ui_lineEdit;
};

スロットon_findButton_clicked() は、uic で要求されるAutomatic Connectionの命名規則に従って命名されたスロットです。

リソースのロード

実行時にプログラムリソースからデータをロードするためにQFile を使用します。このためのコードは、textfinder.cpp の上にある2つのメソッド、loadUiFileloadTextFile にあります。

loadUiFile 関数は、Qt Widgets Designer で事前に作成したユーザー・インターフェース・ファイルをロードします。まず、textfinder.ui ファイルを探し、リソース・システムから開きます。次に、QUiLoader インスタンスが作成され、QUiLoader::load() 関数が呼び出されます。第1引数にはオープンされたファイル、第2引数には親として設定されるウィジェットのポインタが指定されます。作成されたQWidget が返される。

静的QWidget*loadUiFile(QWidget*parent) { QFileファイル(u":/forms/textfinder.ui"_s);if(!file.open(QIODevice::ReadOnly))        qFatal("Cannot open resource file");

   リターンQUiLoader().load(&file,parent); }

同様に、loadTextFile 関数は、リソースからinput.txt を探し、開きます。そして、QTextStream::readAll ()関数を使用してファイルの内容を返します。

静的QStringloadTextFile() { QFileinputFile(u":/forms/input.txt"_s);if(!inputFile.open(QIODevice::ReadOnly))        qFatal("Cannot open resource file");

   リターンQTextStream(&inputFile).readAll(); }

TextFinderクラスの実装

TextFinder クラスのコンストラクタは、子ウィジェットを直接インスタンス化しません。その代わり、loadUiFile() 関数を呼び出し、QObject::findChild() を使って、作成されたQWidgetをオブジェクト名で探します。

TextFinder::TextFinder(QWidget *parent)
    : QWidget(parent)
{
    QWidget *formWidget = loadUiFile(this);

    ui_findButton = findChild<QPushButton*>("findButton");
    ui_textEdit = findChild<QTextEdit*>("textEdit");
    ui_lineEdit = findChild<QLineEdit*>("lineEdit");

その後、QMetaObject::connectSlotsByName() を使用して、on_findButton_clicked() スロットを自動的に呼び出せるようにします。

    QMetaObject::connectSlotsByName(this);

loadTextFile 関数が呼び出され、QTextEdit に表示されるテキストが取得される。

    ui_textEdit->setText(loadTextFile());

formWidget 、動的にロードされるユーザーインターフェイスが適切にセットアップされました。QVBoxLayout を使ってformWidget を埋め込みます。

    auto *layout = new QVBoxLayout(this);
    layout->addWidget(formWidget);

コンストラクタの最後に、ウィンドウのタイトルを設定します。

    setWindowTitle(tr("Text Finder"));
}

on_findButton_clicked() 関数はui_findButtonclicked() シグナルに接続されるスロットである。searchStringui_lineEdit から抽出され、documentui_textEdit から抽出される。空のsearchString がある場合は、QMessageBox が使用され、ユーザーに単語の入力を要求する。そうでない場合は、ui_textEdit の単語を走査し、searchString のすべての出現箇所を強調表示します。2 つの QTextCursor オブジェクトが使用されます:1つはline の単語を走査するため、もう1つは編集ブロックを追跡するためです。

void TextFinder::on_findButton_clicked()
{
    QString searchString = ui_lineEdit->text();
    QTextDocument *document = ui_textEdit->document();

    bool found = false;

    // undo previous change (if any)
    document->undo();

    if (searchString.isEmpty()) {
        QMessageBox::information(this, tr("Empty Search Field"),
                                 tr("The search field is empty. "
                                    "Please enter a word and click Find."));
    } else {
        QTextCursor highlightCursor(document);
        QTextCursor cursor(document);

        cursor.beginEditBlock();

        QTextCharFormat plainFormat(highlightCursor.charFormat());
        QTextCharFormat colorFormat = plainFormat;
        colorFormat.setForeground(Qt::red);

        while (!highlightCursor.isNull() && !highlightCursor.atEnd()) {
            highlightCursor = document->find(searchString, highlightCursor,
                                             QTextDocument::FindWholeWords);

            if (!highlightCursor.isNull()) {
                found = true;
                highlightCursor.movePosition(QTextCursor::WordRight,
                                             QTextCursor::KeepAnchor);
                highlightCursor.mergeCharFormat(colorFormat);
            }
        }

        cursor.endEditBlock();

searchStringui_textEdit のコンテンツ内で見つかったかどうかを示すために、found フラグが使用されます。 見つからなかった場合は、QMessageBox が使用され、ユーザーに通知されます。

        if (found == false) {
            QMessageBox::information(this, tr("Word Not Found"),
                                     tr("Sorry, the word cannot be found."));
        }
    }
}

main() 機能

main() 関数はTextFinder をインスタンス化し、表示します。

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    TextFinder textFinder;
    textFinder.show();

    return app.exec();
}

アプリケーションにフォームを組み込むには様々なアプローチがある。QUILoaderの使用はその1つに過ぎません。その他のアプローチの詳細については、「アプリケーションでデザイナーUIファイルを使用する」を参照してください。

サンプルプロジェクト @ code.qt.io

電卓ビルダーも参照してください

© 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.