This part of the guide is about adding logic and backend to the text editor example. At this stage, the user interface is set up from the previous stage.
文本编辑器 has a QML user interface and a C++ backend to implement the document handling. To connect QML and C++, we need to create actions associated to the tool buttons, which will call the document handling logic in C++.
The document handler implements the file loading and file saving logic with Qt's C++ APIs. First, we need to create the header file and the implementation file in Qt Creator's 编辑 模式。
The wizard creates a DocumentHandler class in two files, documenthandler.h and documenthandler.cpp .
There are two functionalities we can expose to QML, the file loading and saving. We can do this by creating properties and binding them to C++ functions through the Qt Property System .
在 documenthandler.h header file, add the following functions with their respective access modifier:
Q_PROPERTY(QUrl fileUrl READ fileUrl WRITE setFileUrl NOTIFY fileUrlChanged) Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) Q_PROPERTY(QString documentTitle READ documentTitle WRITE setDocumentTitle NOTIFY documentTitleChanged) public: QUrl fileUrl() const; QString text() const; QString documentTitle() const; public slots: void setFileUrl(const QUrl &arg); void setText(const QString &arg); void setDocumentTitle(QString arg); signals: void fileUrlChanged(); void textChanged(); void documentTitleChanged();
The lines with
Q_PROPERTY()
macro declares the
property
及其
write
and
read
methods as well as its
notify
signal. For example, setting the
fileUrl
property calls
setFileUrl()
and reading the property calls the
fileUrl()
function. Similarly, when the value of fileUrl changes the
fileUrlChanged()
函数被调用。
Internally, the properties are represented by private member variables. For our needs, here are the three variables in documenthandler.h which correspond to the properties:
private: QUrl m_fileUrl; QString m_text; QString m_documentTitle;
Implementing the read functions is straightforward. They simply return the private member variables. For example, the implementation of
documentTitle()
in
documenthandler.cpp
is:
QString DocumentHandler::documentTitle() const { return m_documentTitle; }
Implementing the write (
setText()
, for example) functions is also straightforward as they simply assign a value to a private member variable. They also handle basic error handling and they emit their respective notify signals. For example, the
setDocumentTitle()
function is implemented in
documenthandler.cpp
as:
void DocumentHandler::setDocumentTitle(QString arg) { if (m_documentTitle != arg) { m_documentTitle = arg; emit documentTitleChanged(); } }
The opening of the file is done in the
setFileUrl()
函数:
void DocumentHandler::setFileUrl(const QUrl &arg) { if (m_fileUrl != arg) { m_fileUrl = arg; QString fileName = arg.fileName(); QFile file(arg.toLocalFile()); if (file.open(QFile::ReadOnly)) { setText(QString(file.readAll())); if (fileName.isEmpty()) m_documentTitle = QStringLiteral("untitled"); else m_documentTitle = fileName; emit textChanged(); emit documentTitleChanged(); } emit fileUrlChanged(); } }
Note how the function emits the notify signals with the
emit
关键词。
Similarly, we use
QFile
and text streams to save files. The function signature in
documenthandler.h
is placed under
public slots
because that is one way to expose functions to the QML engine.
saveFile()
is called from the QML file during saving.
public slots: Q_INVOKABLE void saveFile(const QUrl &arg) const;
实现为
saveFile()
is in documenthandler.cpp:
void DocumentHandler::saveFile(const QUrl &arg) const { QFile file(arg.toLocalFile()); if (file.open(QFile::WriteOnly | QFile::Truncate)) { QTextStream out(&file); out << text(); } }
For information about reading files and data storage, visit the QFile 和 数据存储 文档编制。
We now need to let the QML engine know about the
DocumentHandler
and its type. The
qmlRegisterType()
function is called in the application's
main()
函数在
main.cpp
:
qmlRegisterType<DocumentHandler>("org.qtproject.example", 1, 0, "DocumentHandler");
The
org.qtproject.example
is the library with the version
1.0
and the QML type registered is
DocumentHandler
. The import statement for the DocumentHandler QML type is then
import org.qtproject.example 1.0
注意:
The
qmlRegisterType()
function should be called before the engine loads the QML file.
With the basic loading implemented, we can use the functionalities in the QML file by creating an instance of the DocumentHandler class and by accessing its properties.
The next page is about using these C++ functions in QML files.
The accompanying examples files are found in the following page:
Qt Quick Text Editor Guide - UI Qt Quick Text Editor - Connecting Actions