Qml (QtQuick)控件和 Widgets 控件都可以通过类继承 扩展其功能。
下面以扩展qml的TextArea 功能为例,其实现类QQuickTextArea 。
1.添加 QquickTextArea 和 QQuickTextControl头文件
1.1通过搜索可知俩个类的头文件分别是:
Qt5.9.8\5.9.8\mingw53_32\include\QtQuickTemplates2\5.9.8\QtQuickTemplates2\private\ qquicktextarea_p.h
Qt5.9.8\5.9.8\mingw53_32\include\QtQuick\5.9.8\QtQuick\private\qquicktextcontrol_p.h
所以如果想要在源码中引用 上面的private头文件,
.pro文件中需要添加
QT_PRIVATE += quick-private
QT_PRIVATE += quicktemplates2-private
1.1.1 qquicktextarea 在QtQuickTemplates2 模块还可以从
Qt5.9.8\5.9.8\mingw53_32\qml\QtQuick\Controls.2\TextArea.qml
中看出:
…
import QtQuick.Templates 2.2 as T
T.TextArea {
…
1.2 引用头文件
#include <QtQuickTemplates2/private/qquicktextarea_p.h>
#include <QtQuickTemplates2/private/qquicktextarea_p_p.h>
#include <QtQuick/private/qquicktextcontrol_p.h>
2.源码分析
2.1d指针
#include <QtQuickTemplates2/private/qquicktextarea_p.h>
#include <QtQuickTemplates2/private/qquicktextarea_p_p.h>
class QuickTextAreaEx : public QQuickTextArea{
…
private:
Q_DECLARE_PRIVATE(QQuickTextArea)//使用 QQuickTextArea 的d指针
…
}
使用d指针是因为用到的 QQuickTextAreaPrivate *d_ptr 中的control指针QquickTextControl,比如获取游标
QTextCursor cursor = d->control->textCursor();
2.2为TextArea 增加一种只能输入十六进制字符(Hex)的状态。
原理是文档的每次改变都判断下增加的内容是否是Hex字符,否则删除。
在构造函数中添加
connect(this->textDocument()->textDocument(),&QTextDocument::contentsChange,this,&QuickTextAreaEx::contentsChange);
并实现void contentsChange(int from, int charsRemoved, int charsAdded);函数
3.解决问题
3.1. undefined reference to QQuickTextControl::textCursor
参考:
https://forum.qt.io/topic/82772/undefined-reference-to-qquicktextcontrol-textcursor-const
原因是因为QQuickTextControl的声明如下
class Q_AUTOTEST_EXPORT QQuickTextControl : public QInputControl{…}
而Q_AUTOTEST_EXPORT定义为
在调用和源码编译时都如上图,没有导入和导出动态库
解决方法是 修改qquicktextcontrol_p.h和qquicktextcontrol_p_p.h文件
#include <private/qtquickglobal_p.h>
class Q_QUICK_PRIVATE_EXPORT QQuickTextControl : public QInputControl{…}
#include <private/qtquickglobal_p.h>
class Q_QUICK_PRIVATE_EXPORT QQuickTextControlPrivate : public QobjectPrivate{…}
然后重新编译 qtdeclarative模块生成 Qt5Quick动态库,替换对应编译环境的动态库文件
qtdeclarative下载地址 http://download.qt.io/archive/qt/5.9/5.9.8/submodules/
MinGW:
Qt5Quick.dll Qt5Quick.a Qt5Quickd.dll Qt5Quickd.a
MSVC:
armeabi_v7a:
libQt5Quick.so (libQt5Quick.a 不需要)
3.1.1 armeabi_v7a 环境 qtdeclarative模块的编译
MinGW和MSVC 环境的编译,可以直接用Qt Creator打开pro文件编译,armeabi_v7a 环境在Qt Creator中编译则会报错。
我的做法是在 Cygwin 模拟终端中编译(在windows cmd终端应该也可以)。
环境变量设置和编译命令是从 构建设置获得的。
3.1.1.1环境变量:设置
export ANDROID_HOME=E:/ProgramFiles/Tools/Android/android-sdk
export ANDROID_NDK_HOST=windows-x86_64
export ANDROID_NDK_PLATFORM=android-16
export ANDROID_NDK_ROOT=D:/ProgramFiles/android-ndk-r17c
export ANDROID_SDK_ROOT=E:/ProgramFiles/Tools/Android/android-sdk
export PATH=${PATH/mingw53_32/android_armv7}
export PATH=/cygdrive/d/ProgramFiles/android-ndk-r17c/prebuilt/windows-x86_64/bin:/cygdrive/d/ProgramFiles/android-ndk-r17c/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin:/cygdrive/d/ProgramFiles/Qt5.9.8/5.9.8/android_armv7/bin/:$PATH
3.1.1.2 进入 qtdeclarative-opensource-src-5.9.8 目录 执行:
qmake qtquickcontrols.pro -spec android-g++ "CONFIG+=debug" "CONFIG+=qml_debug" && make.exe qmake_all
然后再执行:
make -j4
3.1.1.3 examples 子模块可以删除去掉。编译过程中虽然仍有报错,但最终会生成libQt5Quick.so
3.1.2虽然 能够成功编译出Qt5Quick 动态库,但生成的文件比原有的文件大很多,不知道哪里设置的原因。
3.2 正确的在qml中使用扩展的 TextAreaEx
3.2.1 一般在qml中使用使用 C++类,需要在main 函数里注册:
QQmlApplicationEngine engine;
qmlRegisterType< QuickTextAreaEx >("qtproject.extern", 1, 1, "TextEditEx");
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
在qml中添加
import qtproject.extern 1.1;
即可使用 TextEditEx
3.2.2 只注册QuickTextAreaEx无法使用QquickTextEdit,和QQuickTextArea 中被 “REVISION n”修饰的Q_PROPERTY 属性。比如 QquickTextEdit 一些属性:
Q_PROPERTY(qreal padding READ padding WRITE setPadding RESET resetPadding NOTIFY paddingChanged REVISION 6)
Q_PROPERTY(qreal topPadding READ topPadding WRITE setTopPadding RESET resetTopPadding NOTIFY topPaddingChanged REVISION 6)
Q_PROPERTY(qreal leftPadding READ leftPadding WRITE setLeftPadding RESET resetLeftPadding NOTIFY leftPaddingChanged REVISION 6)
Q_PROPERTY(qreal rightPadding READ rightPadding WRITE setRightPadding RESET resetRightPadding NOTIFY rightPaddingChanged REVISION 6)
Q_PROPERTY(qreal bottomPadding READ bottomPadding WRITE setBottomPadding RESET resetBottomPadding NOTIFY bottomPaddingChanged REVISION 6)
Q_PROPERTY(QString preeditText READ preeditText NOTIFY preeditTextChanged REVISION 7)
Q_SIGNALS:
Q_REVISION(6) void editingFinished();
Q_REVISION(6) void paddingChanged();
Q_REVISION(6) void topPaddingChanged();
Q_REVISION(6) void leftPaddingChanged();
Q_REVISION(6) void rightPaddingChanged();
Q_REVISION(6) void bottomPaddingChanged();
运行时会报错"TextAreaEx.leftPadding" is not available in qtproject.extern 1.1.”
解决方法是将 注册方法改为下面这样:
qmlRegisterType<QQuickTextEdit,7>("qtproject.extern", 1, 1, "QTextEdit");
qmlRegisterType<QQuickTextArea,7>("qtproject.extern", 1, 1, "QTextArea");
qmlRegisterType<QuickTextAreaEx,7>("qtproject.extern", 1, 1, "TextAreaEx");
qmlRegisterType <**,n> 数字n 只要大于等于 “REVISION n” 中的n即可
参考:https://stackoverflow.com/questions/56699204/q-revision-meaning-in-qt-class
4.将QuickTextAreaEx做成qml plugin插件使用
参考https://blog.csdn.net/yizhou2010/article/details/87620776
https://blog.csdn.net/u013411873/article/details/95936614
4.1生成动态库
4.1.1新建插件项目:
4.1.2配置 .pro文件
.
4.1.3qmldir 内容
module QuickTextAreaEx
plugin quicktextareaexplugin
4.1.4 QuickTextAreaEx 类内容同3
4.1.5 修改QuickTextareaExPluginPlugin 构造函数
void QuickTextareaExPluginPlugin::registerTypes(const char *uri){
qmlRegisterType<QuickTextAreaEx>(uri, 1, 0, "TextareaEx");
qmlRegisterType<QQuickTextEdit,7>(uri, 1, 0, "QTextEdit");
qmlRegisterType<QQuickTextArea,7>(uri, 1, 0, "QTextArea");
}
4.1.6 编译生成动态库插件
4.2使用 plugin 插件
4.2.1 生成 plugin.qmltypes 文件
4.2.1.1 如下图将dll 、.a、qmldir、放在 QuickTextareaEx文件夹下,
就是4.1.3 qmldir 内容“module QuickTextAreaEx”
4.2.1.2 生成qmltypes文件
打开Qt 5.9.8 (MinGW 5.3.0 32-bit),
执行命令 (一定要绝对路径)
qmlplugindump -nonrelocatable QuickTextAreaEx 1.0 D:\ > D:\QuickTextAreaEx\plugin.qmltypes
4.3plugin插件的使用
4.3.1 .pro配置
“QML_IMPORT_PATH = $$PWD/imports/”是在编译时路径
运行时只需将 dll和 qmltypes放在对应位置即可
./ HexTextArea2.exe
./QuickTextAreaEx/qmldir
./QuickTextAreaEx/quicktextareaexplugin.dll
4.4 对于 “module QuickTextAreaEx” 需配合 https://blog.csdn.net/u013411873/article/details/95936614 理解
5.源码