文本查找器

使用QUiLoader 动态加载 .ui 文件。

TextFinder 示例展示了如何使用QUiLoader 类动态加载和设置.ui 文件,该类是 Qt UI Tools类动态加载和设置 文件。

该程序允许用户查找文本内容中的某个特定单词。用户界面的视觉元素和布局是在运行时从程序资源中加载的。

设置资源文件

本示例所需的资源包括

textfinder.ui 其中包含文本查找器所需的所有 对象。 用于用户输入, 用于显示 的内容, 用于显示文本 "关键词", 用于 按钮。请注意,所有部件都分配了合理的 's。代码中使用这些字符来识别它们。QWidget QLineEdit QTextEdit input.txt QLabel QPushButton Find objectName

下面的截图显示了在Qt Widgets Designer 中获得的预览。

在本示例中,我们通过包含textfinder.qrc 文件将两种资源存储在应用程序的可执行文件中。或者,也可以在运行时从文件系统或外部二进制资源.rcc 文件中加载这些文件。有关资源文件的更多信息,请参阅Qt 资源系统

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 所要求的自动连接命名约定命名的插槽。

加载资源

我们使用QFile 在运行时从程序资源中加载数据。相关代码包含在textfinder.cpp 上的两个方法中:loadUiFileloadTextFile

loadUiFile 函数加载之前在Qt Widgets Designer 中创建的用户界面文件。首先,从资源系统中找到并打开textfinder.ui 文件。然后创建QUiLoader 实例,调用QUiLoader::load() 函数,第一个参数是打开的文件,第二个参数是应设置为父对象的部件指针。创建的QWidget 将被返回。

静态QWidget*loadUiFile(QWidget*父节点){    QFilefile(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() 按对象名称查找创建的QWidgets。

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 的所有出现。我们使用了两个 QTextCursor 对象:一个用于遍历line 中的单词,另一个用于跟踪编辑块。

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();

found 标志用于指示是否在ui_textEdit 的内容中找到searchString 。如果没有找到,则使用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 只是其中之一。有关其他可用方法的更多信息,请参阅在应用程序中使用设计器 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.