Qt QML的插件(Qt Quick 2 Extension Plugin)方法

news2024/11/25 7:51:58

Qt Quick的插件方法

  • 序言
  • 环境
  • 前置注意
  • 概念——Qt Quick插件的相关知识
    • 插件里的qml文件
    • 模块名的相关知识
      • 模块名本身注意事项
      • 模块名版本注意事项
  • 以示例来说明
    • 创建插件
      • qmltypes的生成
        • qmltypes的可能性失效
    • 插件的编码注意
      • 1、插件模块版本控制
      • 2、pro里的注意
    • 调用插件
      • 插件信息输入

序言

网上有很多的Qt Quick扩展插件方法,比如龚建波或者诺谦的,确实是教了怎么做,可是还是按着做时还是出现了一些问题,有些细节上的理解容易与作者想的不一样,对于新手不太友好,不够简单和全面,起码我看着没有第一时间弄出来,还花了不少时间研究才最终弄出来。

因此我作为更新手的视角也来写一下插件的用法,以供学习的人分别参考。

如果有兴趣,我后面也可以出C++的插件方法,不过感觉资料很多没什么必要。

环境

Qt5.15(MSVC2019)
VS2019

前置注意

示例插件名: TestQmlPlugin
模块名:QmlEditorStyle
插件库名:TestQmlPlugin

概念——Qt Quick插件的相关知识

Qt的插件,有一个很大的特点,就是不需要lib文件,只需要dll文件,就可以进行动态装载。

如果是C++,会需要QPluginLoader进行加载,不过其实也是用的QLibrary。

QML不需要自己来加载,因为Engine已经负责了这个加载任务。

不过相对的,Qt Quick也需要一些信息,比如插件的外接接口的信息,我们提供的就是一个名为:qmldir 的文件,无.txt,.pri那些后缀,就叫qmldir
在这里插入图片描述

关于qmldir里面该怎么写,Qt的助手就已经有相关说明:

在这里插入图片描述

具体有什么可以自行翻找查阅,但是qmldir最起码需要两条信息,也是我演示用的其中两条:
在这里插入图片描述
在这里插入图片描述
一个交代了QML的import时的模块名,另一个交代了插件库的库名。
举例:
qmldir文件里只有两行信息:

module QmlEditorStyle
plugin TestQmlPlugin

而其分别影响的是:

module QmlEditorStyle
->

import QmlEditorStyle 1.0

.
plugin TestQmlPlugin
->
TestQmlPlugin.dll
TestQmlPlugind.dll
.

插件里的qml文件

有些人,会想将QML文件放进插件里,这样调用的时候就可以拿着dll随便用了。

可惜,实现不了。

插件本质上是一种特殊的动态库,动态库你我都懂,如果需要调用动态库里面的类,就需要提供一些接口.h文件。

然后编码时才可以自由访问提供的接口类。

同理,你要调用QML文件,就必须要有接口,可怎么提供接口呢?QML文件就没有分什么.h文件,.cpp文件,它是解释型语言,就算用插件,你也需要提供源码才可以。

除非你用C++实现QML的项,然后封装进插件里,再放出.h文件即可。(因为QML的项本质上是QtC++的实现而来的。)

将自己封装好的QML文件放在插件库文件夹里,即下文会提到的QmlEditorStyle文件夹里。

再将qmldir文件夹的末尾,加上资源标识符 注册的版本 对应文件
在这里插入图片描述
其对应的就是

qmlRegisterType<MySliderItem>("QmlEditorStyle", 1, 0, "Slider");

ResourceIdentifier对应的是Slider,注册的QML类型
InitialVersion对应的是1, 0,C++是1逗号0,qmldir是1点0
File对应的是MySliderItem,实际的QML文件,C++的是实际的C++类

module QmlEditorStyle
...
Slider 1.0 MySliderItem.qml

不过一般都会文件和类型名一致。

这样就算是将QML文件放进插件库里了,当调用该文件夹的插件时,也会囊括QML文件了。

模块名的相关知识

Qt Quick的import模块名,值得注意的是,其代表的其实是文件夹名,什么意思呢?
比如说QtQuick.Window 2.15这个import的模块,实际代表的是QtQuick文件夹里的Window.2文件夹
在这里插入图片描述

Creator会根据这个,从路径信息里找到对应的文件夹,找到对应的plugins.qmltypes文件和qmldir文件,进而读取进来。
在这里插入图片描述

模块名本身注意事项

有的人可能要自己定义一个插件库,比如说:[公司名].[库名]
然后就打算这样命名文件夹:Company.TestQmlPlugin

这样是行不通的,Creator会找不到插件库的,你得改成 Company文件夹里放TestQmlPlugin文件夹

模块名版本注意事项

那么如果说我们导入示例插件TestQmlPlugin呢?

比如说import TestQmlPlugin 1.0
就直接是TestQmlPlugin文件夹里放就行,后面的.1可加可不加,没有会默认按.1处理

如果是import TestQmlPlugin 2.0
就需要命名为:TestQmlPlugin.2文件夹,这个不能缺少后面的.2

.
另外还需要一个文件,plugins.qmltypes,其提供给Creator提示信息,是由我们用qmlplugindump生成的,或者qmake的里面设置一些东西可以自动生成。

基本这些加上库文件就组成了一个插件。
在这里插入图片描述

以示例来说明

创建插件

在这里插入图片描述

按选择,创建插件的这个工程名,与提供出来的插件名不影响
在这里插入图片描述
选择qmake还是cmake进行编译,Qt6只运行用cmake,如果用QML,以后考虑用Qt6的,就选择cmake。
但是呢,这里现在暂时只讲解qmake方法,cmake待后续添加。
在这里插入图片描述
接下来选择一些基本信息,如最低Qt版本这些,URI的com.mycompany.qmlcomponents,可以改为我们示例用的模块名QmlEditorStyle,或者你打算设置的模块名。
在这里插入图片描述
.
在这里插入图片描述
.
在这里插入图片描述
如此就生成了初始的插件
在这里插入图片描述
进行构建,就可以生成debug版本或者release版本这些的dll了。

不需要在意debug版本,dll名是否会因为有个d后缀而影响的问题,Qt在读取的时候会自动判断的了。

将构建好的dll和qmldir放进由模块名为文件夹名的文件夹里。
在这里插入图片描述

qmltypes的生成

在该文件夹的上一级,用cmd输入:

qmlplugindump QmlEditorStyle 1.1 . > .\QmlEditorStyle\plugins.qmltypes

其的输入规则是:
qmlplugindump+空格+[模块名]+空格+[版本]+空格+[模块所在目录]+空格+ > +空格+[要生成的路径]

需要注意的是,[模块所在目录]是指以模块名为文件夹名的文件夹所在目录,即QmlEditorStyle文件夹。
在这里插入图片描述
生成之后会在模块文件夹里即QmlEditorStyle生成一个plugins.qmltypes,是qmlplugindump根据插件里注册的内容,生成的信息。

qmltypes的可能性失效

1、生成了plugins.qmltypes可能是缺少信息的,也可能是我指令有误之类的吧,但是参考别人的也都是相同的。
在这里插入图片描述
注意上方的exports这行信息,在每个MyItem的左边,需要加上模块名QmlEditorStyle/MyItem 1.1

这样才能生效

2、如果上方加上了模块名仍然Creator提示无效,则在qmldir里新增一行:

typeinfo plugins.qmltypes

不过一般来说加不加不影响

3、如果上边的都弄了之后,发现在导入的地方存在一个错误提示
Error 1:1 预计符号numeric literal
这是编码问题,我遇到了,发现plugins.qmltypes是utf-16格式的,于是我转成了utf-8格式的就正常了
.

插件的编码注意

1、插件模块版本控制

Qt Quick的模块版本,是由注册到该版本的项决定是否存在的。

什么意思呢?

testqmlplugin_plugin.cpp里,有个代码

void TestQmlPluginPlugin::registerTypes(const char *uri)
{
	qmlRegisterType<MyItem>(uri, 1, 0, "MyItem");
}

uri代表的是会传入你编写的模块名,比如说该示例是QmlEditorStyle,uri也是这个值。

第二个参数是主版本号,第三个参数是次版本号。

就是import QmlEditorStyle 1.0里的1是主版本号,0是次版本号。

这样将MyItem注册在了1.0这个模块里,1.0就存在了一个MyItem的项。

你如果后面都弄好后平白无故去导入1.1模块也是不存在的,会提示不存在这个模块,因为里面不包含任何项。

2、pro里的注意

TEMPLATE = lib
TARGET = TestQmlPlugin		// 插件的dll名称
QT += qml quick
CONFIG += plugin c++11

TARGET = $$qtLibraryTarget($$TARGET)
uri = QmlEditorStyle		// 代表着模块名,一般用不上

此处如果额外增加下列代码

CONFIG += qmltypes #自动生成 plugins.qmltypes
QML_IMPORT_NAME = TestQmlPlugin
QML_IMPORT_MAJOR_VERSION = 1

就会自动在构建之后产生一个plugins.qmltypes代码了,可以免掉后面再自行命令行用qmlplugindump了。

不过要自行更改QML_IMPORT_MAJOR_VERSION版本,其代表的是主版本号。

.

调用插件

接下来就是怎么去使用我们的插件了

首先,在上文生成插件后,有一个QmlEditorStyle的文件夹。

将这个文件夹放到使用的工程文件下,专门放QML插件的一个文件夹下,我这里是qml文件夹,你也可以命名为DLL或者其他什么的,名字不影响。
在这里插入图片描述

插件信息输入

有两处需要填写插件信息的:
第一处是pro里,有个QML_IMPORT_PATH,增加qml所在路径。

QML_IMPORT_PATH += C:/Project/Qt/build-testQtQML-Desktop_Qt_5_15_2_MSVC2019_32bit-Release/release/qml

我这里放的是生成的目标路径位置,也可以放工程里,是一样的,不影响。

第二处是在main.cpp里,有个engine,调用engine增加插件路径。

QQmlApplicationEngine engine;
engine.addImportPath(QString("%1/qml").arg(app.applicationDirPath()));		// 可以用绝对路径之类的,指向qml文件夹
const QUrl url(QStringLiteral("qrc:/main.qml"));
...

第三处是调用处的qml里:

import QtQuick 2.15
import QtQuick.Window 2.15
import QmlEditorStyle 1.1			// 调用对应的模块

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")


    MyItem {			// 使用默认提供的C++的Item
        width: 100
        height: 100
        fillColor: "red"
    }
}

上边如果import QmlEditorStyle 1.1或者MyItem有报错,则是没有配置好。

如果能正常运行,则是plugins.qmltypes没有弄好。

以上全部都弄好后,应该是这样的:
正常显示无报错
正常显示无报错

在这里插入图片描述
item能正常显示

至此,Qt Qucik的插件方法教程结束。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1578673.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

element-ui drawer 组件源码分享

今日简单分享 drawer 组件的源码实现&#xff0c;从以下五个方面来分享&#xff1a; 1、drawer 组件页面结构 2、drawer 组件属性 3、drawer 组件 slot 4、drawer 组件方法 5、drawer 组件事件 一、drawer 组件页面结构 二、drawer 组件属性 2.1 append-to-body 属性&am…

(Atcoder Beginner Contest 348)题解

前言 这是我第 4 4 4 次做出 F F F 题&#xff0c;庆祝上蓝&#xff01; 正题 本题解提供 A − F A-F A−F 题题解&#xff0c;欢迎诸位大佬参考。 第 1 题 Penalty Kick 照例很水&#xff0c;模拟即可。 #include <bits/stdc.h> using namespace std; #define…

一种新兴的身份安全理念:身份结构免疫

文章目录 前言一、从身份管理到身份结构免疫二、身份结构免疫应用实践三、典型应用场景前言 随着组织的数字身份数量激增,基于身份的网络攻击活动也在不断增长。在身份优先的安全原则下,新一代身份安全方案需要更好的统一性和控制度。而在现有的身份管理模式中,组成业务运营…

MySQL相关问题快问快答

我写这篇文章的目的只有一个&#xff1a;通过这些问题来帮助我去将我脑子里的MySQL脑图给巩固熟悉&#xff0c;通过回答这些问题&#xff0c;让我对脑子里的MySQL知识有更深的印象&#xff0c;当什么时候我的MySQL脑图不熟的时候&#xff0c;我就可以拿这篇文章来去巩固一下&am…

ctfshow web入门 php特性 web123--web139

web123 必须传CTF_SHOW&#xff0c;CTF_SHOW.COM 不能有fl0g 在php中变量名字是由数字字母和下划线组成的&#xff0c;所以不论用post还是get传入变量名的时候都将空格、、点、[转换为下划线&#xff0c;但是用一个特性是可以绕过的&#xff0c;就是当[提前出现后&#xff0c;…

【javaWeb 原理篇】底层实现原理(快速学习配置原理,Bean管理)

Spring底层 配置优先级Bean管理获取beanBean的作用域第三方Bean SpringBoot原理起步依赖自动配置自动配置的原理自定义starter 配置优先级 Spring中的配置文件如果配置了相同的内容则根据配置优先级进行配置: application.properties>application.yml>application.yaml …

90天玩转Python—08—基础知识篇:Python优秀代码的编程规范

90天玩转Python系列文章目录 90天玩转Python—01—基础知识篇:C站最全Python标准库总结 90天玩转Python--02--基础知识篇:初识Python与PyCharm 90天玩转Python—03—基础知识篇:Python和PyCharm(语言特点、学习方法、工具安装) 90天玩转Python—04—基础知识篇:Pytho…

Python技能树学习-函数

题目一&#xff1a;递归调用 函数的参数&#xff1a; def dump(index, default0, *args, **kw): print(打印函数参数) print(---) print(index:, index) print(default:, default) for i, arg in enumerate(args): print(farg[{i}]:, arg) for…

跨越网络边界:借助C++编写的下载器程序,轻松获取Amazon商品信息

背景介绍 在数字化时代&#xff0c;数据是新的石油。企业和开发者都在寻找高效的方法来收集和分析网络上的信息。亚马逊&#xff0c;作为全球最大的电子商务平台之一&#xff0c;拥有丰富的商品信息&#xff0c;这对于市场分析和竞争情报来说是一个宝贵的资源。 问题陈述 然…

ArcGIS和ArcGIS Pro快速加载ArcGIS历史影像World Imagery Wayback

ArcGIS在线历史影像网站 World Imagery Wayback(网址:https://livingatlas.arcgis.com/wayback/)提供了数期历史影像在线浏览服务,之前不少自媒体作者在文中宣称其能代表Google Earth历史影像。 1、一点对比 (1)同一级别下的版本覆盖面 以下述区域为例,自2014年2月20…

面试题:ConcurrentHashMap

ConcurrentHashMap 是一种线程安全的高效Map集合 底层数据结构&#xff1a; JDK1.7底层采用分段的数组链表实现 JDK1.8 采用的数据结构跟HashMap1.8的结构一样&#xff0c;数组链表/红黑二叉树。 1. JDK1.7 数据结构 提供了一个segment数组&#xff0c;在初始化Concurre…

SQL注入利用学习-Union联合注入

联合注入的原理 在SQL语句中查询数据时&#xff0c;使用select 相关语句与where 条件子句筛选符合条件的记录。 select * from person where id 1; #在person表中&#xff0c;筛选出id1的记录如果该id1 中的1 是用户可以控制输入的部分时&#xff0c;就有可能存在SQL注入漏洞…

【学习】软件验收测试,能否选择第三方检测机构进行测试?

随着信息技术的快速发展&#xff0c;软件已经成为各行各业中不可或缺的一部分。为了保证软件的质量和稳定性&#xff0c;验收测试成为了软件开发过程中至关重要的一环。那么&#xff0c;第三方软件测试机构可以做验收测试吗&#xff1f;我们一起来看下今日的分享。 一、验收测…

目标检测——色素性皮肤病数据集

一、重要性及意义 首先&#xff0c;色素性皮肤病变是一类常见的皮肤疾病&#xff0c;其发病率有逐年增高的趋势。这些病变可能由遗传或环境因素导致黑素细胞生成异常&#xff0c;如黑色素瘤等。黑色素瘤具有极高的恶性率和致死率&#xff0c;而且恶化可能性大&#xff0c;容易…

大模型基础知识 - 语言模型及其演进

开场白 人工智能发展到现在&#xff0c;在2个重要领域取得了重大突破&#xff0c;有望达到人类水平&#xff1a; 计算机视觉 &#xff08;Computer Vision, CV&#xff09;-> 希望机器帮助人类处理图像数据自然语言处理&#xff08;Natural Language Processing, NLP&…

rsync+inotify实时同步 和 GFS分布式文件系统概述

目录 一、rsyncinotify实时同步 1.1.实时同步的优点 1.2.Linux内核的inotify机制 1.3.发起端配置rsyncInotify 1.4.配置远程登陆 1.4.1.修改rsync源服务器配置192.168.190.101 ​编辑 1.4.2.配置server 192.168.190.102 二、GFS 2.1.GlusterFS简介 2.2.GlusterFS特点…

6 个典型的Java 设计模式应用场景题

单例模式(Singleton) 场景: 在一个Web服务中,数据库连接池应当在整个应用生命周期中只创建一次,以减少资源消耗和提升性能。使用单例模式确保数据库连接池的唯一实例。 代码实现: import java.sql.Connection; import java.sql.SQLException;public class DatabaseConne…

【SCI绘图】【热力图系列2 R】多特征相关性分析热力图指定聚类 R

SCI&#xff0c;CCF&#xff0c;EI及核心期刊绘图宝典&#xff0c;爆款持续更新&#xff0c;助力科研&#xff01; 本期分享&#xff1a; 【SCI绘图】【热力图系列2 R】多特征相关性分析热力图指定聚类 R 1.环境准备 library(gplots) library(RColorBrewer)2.数据读取 ###…

AI如何与健康管理相结合

AI与健康管理的结合是当今科技和医疗领域的一个重要趋势。随着人工智能技术的不断发展和完善&#xff0c;它在健康管理方面的应用越来越广泛&#xff0c;为人们提供了更加高效、精准和个性化的健康管理服务。本文将探讨AI如何与健康管理相结合&#xff0c;以及这种结合所带来的…

1.Godot引擎|场景|节点|GDS|介绍

Godot介绍 Godot是一款游戏引擎 可以通过在steam商城免费下载 初学者和编程基础稍差的推荐学习使用GDScript&#xff0c;和python有些相似 Godot节点 Godot的开发思想——围绕节点 节点的特征与优势 最常用基本的开发组件大部分都具有具体的功能&#xff0c;如图片&#xf…