目錄

(放個目錄方便大家預覽。破乎不支持目錄,這個目錄是從博客複製過來的,點擊跳轉到博客)

  • 簡介
  • 近期訊息
    • Qt Design Studio
    • TaoQuick
  • Qt資源管理
    • qrc內容
    • 編譯和載入qrc
    • 資源的引用
    • 插件中註冊資源
  • Qml模塊
    • qmldir文件
      • 示例
      • 不用開放Qml源碼
  • Designer支持
    • metainfo
    • 帶資源的組件,需要用C++擴展註冊資源
    • 安裝
  • 最簡Demo

簡介

本文是《Qml組件化編程》系列文章的第十篇,濤哥將教大家,Qml自定義模塊的知識。

特別是最近的研究結果:如何讓Qml模塊在Designer中拖拽使用。濤哥希望有更多的人學會這個技能。

註:文章主要發布在濤哥的博客 和 濤哥的知乎專欄-Qt進階之路

近期訊息

(先播點新聞)

Qt Design Studio

2019年5月20的時候,Qt官方放出了Qt Design Studio的1.2 beta版, 免費使用/暫不開源。

下載地址在這:

download.qt.io/developm

Qt Design Studio是主要給美工使用的一款UI工具。

Qt在Photo Shop/Sketch這兩款工具中,提供了QtBridge插件,可以將設計好的資源直接導出成Qml工程。

導出的工程可以用Qt Design Studio/QtCreator打開,用拖拖拽拽的方式,實現各種功能、動畫等等。

QtDesignStudio目前還不成熟,但未來是一片光明。等Designer做好了,就不再需要手寫Qml代碼,拖拖拽拽就能搞定界面部分。

只剩下邏輯處理和後端功能才需要寫代碼/寫js腳本。

Qt Design Studio目前與QtCreator的差異是,前者內置了一些特殊的模塊:包括 Shapes圖元、Effects等,

Qt Design Studio還使用了qmlproject文件作為工程管理。

除此之外,功能都是一樣的。幀動畫編輯器在QtCreator中也是可以使用的。

TaoQuick

最新的TaoQuick (tag: 0.1.6), 已經支持在QtCreator中拖拽使用了

代碼倉庫在這:TaoQuick

(下面進入正題)

Qt資源管理

(有必要先說一下資源管理,這部分內容幫助文檔都有,搜索關鍵詞為」rcc」 或 「Qt Resource」)

Qt提供了一個資源管理工具rcc,可以將各種資源文件壓縮、打包進二進位程序。

通常用來打包各種圖片、Qml文件、配置文件或數據文件等等,只要將資源文件添加到qrc文件中即可。

qrc文件是xml格式的文本文件,裡面記錄著添加的各種資源。

qrc內容

示例 TaoResource.qrc:

<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>images/copy.png</file>
<file>images/cut.png</file>
<file>images/new.png</file>
<file>images/open.png</file>
<file>images/paste.png</file>
<file>images/save.png</file>
</qresource>
</RCC>

編譯和載入qrc

只要在pro文件中寫上 RESOURCES = TaoResource.qrc就可以了。qmake會自動將資源壓縮、打包進exe/dll程序

也可以使用命令行手動編譯:

rcc -binary TaoResource.qrc -o TaoResource.rcc

或者

rcc -binary TaoResource.qrc -o TaoResource.dll

這種方式編譯出來的,是一個純粹的資源插件,擴展名寫什麼都無所謂的。

可以在代碼中動態載入資源、卸載資源

QResource::registerResource("/path/to/TaoResource.rcc");
QResource::unRegisterResource("/path/to/TaoResource.rcc");

資源的引用

使用」:/「 或者 「qrc:/「開頭的路徑即可,這兩者的區別濤哥未作總結,大家自己實踐吧。

cutAct = new QAction(QIcon(":/images/cut.png")

插件中註冊資源

在Qt插件中,添加了資源的情況下,需要用宏Q_INIT_RESOURCE來註冊資源

(Qt插件和前面的rcc編譯出來的不一樣,不是一個純粹的資源插件,不能直接被QResource::registerResource識別)

TaoClass::TaoClass() : BaseClass()
{
Q_INIT_RESOURCE(TaoResource);

QFile file(":/images/save.png");
...
}

Qml模塊

(這部分內容幫助文檔也有,搜索關鍵詞」QML Modules」)

設計Qml模塊的大致步驟如下:

  1. 實現Qml組件
  2. 實現qmldir文件
  3. 導出Qml插件類

如果要支持designer,還要加上一步:

  1. 創建designer文件夾,編寫metainfo文件

這一步暫時沒有任何文檔和工具,濤哥照貓畫虎做出來的。以後文檔肯定會出來的,現在有些功能不完善。

(參考Qt的支持Designer的Qml模塊。更深入的瞭解,在QtCreator源碼)

qmldir文件

(幫助文檔搜索關鍵詞 「qmldir」 或 「Module Definition qmldir…」)

示例

這裡以TaoQuick中的為例,我順手加了點注釋:

TaoQuick/TaoQuick/qmldir:

#模塊名稱 import使用的地方,就用這個名稱
module TaoQuick

#插件dll文件名稱,即 TaoQuick.dll
plugin TaoQuick

#依賴的模塊

depends QtQuick 2.12
depends QtQuick.Controls 2.12

# 這裡一堆的組件
TGradientBtn 1.0 BasicComponent/Button/TGradientBtn.qml
TImageBtn 1.0 BasicComponent/Button/TImageBtn.qml
TImgTextBtn 1.0 BasicComponent/Button/TImgTextBtn.qml
TTextBtn 1.0 BasicComponent/Button/TTextBtn.qml

TMoveArea 1.0 BasicComponent/Mouse/TMoveArea.qml
TTransArea 1.0 BasicComponent/Mouse/TTransArea.qml

TNormalProgress 1.0 BasicComponent/Progress/TNormalProgress.qml
TCircleProgress 1.0 BasicComponent/Progress/TCircleProgress.qml

TBusyIndicator 1.0 BasicComponent/Others/TBusyIndicator.qml
TDragItem 1.0 BasicComponent/Others/TDragItem.qml
TResizeBorder 1.0 BasicComponent/Others/TResizeBorder.qml
TToolTip 1.0 BasicComponent/Others/TToolTip.qml
TDialog 1.0 BasicComponent/Others/TDialog.qml
TPopup 1.0 BasicComponent/Others/TPopup.qml
TFPS 1.0 BasicComponent/Others/TFPS.qml

# 支持designer
designersupported

還有單例singleton、內部類型internal、C++類型描述typeinfo, 這些用法TaoQuick沒有用到,就不多說了。

plugin TaoQuick這一句,表示對應的dll文件名稱。dll是要寫一個C++類,繼承自QQmlExtensionPlugin

看一下TaoQuick中的實現

//taoquick_plugin.h
#pragma once

#include <QQmlExtensionPlugin>

class TaoQuickPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)

public:
void registerTypes(const char *uri) override;
};

//taoquick_plugin.cpp
#include "taoquick_plugin.h"
void TaoQuickPlugin::registerTypes(const char *uri)
{
Q_UNUSED(uri);
Q_INIT_RESOURCE(Qml); //註冊Qml.qrc
}

運行時候的bin路徑文件結構是這樣的:

TaoQuick文件夾的名字就是模塊名字

不用開放Qml源碼

這裡說一下,TaoQuick項目中還有一個qmldir文件:

TaoQuick/TaoQuick/Qml/qmldir:

TGradientBtn 1.0 BasicComponent/Button/TGradientBtn.qml
TImageBtn 1.0 BasicComponent/Button/TImageBtn.qml
TImgTextBtn 1.0 BasicComponent/Button/TImgTextBtn.qml
TTextBtn 1.0 BasicComponent/Button/TTextBtn.qml

TMoveArea 1.0 BasicComponent/Mouse/TMoveArea.qml
TTransArea 1.0 BasicComponent/Mouse/TTransArea.qml

TNormalProgress 1.0 BasicComponent/Progress/TNormalProgress.qml
TCircleProgress 1.0 BasicComponent/Progress/TCircleProgress.qml

TBusyIndicator 1.0 BasicComponent/Others/TBusyIndicator.qml
TDragItem 1.0 BasicComponent/Others/TDragItem.qml
TResizeBorder 1.0 BasicComponent/Others/TResizeBorder.qml
TToolTip 1.0 BasicComponent/Others/TToolTip.qml
TDialog 1.0 BasicComponent/Others/TDialog.qml
TPopup 1.0 BasicComponent/Others/TPopup.qml
TFPS 1.0 BasicComponent/Others/TFPS.qml

這裡面module、plugin這些東西都沒有,只有組件。而且這個文件是加入了qrc的,即編譯進dll裡面了。

前面那個qmldir,需要和dll放在同級目錄,dll模塊才能被Qml引擎導入。

後面這個qmldir的作用是,導出dll插件時,不用帶上qml源碼,直接import 這個qmldir的資源路徑,就能夠用裡面的組件了。

也就是說,使用的地方,要寫兩句import

import TaoQuick 1.0
import "qrc:/Tao/Qml/"

這種用法不能在QtCreator高亮,運行沒問題。(商業版似乎有更高級的資源內建功能,或許可以支持高亮,後續再研究)

具體的實現和用法,可以參考TaoQuick 或者文末的最簡Demo。

TaoQuick中的qmake語法,可以參考另一篇文章 <Qt實用技能2-用好qmake>

Designer支持

再看一下效果:

要支持Designer,需要以下步驟:

首先要在Qml路徑下,創建一個designer文件夾。必須叫這個名字

其次要放一個擴展名為.metainfo的文件,裡面按格式寫上組件信息。名字似乎沒有要求。

最後,將整個Qml文件夾拷貝到[QTDIR]/qml/路徑下,並把文件夾名字改成模塊名字。

TaoQuick項目的路徑是這樣的:

metainfo

metainfo文件,目前沒有文檔、沒有自動生成工具,只能手動寫,語法和qml語法類似。(可以參考QtCreator源碼,裡面有完整的解析器)

MetaInfo {
Type {
name: "TaoQuick.BasicComponent.Button.TGradientBtn"
icon: "images/TGradientBtn.png"

ItemLibraryEntry {
name: "TGradientBtn"
category: "TaoQuick - Buttons"
libraryIcon: "images/TGradientBtn.png"
version: "1.0"
requiredImport: "TaoQuick"
Property { name: "width"; type: "int"; value: 120 }
Property { name: "height"; type: "int"; value: 80 }
}
}
}

頂層MetaInfo為固定寫法

接下來一個Type就對應Designer中的一個可拖拽的組件:

* name應該算作Qml組件文件的路徑,路徑分隔符用"點", 路徑默認從[QTDIR]/qml開始,如果有自定義qml 導入路徑,應該可以從相應的路徑開始查找(未嘗試)。

* icon 就是小圖標了,用來在Designer界面上預覽。這裡的images路徑,默認從designer文件夾開始

ItemLibraryEntry 是對這個組件更詳細的描述:

* name 顯示在Designer上面的名字
* category 分組的名字
* libraryIcon 小圖標,和前面那個一樣(不懂有什麼區別,先照抄)
* version 版本 (TaoQuick都是1.0)
* requiredImport 必要的導入的模塊
* Property 屬性。就是可以在Designer中調整、做幀動畫的。

Property支持的關鍵字有 name type value三個。 type 的值,暫時沒有完整的支持列表,源碼裡面能翻到Qml的基礎類型[「boolean」, 「int」, 「real」, 「string」, 「url」, 「color」], Qt發行的Qml中,還能看到」binding」。

(qtcreator-4.9.0qt-creator-opensource-src-4.9.0srcpluginsqmldesignerdesignercoremetainfometainfo.cpp)

屬性這裡,應該是QtCreator還沒有開發完整。Qml組件,metainfo裏什麼屬性都不寫,Designer裡面一個屬性都看不到。就寫一個width屬性,其它的屬性也自動給列出來了。

但是Color這種,即使寫了color,還是按照binding字元串處理的,不能用顏色選擇器改顏色。只能等QtCreator後續版本了。

Qt自帶的Rectangle一類,是從C++裡面寫的,Color屬性是可以用顏色選擇器的。Qt自帶的Qml組件Color屬性也是按binding處理的。

帶資源的組件,需要用C++擴展註冊資源

前面示例那個FPS組件,用到了一張圖片。圖片資源要麼和Qml文件放一起,用」file:///./「的方式訪問,要麼放進資源裏,用C++註冊。

所以在前面的TaoQuick安裝路徑中,有一個dll文件。C:Qt5.12.3msvc2017_64qmlTaoQuickTaoQuick.dll

然後封裝這個組件的時候,還要再import一下TaoQuick.dll, 即import TaoQuick 1.0

圖片路徑就用資源路徑

//TFPS.qml
import QtQuick 2.12
import QtQuick.Controls 2.12
import TaoQuick 1.0
Item {
property int fps: 60

property int frameCount: 0
property color textColor: "#f7e08c"
Image {
id: spinner
source: "qrc:/Core/Image/Others/spinner.png"
width: 32
height: 32
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
RotationAnimation on rotation {
from: 0
to: 360
running: true
loops: Animation.Infinite
duration: 1000
}
onRotationChanged: frameCount++
}
Text {
anchors.left: spinner.right
anchors.verticalCenter: parent.verticalCenter
text: "FPS" + fps
font.pixelSize: 20
renderType: Text.NativeRendering
color: textColor
}
Timer {
interval: 1000
repeat: true
running: true
onTriggered: {
fps = frameCount
frameCount = 0
}
}
}

安裝

可以手動拷貝文件夾,也可以參考TaoQuick的自動化安裝。

<Qt實用技能2-用好qmake>一文中已經說過了

只要增加一個pri文件,再執行make install即可

//TaoQuickDesigner.pri
taoquick_designer.files = $$PWD/designer/TaoQuick.metainfo
taoquick_designer.path = $$[QT_INSTALL_QML]/$${uri}/designer

toaquick_qmldir.files = $$PWD/qmldir
toaquick_qmldir.path = $$[QT_INSTALL_QML]/$${uri}

taoquick_qml_buttons.files = $$PWD/BasicComponent/Button/*.qml
taoquick_qml_buttons.path = $$[QT_INSTALL_QML]/$${uri}/BasicComponent/Button

taoquick_qml_mouse.files = $$PWD/BasicComponent/Mouse/*.qml
taoquick_qml_mouse.path = $$[QT_INSTALL_QML]/$${uri}/BasicComponent/Mouse

taoquick_qml_others.files = $$PWD/BasicComponent/Others/*.qml
taoquick_qml_others.path = $$[QT_INSTALL_QML]/$${uri}/BasicComponent/Others

taoquick_qml_progress.files = $$PWD/BasicComponent/Progress/*.qml
taoquick_qml_progress.path = $$[QT_INSTALL_QML]/$${uri}/BasicComponent/Progress

taoquick_degisner_images.files = $$PWD/designer/images/*.png
taoquick_degisner_images.path = $$[QT_INSTALL_QML]/$${uri}/designer/images

INSTALLS += taoquick_designer toaquick_qmldir taoquick_qml_buttons taoquick_qml_mouse taoquick_qml_others taoquick_qml_progress taoquick_degisner_images


最簡Demo

有讀者反饋說,上面的太複雜了,不容易抓住重點。濤哥特意寫了一個最簡單的Demo,給大家參考,github鏈接:

github.com/jaredtao/tao


推薦閱讀:
相關文章