Dynamic form processing enables a form to be processed at run-time only by changing the UI file for the project. The program allows the user to look up a particular word within the contents of a text file. This text file is included in the project's resource and is loaded into the display at startup.
|
|
The resources required for Text Finder are:
textfinder.ui contains all the necessary QWidget objects for the Text Finder. A QLineEdit is used for the user input, a QTextEdit is used to display the contents of input.txt , QLabel is used to display the text "Keyword", and a QPushButton is used for the "Find" button. The screenshot below shows the preview obtained in QtDesigner .
A textfinder.qrc file is used to store both the textfinder.ui and input.txt in the application's executable. The file contains the following code:
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>forms/textfinder.ui</file>
<file>forms/input.txt</file>
</qresource>
</RCC>
有关资源文件的更多信息,见 Qt 资源系统 .
To generate a form at run-time, the example is linked against the
QtUiTools
module library. This is done in the
textfinder.pro
file that contains the following lines:
CONFIG += uitools HEADERS = textfinder.h RESOURCES = textfinder.qrc SOURCES = textfinder.cpp main.cpp
The
TextFinder
类是子类化的
QWidget
and it hosts the
QWidget
s we need to access in the user interface. The
QLabel
in the user interface is not declared here as we do not need to access it.
class TextFinder : public QWidget { Q_OBJECT public: TextFinder(QWidget *parent = 0); private slots: void on_findButton_clicked(); private: QWidget* loadUiFile(); void loadTextFile(); QPushButton *ui_findButton; QTextEdit *ui_textEdit; QLineEdit *ui_lineEdit; bool isFirstTime; };
槽
on_findButton_clicked()
is a slot named according to the
Automatic Connection
naming convention required by
uic
.
The
TextFinder
class's constructor calls the
loadUiFile()
function and then uses
qFindChild()
to access the user interface's
QWidget
。
TextFinder::TextFinder(QWidget *parent) : QWidget(parent) { QWidget *formWidget = loadUiFile(); ui_findButton = findChild<QPushButton*>("findButton"); ui_textEdit = findChild<QTextEdit*>("textEdit"); ui_lineEdit = findChild<QLineEdit*>("lineEdit");
We then use QMetaObject 's system to enable signal and slot connections.
QMetaObject::connectSlotsByName(this);
The loadTextFile() function is called to load
input.txt
into
QTextEdit
to displays its contents.
loadTextFile();
The
TextFinder
's layout is set with
setLayout()
.
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(formWidget);
setLayout(layout);
Finally, the window title is set to
文本查找器
and
isFirstTime
is set to true.
isFirstTime
is used as a flag to indicate whether the search operation has been performed more than once. This is further explained with the
on_findButton_clicked()
函数。
The
loadUiFile()
function is used to load the user interface file previously created in
QtDesigner
。
QUiLoader
class is instantiated and its
load()
function is used to load the form into
formWidget
that acts as a place holder for the user interface. The function then returns
formWidget
to its caller.
QWidget* TextFinder::loadUiFile() { QUiLoader loader; QFile file(":/forms/textfinder.ui"); file.open(QFile::ReadOnly); QWidget *formWidget = loader.load(&file, this); file.close(); return formWidget; }
As mentioned earlier, the loadTextFile() function loads
input.txt
into
QTextEdit
to display its contents. Data is read using
QTextStream
成
QString
对象,
line
采用
QTextStream::readAll
() function. The contents of
line
are then appended to
ui_textEdit
.
void TextFinder::loadTextFile() { QFile inputFile(":/forms/input.txt"); inputFile.open(QIODevice::ReadOnly); QTextStream in(&inputFile); QString line = in.readAll(); inputFile.close(); ui_textEdit->append(line); ui_textEdit->setUndoRedoEnabled(false); ui_textEdit->setUndoRedoEnabled(true); }
The
on_findButton_clicked()
function is a slot that is connected to
ui_findButton
's
clicked()
信号。
searchString
is extracted from the
ui_lineEdit
和
document
is extracted from
textEdit
. In event there is an empty
searchString
,
QMessageBox
is used, requesting the user to enter a word. Otherwise, we traverse through the words in
ui_textEdit
, and highlight all ocurrences of the
searchString
. Two
QTextCursor
objects are used: One to traverse through the words in
line
and another to keep track of the edit blocks.
void TextFinder::on_findButton_clicked() { QString searchString = ui_lineEdit->text(); QTextDocument *document = ui_textEdit->document(); bool found = false; if (isFirstTime == false) document->undo(); if (searchString.isEmpty()) { QMessageBox::information(this, tr("Empty Search Field"), "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();
The
isFirstTime
flag is set to false the moment
findButton
is clicked. This is necessary to undo the previous text highlight before highlighting the user's next search string. Also, the
found
flag is used to indicate if the
searchString
was found within the contents of
ui_textEdit
. If it was not found, a
QMessageBox
is used to inform the user.
isFirstTime = false;
if (found == false) {
QMessageBox::information(this, tr("Word Not Found"),
"Sorry, the word cannot be found.");
}
}
}
main()
函数
int main(int argc, char *argv[]) { Q_INIT_RESOURCE(textfinder); QApplication app(argc, argv); TextFinder *textFinder = new TextFinder; textFinder->show(); return app.exec(); }
The
main()
function initialises the
textfinder.qrc
resource file and instantiates as well as displays
TextFinder
.
文件:
另请参阅 计算器构建者范例 and 世界时间时钟构建者范例 .