QML 模型

QML模型基礎架構

QML采用經典的Model-View-Delegate (MVD)?架構來分離數據與界面,這與MVC模式類似但更加適合聲明式UI開發。在這個架構中:

  • ?Model?:負責管理數據,可以是簡單的整數,也可以是復雜的C++自定義模型
  • ?View?:負責顯示數據,如ListView、GridView、TableView等
  • ?Delegate?:負責如何顯示單個數據項,相當于模板
// 基本結構示例
ListView {width: 200; height: 250model: myModel  // 數據模型delegate: Rectangle {  // 委托項Text { text: model.display }}
}

Qt的模型系統最大的特點是靈活性——幾乎任何數據類型都可以作為模型使用。模型在QML中不僅是數據容器,還通過角色(roles)?系統提供數據訪問接口,委托可以通過這些角色訪問模型中的數據項。

整數模型:最簡單的模型類型

整數模型是QML中最簡單的模型形式,它僅提供一個整數計數,用于生成重復的UI元素。

import QtQuick 2.15
import QtQuick.Controls 2.15Rectangle {width: 600; height: 400ListView {anchors.fill: parentmodel: 5  // 整數作為模型delegate: Rectangle {width: parent.widthheight: 30required property int indexText {text: "我是第"+index + "個元素"}}}
}

?使用場景?:

  • 創建固定數量的相似組件
  • 快速原型開發
  • 不需要復雜數據綁定的簡單界面

?特點?:

  • 每個委托項自動獲得index屬性(從0開始)
  • 沒有額外的數據角色,僅提供索引值
  • 性能高效,適合靜態簡單布局

?高級用法?:
可以與Repeater結合使用,創建網格布局:

Grid {columns: 3Repeater {model: 9  // 創建3x3網格Rectangle {width: 50; height: 50color: index%2 ? "red" : "blue"}}
}

整數模型雖然簡單,但在許多不需要復雜數據的場景下非常實用,能夠避免創建不必要的復雜模型,注意:整數模型中的項目數量不能超過100000000

列表模型ListModel:動態數據管理

ListModel是QML中最常用的模型之一,它允許在QML中直接定義結構化數據,并支持動態修改。

基本用法

import QtQuick 2.0ListModel {id: fruitModelListElement {name: "Apple"cost: 2.45}ListElement {name: "Orange"cost: 3.25}
}

在視圖中使用:

ListView {anchors.fill: parentmodel: fruitModeldelegate: Row {Text { text: "名稱:" + name }Text { text: "價格:" + cost }}
}

?ListElement特性?:

  • 必須以小寫字母開頭
  • 值只能是簡單類型:字符串、布爾值、數字或枚舉值
  • 支持嵌套ListElement,創建層次結構

動態操作

ListModel提供了一系列方法用于動態修改數據:

// 添加數據
fruitModel.append({"name": "Banana", "cost": 1.95})// 插入數據
fruitModel.insert(1, {"name": "Pear", "cost": 3.50})// 修改數據
fruitModel.set(0, {"name": "Pineapple", "cost": 2.75})// 移動數據
fruitModel.move(0, 2, 1)  // 將第0項移動到第2項// 刪除數據
fruitModel.remove(1)  // 刪除第1項// 清空模型
fruitModel.clear()

高級特性

?動態角色?:ListModel支持動態添加角色,只需設置dynamic屬性為true:

ListModel {id: dynamicModeldynamic: true// 可以后續添加新角色
}Component.onCompleted: {dynamicModel.append({"newRole": "value"})
}

?與WorkerScript配合?:對于大數據量操作,可以在后臺線程處理模型以避免界面卡頓:

WorkerScript {id: workersource: "script.mjs"
}Timer {id: timerinterval: 2000; repeat: truerunning: trueonTriggered: {var msg = {'action': 'appendCurrentTime', 'model': listModel};worker.sendMessage(msg);}
}

ListModel非常適合中等規模的數據集,它提供了QML中直接操作數據的便利性,但對于大規模數據復雜數據結構,建議使用C++實現的模型。

對象模型ObjectModel:封裝可視化項

ObjectModel是一種特殊模型,它直接包含可視化項而不是數據,因此不需要委托(delegate)。

基本用法

import QtQuick 2.12
import QtQml.Models 2.12ObjectModel {id: itemModelRectangle { height: 30; width: 80; color: "red" }Rectangle { height: 30; width: 80; color: "green" }Rectangle { height: 30; width: 80; color: "blue" }
}ListView {anchors.fill: parentmodel: itemModel
}

?特點?:

  • 模型項本身就是可視化組件
  • 不需要定義delegate
  • 適合固定數量有限的可視化項集合
  • 性能優于Repeater生成的相同數量項

動態操作

ObjectModel也支持動態修改內容:

// 添加項
itemModel.append(rectComponent.createObject())// 插入項
itemModel.insert(1, textComponent.createObject())// 移動項
itemModel.move(0, itemModel.count-1, 1)// 刪除項
itemModel.remove(0)// 獲取項
var item = itemModel.get(2)

與C++集成

ObjectModel也可以從C++端創建和管理:

class ObjectModel : public QObject {Q_OBJECT
public:Q_INVOKABLE QVariant _objmodel() {return QVariant::fromValue(objmodellist);}// 其他操作接口...
private:QList<QObject*> objmodellist;
};

在QML中使用:

ListView {delegate: Text { text: model.modelData.data }model: Global._objmodel()
}

ObjectModel非常適合混合布局場景,其中某些項需要特殊定制而不是統一的數據驅動委托。

表格模型TableModel:處理二維數據

TableModel用于處理表格數據,相比ListModel,它增加了列的概念,適合展示類似數據庫表格的結構化數據。

QML實現

import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQml.Models 2.15TableView {anchors.fill: parentcolumnSpacing: 1rowSpacing: 1model: TableModel {TableModelColumn { display: "name" }TableModelColumn { display: "age" }rows: [{"name": "Alice","age": 22},{"name": "Bob","age": 25}]}delegate: Rectangle {Text { text: display }}
}

C++實現

對于更復雜的表格,通常需要在C++中實現:

class DataModel : public QAbstractTableModel {Q_OBJECT
public:int rowCount(const QModelIndex&) const override {return m_data.size();}int columnCount(const QModelIndex&) const override {return m_roleList.size();}QVariant data(const QModelIndex &index, int role) const override {return m_data[index.row()].at(index.column());}QHash<int, QByteArray> roleNames() const override {QHash<int, QByteArray> roles;for(int i=0; i<m_roleList.size(); i++) {roles[Qt::UserRole+i+1] = m_roleList.at(i).toLocal8Bit();}return roles;}
private:QList<QVariantList> m_data;QStringList m_roleList;
};

注冊到QML:

qmlRegisterType<DataModel>("CustomModels", 1, 0, "DataModel");

高級特性

?動態列管理?:可以通過動態添加TableModelColumn來創建靈活的表結構

?行選擇?:配合SelectionModel實現行選擇功能

?排序?:通過實現sort函數添加排序能力

?性能優化?:對于大型表格,需要實現fetchMore/canFetchMore進行分批加載

TableModel特別適合展示業務數據,如數據庫查詢結果、電子表格等結構化信息。

XML列表模型XmlListModel:處理XML數據 使用較少

XmlListModel專門用于解析和展示XML格式的數據,常見于RSS閱讀器或Web API交互場景。

基本用法

import QtQuick 2.0
import QtQuick.XmlListModel 2.0XmlListModel {id: xmlModelsource: "http://www.example.com/feed.xml"query: "/rss/channel/item"XmlRole { name: "title"; query: "title/string()" }XmlRole { name: "pubDate"; query: "pubDate/string()" }
}ListView {width: 180; height: 300model: xmlModeldelegate: Text { text: title + ": " + pubDate }
}

?關鍵屬性?:

  • source:XML數據源,可以是本地文件或網絡URL
  • query:XPath表達式,指定要處理的節點集
  • XmlRole:定義如何從XML節點提取數據
  • namespaceDeclarations:處理含命名空間的XML

動態查詢

XmlListModel支持動態修改查詢條件:

// 只獲取特定條件的項目
xmlModel.query = "/rss/channel/item[contains(title, 'Qt')]"// 重新加載模型
xmlModel.reload()

錯誤處理

通過status屬性處理加載狀態:

Text {text: {switch(xmlModel.status) {case XmlListModel.Loading: return "加載中...";case XmlListModel.Ready: return "就緒";case XmlListModel.Error: return "錯誤: "+xmlModel.errorString();}}
}

性能考慮

  • 大型XML文件考慮在后臺線程解析
  • 使用progress屬性顯示加載進度
  • 合理設置XPath查詢,避免復雜查詢影響性能

XmlListModel極大簡化了XML數據處理流程,是構建RSS閱讀器或與Web服務交互的理想選擇。

Package機制:多視圖共享委托--使用較少

Package(包)機制允許多個視圖共享同一組委托實例,實現復雜的視圖交互效果。

基本概念

Package與DelegateModel配合使用,可以:

  • 在不同視圖中復用同一委托
  • 實現項目在不同視圖間動畫過渡
  • 構建主從視圖(Master-Detail)布局

實現示例

import QtQuick 2.12
import QtQml.Models 2.12
import Qt.labs.qmlmodels 1.0DelegateModel {id: visualModelmodel: ListModel {ListElement { name: "Item 1"; color: "red" }ListElement { name: "Item 2"; color: "green" }}delegate: Package {Item { Package.name: "list" }Item { Package.name: "grid" }Rectangle {width: parent.width; height: 50color: model.colorText { text: model.name }parent: viewSwitcher.checked ? grid : list}}
}ListView {width: 200; height: 300model: visualModel.parts.list
}GridView {x: 210; width: 300; height: 300model: visualModel.parts.grid
}

Package機制為構建復雜視圖交互提供了強大支持,是QML模型系統中較高級但極具價值的功能。

模型性能優化與實踐建議

在實際項目中使用QML模型時,?性能可維護性是需要重點考慮的因素。

性能優化技巧

  1. ?虛擬化?:ListView/GridView等視圖默認只創建可見項委托,確保clip屬性為true

  2. ?輕量委托?:保持委托盡可能簡單,復雜委托會顯著影響滾動性能

  3. ?批處理操作?:對于大規模數據修改,先調用beginResetModel(),修改完成后調用endResetModel()

  4. ?C++模型?:數據量超過1000項時考慮使用C++實現的模型

  5. ?緩存策略?:對于網絡數據或計算成本高的模型,實現緩存機制

模型選擇指南

模型類型適用場景優點缺點
整數模型簡單重復項極簡、高效無數據綁定
ListModel中小型動態數據QML內定義、易用大數據性能差
ObjectModel固定可視化項無需委托、靈活不適合數據驅動
TableModel表格數據行列結構、功能豐富復雜度高
XmlListModelXML數據內置解析、XPath支持僅只讀
C++模型大型專業應用高性能、功能全面需要C++知識

常見問題解決

?數據不同步?:確保模型變更時發出正確的信號(如dataChanged)

?內存泄漏?:ObjectModel中注意管理QObject生命周期

?跨線程訪問?:使用WorkerScript處理耗時操作

?復雜過濾?:考慮使用SortFilterProxyModel等中間模型

最佳實踐

  1. ?角色命名?:使用有意義的角色名而非簡單role1、role2

  2. ?模塊化?:將復雜模型分離到單獨QML文件或C++類中

  3. ?測試?:大數據量下測試滾動性能和內存占用

  4. ?文檔?:為自定義模型編寫使用說明,特別是角色定義

  5. ?漸進增強?:簡單需求先用ListModel,復雜時再遷移到C++模型

結語

QML的模型系統提供了從簡單到復雜、從純QML到C++集成的全方位解決方案。掌握這些模型類型的特點和使用場景,能夠幫助開發者構建數據驅動的高性能用戶界面。無論是簡單的整數模型還是復雜的C++集成模型,Qt都提供了相應的工具和模式,關鍵在于根據項目需求選擇合適的工具

隨著Qt的持續發展,QML的模型系統也在不斷進化,如最新的Qt 6中引入的DelegateChooser等新特性,進一步增強了模型的靈活性。建議開發者定期查閱Qt官方文檔,了解最新的最佳實踐和功能增強。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/90404.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/90404.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/90404.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

基于Trae IDE與MCP實現網頁自動化測試的最佳實踐

引言 在現代Web開發流程中&#xff0c;自動化測試已成為保障應用質量、提升開發效率的關鍵環節。Playwright作為一款新興的測試框架&#xff0c;因其出色的跨瀏覽器支持能力和豐富的API特性&#xff0c;正逐漸成為自動化測試領域的主流選擇。本文將詳細介紹如何在葡萄城Trae ID…

Android 動畫優化

動畫是提升 Android 應用用戶體驗的核心手段 —— 流暢的過渡動畫能讓頁面切換更自然&#xff0c;交互反饋動畫能讓操作更有質感。但動畫也是性能 “重災區”&#xff1a;掉幀、卡頓、內存暴漲等問題&#xff0c;往往源于對動畫原理和優化技巧的忽視。本文將從動畫性能的核心瓶…

Linux——進程間通信,匿名管道,進程池

文章目錄一、進程間通信&#xff08;IPC&#xff09;的理解1.為什么進程間要通信&#xff08;IPC&#xff09;2.如何進行通信二、匿名管道1.管道的理解2.匿名管道的使用3.管道的五種特性4.管道的四種通信情況5.管道緩沖區容量三、進程池1.進程池的理解2.進程池的制作四、源碼Pr…

深度分析Java內存回收機制

內存回收機制是Java區別于C/C等語言的核心特性之一&#xff0c;也是Java開發者理解程序性能、解決內存相關問題&#xff08;如內存泄漏、OOM&#xff09;的關鍵。 核心目標&#xff1a; 自動回收程序中不再使用的對象所占用的內存&#xff0c;防止內存耗盡&#xff0c;同時盡量…

uniapp “requestPayment:fail [payment支付寶:62009]未知錯誤“

解決方案&#xff1a;兄弟&#xff0c;有一種可能是你用測試機沒有安裝支付寶

分布在內側內嗅皮層(MEC)的帶狀細胞對NLP中的深層語義分析的積極影響和啟示

帶狀細胞&#xff08;Band Cells&#xff09;作為內側內嗅皮層&#xff08;Medial Entorhinal Cortex, MEC&#xff09;層Ⅱ/Ⅲ的核心空間編碼單元&#xff08;如網格細胞、頭方向細胞等&#xff09;&#xff0c;其獨特的神經計算機制為自然語言處理&#xff08;NLP&#xff09…

綜合實驗(4)

文章目錄 目錄 文章目錄 前言 實驗配置 實驗總結 總結 前言 Cisco IOS Site-to-Site VPN&#xff08;虛擬專用網絡&#xff09;是一種通過公共網絡&#xff08;如互聯網&#xff09;建立安全連接的技術&#xff0c;使不同地理位置的局域網&#xff08;LAN&#xff09;能夠安…

JavaSE:開發環境的搭建(Eclipse)

一、IDE概述與核心價值 集成開發環境定義 提供編譯器、調試器、項目管理工具的統一平臺&#xff0c;顯著提升開發效率。 Eclipse核心優勢&#xff1a; 免費開源 &#xff1a;社區驅動&#xff0c;無授權費用跨平臺支持 &#xff1a;Windows/Linux/macOS全兼容多語言擴展 &a…

使用LLaMA-Factory對大模型進行微調

之前了解過一些LLM從訓練到落地的過程; 其中一個重要的步驟就是微調; 預訓練&#xff1a;在大規模數據上學習通用語言知識。(使用海量無標注文本&#xff08;TB級&#xff09;) 微調&#xff1a;在預訓練基礎上&#xff0c;使用特定任務的標注數據進一步優化模型。(使用少量任務…

WxPython——一些最常見的錯誤現象及解決方法

一些最常見的錯誤現象及解決方法 有一些錯誤它們可能會發生在你的wxPython應用程序對象或初始的頂級窗口在創建時&#xff0c;這些錯誤可能是很難診斷的。下面我們列出一些最常見的錯誤現象及解決方法&#xff1a; 錯誤現象&#xff1a;程序啟動時提示“unable to import modul…

SparkSQL 子查詢 IN/NOT IN 對 NULL 值的處理

SparkSQL 子查詢 IN/NOT IN 對 NULL 值的處理 官網&#xff1a;https://spark.apache.org/docs/4.0.0/sql-ref-functions.html https://spark.apache.org/docs/4.0.0/sql-ref-null-semantics.html#innot-in-subquery Unlike the EXISTS expression, IN expression can return…

【安卓筆記】lifecycle與viewModel

0. 環境&#xff1a; 電腦&#xff1a;Windows10 Android Studio: 2024.3.2 編程語言: Java Gradle version&#xff1a;8.11.1 Compile Sdk Version&#xff1a;35 Java 版本&#xff1a;Java11 1. 本篇文章涉及到的內容 lifecycle livedata databinding viewModel 2. …

84、逆向工程開發方法

逆向工程開發方法是一種通過分析現有產品、系統或代碼來理解其設計原理、功能實現及潛在缺陷&#xff0c;并在此基礎上進行改進、復制或創新的技術過程。它廣泛應用于軟件、硬件、機械、電子等多個領域&#xff0c;尤其在缺乏原始設計文檔或需要快速掌握復雜系統時具有顯著優勢…

ospf單區域實驗

拓撲圖&#xff1a;AR1&#xff1a;[Huawei]ospf 1 router-id 1.1.1.1 [Huawei-ospf-1]area 0[Huawei-ospf-1-area-0.0.0.0]network 192.168.1.0 0.0.0.255&#xff08;1.當前網段會被ospf的進程1學習到然后通告出去&#xff1b;2.如果接口的IP地址處于這個網段中&#xff0c…

Linux命令基礎完結篇

用戶權限修改 chmod修改文件權限 文字設定法 u&#xff1a;所有者g&#xff1a;所屬組o&#xff1a;其他人a&#xff1a;所有&#xff1a;添加權限-&#xff1a;刪除權限&#xff1a;賦予權限數字設定法 r&#xff1a;4w&#xff1a;2x&#xff1a;1每一組權限&#xff1a;0~7舉…

高效互聯,ModbusTCP轉EtherCAT網關賦能新能源電纜智能制造

在新能源汽車快速發展的背景下&#xff0c;新能源電纜作為關鍵組件&#xff0c;需滿足耐高低溫、阻燃、耐老化等嚴苛要求&#xff0c;這對生產線的工藝與設備提出了更高標準。為提升制造效率&#xff0c;某領先設備制造商創新采用**ModbusTCP轉EtherCAT網關**技術&#xff0c;實…

Java_多線程_生產者消費者模型_互斥鎖,阻塞隊列

生產者消費者模型(Producer-Consumer Model)是計算機科學中一個經典的并發編程模型&#xff0c;用于解決多線程/多進程環境下的協作問題。 基本概念 生產者&#xff1a;負責生成數據或任務的實體 消費者&#xff1a;負責處理數據或執行任務的實體 緩沖區&#xff1a;生產者與消…

Vue3實現視頻播放彈窗組件,支持全屏播放,音量控制,進度條自定義樣式,適配瀏覽器小窗播放,視頻大小自適配,緩沖loading,代碼復制即用

效果圖組件所需VUE3代碼<template><div class"video-dialog" :class"fullScreen && video-dialog-full-screen"><el-dialogv-model"props.visible"draggable:show-close"false"title""centeralign-c…

LLM層歸一化:γβ與均值方差的協同奧秘

LLM層歸一化參數均值和方差;縮放和平移參數是什么 層歸一化(Layer Normalization,LN)是深度學習中用于穩定神經網絡訓練的一種歸一化技術 均值和方差參數用于對輸入數據進行標準化處理,即將輸入數據轉換為均值為0、方差為1的標準正態分布 縮放因子γ\gammaγ:標準化后…

智慧場景:定制開發開源AI智能名片S2B2C商城小程序賦能零售新體驗

摘要&#xff1a;智慧場景作為零售行業創新發展的關鍵載體&#xff0c;正深刻改變著消費者的生活方式。本文聚焦智慧零售模式下智慧場景的構建&#xff0c;以定制開發開源AI智能名片S2B2C商城小程序為切入點&#xff0c;深入探討其在零售企業選址布局、商業模式創新、經營理念轉…