qml基礎知識

李小飞11發表於2024-03-29

qml入門培訓筆記

QtQuick簡介

Qt Quick是Qt SDK 4.7中引入的一種新的介面開發框架,用於建立供移動和嵌入式裝置使用的動態觸控式介面和輕量級應用程式。它提供了一種高階使用者介面技術,使得開發者能夠輕鬆地為移動裝置建立流暢的使用者介面。Qt Quick包括介面指令碼語言QML、語言執行時、大量的使用者介面元素以及Qt Creator對QML的完美支援等眾多技術。

QML(Qt Meta-Object Language,Qt元物件語言)是Qt Quick模組用於編寫應用程式的標準庫。它提供了一個可視畫布,包括用於建立和動畫可視元件、接收使用者輸入、建立資料模型和檢視以及延遲物件例項化的型別。Qt Quick模組既提供了一個QML API(使用QML語言建立使用者介面的QML型別),也提供了一個C++ API(用於使用C++程式碼擴充套件QML應用程式)。

此外,Qt Quick能夠與C++和JavaScript有機結合進行混合程式設計。開發者可以使用已有的Qt技術結合Qt Quick,建立更好的應用程式。在Android等移動裝置上,Qt Quick應用預設使用OpenGL ES進行渲染,渲染效率很高,可以建立出非常炫酷的使用者介面

qml模組匯入

使用import進行匯入,這點和java,python等語言靠攏了,c++在20版本也引入import匯入,帶來了許多好處

引入 import 關鍵字以及模組系統的優勢主要體現在以下幾個方面:

  1. 編譯效率提升:模組系統避免了傳統 #include 預處理指令中可能導致的重複包含問題,模組僅匯入一次,不會造成重複編譯輸出。這可以顯著減少編譯時間,提高開發效率。

  2. 程式碼結構更清晰:使用 import 匯入模組,可以使程式碼的邏輯結構更清晰。每個模組都有明確的定義和邊界,有助於開發者更好地理解和維護程式碼。

  3. 更好的封裝和抽象:模組系統支援更好的封裝和抽象,可以將功能相關的程式碼組織在同一個模組中,隱藏實現細節,只暴露必要的介面。這有助於減少程式碼的耦合性,提高可維護性。

  4. 支援增量編譯:由於模組系統的特性,編譯器可以只對改變的模組進行編譯,而不是整個專案,從而實現增量編譯。這可以進一步縮短編譯時間,提高開發效率。

  5. 與標準庫和第三方庫的整合:模組系統可以更方便地與標準庫和第三方庫整合。開發者可以直接透過 import 匯入這些庫,而無需擔心標頭檔案路徑和依賴關係等問題。

  6. 支援併發開發:模組系統使得併發開發更加容易實現。不同的開發者可以獨立地開發不同的模組,而無需擔心相互之間的干擾和衝突。

qml註釋

和c++保持一致可以使用雙斜槓單行註釋和/*和*/進行多行註釋

import QtQuick
//這是一個主視窗
Window{
	width: 10
	height: 10
}

qm基本元件

QML(Qt Modeling Language)中的基本元件是QML自帶的,可以直接使用,無需額外定製。這些基本元件是構建QML應用程式的基石,用於建立使用者介面的各種元素。以下是一些常見的QML基本元件:

  1. Rectangle(矩形):這是一個預設尺寸為0的矩形,可以透過屬性設定其寬度、高度、顏色等。例如,可以建立一個特定尺寸和顏色的矩形來作為背景或其他介面元素。
  2. Text(文字):用於在介面上顯示文字內容。可以設定文字的字型、字號、顏色等屬性,以便呈現所需的文字樣式。
  3. Image(影像):用於載入和顯示圖片。可以指定圖片的源路徑、大小、縮放方式等。
  4. Button(按鈕):建立一個可點選的按鈕,用於觸發特定的事件或操作。可以設定按鈕的文字、樣式、點選事件處理器等。
  5. ListView(列表檢視):用於顯示一個專案列表,每個專案可以是文字、影像或其他QML元件。透過模型和檢視的方式,可以方便地管理和展示大量資料。

除了這些基本元件外,QML還提供了許多其他元件,如Slider(滑塊)、CheckBox(核取方塊)、RadioButton(單選按鈕)等,用於構建各種複雜的使用者介面。這些元件都可以透過屬性、訊號和槽等機制進行互動和通訊,實現豐富的使用者體驗。

qml自定義元件

在 QML 中,自定義元件是一個強大的功能,它允許你建立可重用的介面元素,這些元素可以在多個地方使用,從而提高了程式碼的可維護性和複用性。以下是如何建立 QML 自定義元件的基本步驟:

  1. 定義元件
    首先,你需要建立一個 QML 檔案來定義你的自定義元件。這個檔案通常包含元件的佈局、樣式和行為。例如,你可以建立一個名為 MyCustomComponent.qml 的檔案。
// MyCustomComponent.qml
import QtQuick 2.0

Item {
    width: 100
    height: 100
    // 其他屬性和子元件...
}
  1. 暴露屬性和方法
    在你的自定義元件中,你可能希望暴露一些屬性,以便在元件的外部進行設定,或者提供一些方法供外部呼叫。這可以透過在 QML 檔案中定義 propertyfunction 來實現。
// MyCustomComponent.qml
import QtQuick 2.0

Item {
    property color myColor: "red"
    property alias myWidth: width

    function setSize(newWidth: real) {
        width = newWidth
    }

    // 其他屬性和子元件...
}
  1. 註冊元件
    為了使 QML 引擎能夠識別和使用你的自定義元件,你需要在 QML 環境中註冊它。這通常在 C++ 程式碼中完成,使用 qmlRegisterType 函式。
#include <QQmlApplicationEngine>
#include <QQmlComponent>
#include <QGuiApplication>

int main(int argc, char *argv[]) {
    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    qmlRegisterType<MyCustomComponent>("MyComponents", 1, 0, "MyCustomComponent");
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}

在上面的程式碼中,qmlRegisterType 的引數分別是:

  • 自定義元件的 C++ 型別(如果你用 C++ 實現的話)
  • QML 型別名稱空間
  • QML 型別版本號
  • QML 中的型別名稱
  1. 使用元件
    一旦你的自定義元件被註冊,你就可以在任何 QML 檔案中像使用內建元件一樣使用它了。
// main.qml
import QtQuick 2.0
import MyComponents 1.0

Rectangle {
    width: 360
    height: 360

    MyCustomComponent {
        id: myComponent
        myColor: "blue"
        anchors.centerIn: parent
    }

    // 其他元件和佈局...
}
  1. 樣式和行為
    在自定義元件中,你可以使用 QML 的各種元素和屬性來定義元件的樣式和行為。你可以新增形狀、顏色、動畫、事件處理器等,以建立複雜的使用者介面元素。
  2. 測試和除錯
    建立完自定義元件後,確保在不同的場景和條件下對其進行測試,以確保其正確性和穩定性。使用 QML 的除錯工具可以幫助你快速識別和修復問題。

透過遵循這些步驟,你可以建立出功能豐富、可重用的 QML 自定義元件,從而提高你的 QML 應用程式的開發效率和質量。

qml動態載入元件

在 QML 中,動態載入元件意味著在執行時根據某些條件或使用者互動來載入和例項化元件。這可以透過幾種方式來實現,包括使用 Qt.createComponent()Loader 元素或者 QML 的動態匯入功能。以下是一些常見的方法:

使用 Loader 元素

Loader 元素是 QML 中用於動態載入元件的內建元素。它可以根據一個源 URL 或元件型別動態地載入元件。

import QtQuick 2.0

Rectangle {
    width: 360
    height: 360

    Loader {
        id: dynamicLoader
        width: parent.width / 2
        height: parent.height / 2
        anchors.centerIn: parent
        source: "MyDynamicComponent.qml" // 指向要載入的 QML 檔案的路徑
    }

    Button {
        text: "Reload Component"
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 10
        anchors.horizontalCenter: parent.horizontalCenter
        onClicked: dynamicLoader.source = "MyDynamicComponent.qml" // 重新載入元件
    }
}

在上面的例子中,Loader 元素載入了一個名為 MyDynamicComponent.qml 的 QML 元件。透過點選按鈕,可以重新載入該元件。

使用 Qt.createComponent()

Qt.createComponent() 方法可以根據 QML 檔案的 URL 建立一個元件物件。你可以使用它來動態地建立元件例項。

import QtQuick 2.0

Rectangle {
    width: 360
    height: 360

    Component.onCompleted: {
        var component = Qt.createComponent("MyDynamicComponent.qml");
        if (component.status === Component.Ready) {
            var myObject = component.createObject(this);
            myObject.anchors.fill: parent;
            myObject.visible: true;
        } else {
            console.error("Error loading component:", component.errorString());
        }
    }
}

在這個例子中,Qt.createComponent() 用於建立一個元件物件,然後使用 createObject() 方法來例項化它。

動態匯入 QML 模組

QML 也支援動態匯入模組,這允許你在執行時根據需要載入 QML 型別。這通常在 C++ 程式碼中使用 QQmlEngine::addImportPath()QQmlEngine::importModule() 來實現。

在 QML 檔案中,你可以使用 import 語句的變體來動態匯入模組:

import "MyModule" 1.0 as MyTypes // 動態匯入模組

Rectangle {
    width: 360
    height: 360

    MyTypes.MyDynamicComponent { // 使用模組中的元件型別
        anchors.fill: parent
    }
}

然後在 C++ 程式碼中,你需要確保 QML 引擎知道如何找到這個模組:

QQmlApplicationEngine engine;
engine.addImportPath("/path/to/my/module"); // 新增模組的匯入路徑
engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); // 載入主 QML 檔案

qml屬性

QML屬性是QML語言中的一個重要概念,它允許開發者在QML檔案中定義和使用各種型別的屬性,以便儲存和運算元據,控制元件的行為和外觀。QML屬性具有型別,並且可以具有初始值。它們通常以鍵值對的形式出現,例如width: 100text: 'Greetings'color: '#FF0000'

QML屬性可以根據其型別進行分類,包括:

  1. 基本型別屬性:這些屬性包括整型、浮點型、布林型、字串型等基本資料型別。
  2. 物件型別屬性:這些屬性可以是Qt Quick內建的物件型別,如顏色、矩形、點等,也可以是開發者自定義的元件物件型別。
  3. 列表型別屬性:這類屬性可以儲存多個值,這些值可以是基本型別或物件型別。
  4. 列舉型別屬性:這類屬性包含一組預定義的取值,用於限制屬性的取值範圍。

透過定義和使用QML屬性,開發者可以實現以下功能:

  • 靈活性:根據實際需求定義任意型別的屬性,以滿足不同的業務需求。
  • 可讀性:透過自定義屬性,可以使QML程式碼更加易讀和易理解。
  • 儲存和運算元據:自定義屬性可以用於儲存和操作應用程式中的資料,如使用者資訊、配置引數等。
  • 控制元件行為:透過自定義屬性,可以控制元件的可見性、可互動性等行為屬性。

在QML中,物件屬性定義了QML物件的狀態和行為。每個物件都可以有一些屬性,這些屬性可以被用來設定和獲取物件的各種特徵。此外,屬性可以透過屬性繫結來關聯不同物件的屬性,從而方便地構建互動式應用程式。

qml佈局

在 QML 中,佈局是管理元件位置和大小的關鍵部分。QML 提供了多種佈局元素,用於幫助開發者有效地組織和管理介面上的元素。這些佈局元素可以根據需要自動調整其子元素的位置和大小,以適應不同的螢幕尺寸和解析度。

QML 中常見的佈局元素包括:

  1. RowLayout 和 ColumnLayout

    • RowLayout 將子元素水平排列。
    • ColumnLayout 將子元素垂直排列。
    RowLayout {
        spacing: 10
        Rectangle { width: 50; height: 50; color: "red" }
        Rectangle { width: 50; height: 50; color: "green" }
        Rectangle { width: 50; height: 50; color: "blue" }
    }
    
  2. GridLayout

    • GridLayout 將子元素排列在網格中,可以指定行數和列數。
    GridLayout {
        columns: 2
        rows: 2
        Rectangle { color: "red"; Layout.fillWidth: true; Layout.fillHeight: true }
        Rectangle { color: "green"; Layout.fillWidth: true; Layout.fillHeight: true }
        Rectangle { color: "blue"; Layout.fillWidth: true; Layout.fillHeight: true }
        Rectangle { color: "yellow"; Layout.fillWidth: true; Layout.fillHeight: true }
    }
    
  3. StackLayout

    • StackLayout 將子元素堆疊在一起,每次只顯示一個子元素。
  4. FlowLayout

    • FlowLayout 類似於 HTML 中的流式佈局,子元素按照它們在 QML 檔案中出現的順序排列,當一行放不下時,會自動換行。
  5. Anchors

    • 雖然 Anchors 不是專門的佈局元素,但它提供了一種強大的方式來手動控制元件的位置和大小。Anchors 可以繫結到父元素或其他元素的邊緣,以實現精確的佈局控制。
    Rectangle {
        width: 360
        height: 360
        color: "lightgray"
        Rectangle {
            width: 100
            height: 100
            color: "blue"
            anchors.centerIn: parent
        }
    }
    
  6. Positioner 元素

    • QML 還提供了一些用於更高階佈局控制的 Positioner 元素,如 RepeaterView(如 ListViewGridView)等。這些元素通常用於動態建立和佈局多個子元素。

在構建 QML 應用程式時,選擇正確的佈局元素並根據需要進行調整是非常重要的。對於簡單的介面,可能只需要使用基本的佈局元素,而對於更復雜的介面,可能需要結合使用多種佈局元素,甚至自定義佈局行為。透過靈活使用 QML 的佈局功能,可以建立出響應式、使用者友好的介面。

qml模型檢視

QML(Qt Modeling Language)的模型檢視結構是構建圖形使用者介面(GUI)應用程式的一種有效方式。這種結構將資料模型與使用者介面檢視分離,使得資料的改變能夠自動反映在介面上,增強了應用程式的靈活性和可維護性。

在QML的模型檢視結構中,模型(Model)負責提供資料及其結構。這些資料可以是列表、表格、樹狀結構等,並且可以透過多種QML型別來建立。模型是資料的抽象表示,它並不關心資料如何顯示,只負責提供資料。

檢視(View)則是顯示資料的容器,它負責資料的視覺化表示。檢視可以是一個列表、表格、樹狀檢視等,用於將資料以特定的方式呈現出來。檢視與模型分離,使得開發者可以獨立地改變資料的表示方式,而不需要修改資料模型本身。

在QML的模型檢視結構中,還有一個重要的組成部分是代理(Delegate)。代理負責控制資料如何在檢視中進行顯示。每個資料元素的視覺化都分給一個代理,代理定義瞭如何繪製每個資料項。透過代理,開發者可以自定義資料的顯示方式,例如改變顏色、字型、圖示等。

這種模型檢視結構使得QML能夠高效地處理大量資料,並提供了靈活的資料展示方式。同時,透過將資料模型與使用者介面分離,使得程式碼更加清晰、易於維護。開發者可以專注於實現業務邏輯,而不需要過多關注介面的細節。

qml訊號和槽

QML中的訊號和槽是實現元件之間通訊的重要機制。透過訊號和槽的連線,一個元件可以向另一個元件傳送訊息,以響應使用者的操作或者通知其他元件進行相應的操作。

在QML中,訊號和槽的定義都採用signalslot關鍵字進行定義。其中,signal用於定義訊號,而slot用於定義槽。訊號是事件,當某個特定事件發生時,訊號就會被髮射。而槽是由訊號觸發的表示式或函式,用於響應這些訊號。

在QML中,當訊號被髮射時,相應的槽函式就會被自動呼叫。這使得開發者可以在槽函式中放置邏輯(例如指令碼或其他操作),以允許元件響應事件。例如,當某個按鈕被點選時,它可以發射一個訊號,該訊號連線到另一個元件的槽函式,導致該元件執行某種操作。

另外,QML也支援使用C++訊號與QML槽的連線。如果註冊的是C++類或其物件,那麼可以在QML中例項化物件時直接捕獲這些訊號,並在QML中定義相應的槽函式來響應這些訊號。這種連線通常是透過Connections物件實現的,它允許在QML中指定目標物件以及要連線的訊號和槽。

qml和c++

C++物件和QML物件通常分別由它們各自的環境進行管理。這種管理方式確保了各自的穩定性和獨立性,同時也提供了它們之間互動的橋樑。

C++物件的管理
C++物件通常由C++程式碼直接管理。這包括物件的建立、初始化、銷燬以及生命週期的控制。C++提供了強大的記憶體管理機制,如建構函式、解構函式、智慧指標等,以確保資源的正確分配和釋放,避免記憶體洩漏等問題。此外,C++物件還可以封裝資料和方法,提供對資料的封裝和抽象,提高程式碼的可維護性和可重用性。

QML物件的管理
QML物件則由QML引擎和QML型別系統負責管理。QML引擎負責解析QML檔案,建立QML物件樹,並處理QML物件之間的關係和事件。QML型別系統則定義了QML中可用的各種型別和屬性,提供了QML物件的基本結構和行為。QML物件通常透過QML檔案或QML程式碼進行宣告和配置,它們的建立、更新和銷燬都由QML引擎自動處理。

C++與QML的互動
儘管C++物件和QML物件分別由它們各自的環境管理,但它們之間可以透過Qt的元物件系統進行互動。這種互動使得C++物件可以暴露給QML,供QML使用,同時QML物件也可以發出訊號,由C++物件接收並處理。這種互動機制使得開發者能夠結合C++的強大功能和QML的直觀性,構建出功能豐富、易於維護的應用程式。

總的來說,C++物件和QML物件分別由它們各自的環境進行管理,但它們之間的互動使得它們能夠協同工作,實現複雜的應用程式功能。這種分工合作的方式使得開發者能夠充分利用各自的優勢,提高開發效率和應用程式的質量。

qml和ECMAScript

QML和ECMAScript在Qt框架中各自扮演著重要的角色,並且它們之間有著緊密的聯絡。

QML(Qt Modeling Language)是一種描述性的指令碼語言,主要用於描述Qt應用程式的使用者介面。其語法類似於CSS,但又支援類似JavaScript形式的程式設計控制,使得開發者能夠更直觀地定義使用者介面元件、佈局和互動邏輯。QML的一個顯著特點是它提供了為編寫QML應用程式而量身定製的JavaScript環境,這個環境實現了ECMAScript語言規範標準的第七版,即ES7。

ECMAScript是由Ecma國際(前身為歐洲計算機制造商協會)透過ECMA-262標準化的指令碼程式設計語言。它在全球資訊網上應用廣泛,通常被稱為JavaScript或JScript,是JavaScript的一個標準。ECMAScript具有語法簡潔、物件導向、事件驅動、跨平臺、標準統一和動態型別等特性,這使得它在開發互動式網頁和富客戶端應用程式時非常有用。

在QML中,ECMAScript的特性和功能得到了充分的利用。QML的語法是在ECMAScript語法的基礎上實現的,這使得QML能夠利用ECMAScript的豐富功能和靈活性。例如,QML中的訊號和槽機制就借鑑了ECMAScript的事件處理機制,使得元件間的通訊和互動變得更加容易。此外,QML還支援在指令碼中建立圖形物件,使用各種圖形特效和狀態機,這些都離不開ECMAScript的支援。