QML與JavaScript交互的四種方式(內(nèi)聯(lián)調(diào)用、外部文件、信號處理與工作線程)
引言
在Qt6中,QML引擎深度集成了JavaScript。本文將用四個示例,展示QML與Javascript的四種交互方式:內(nèi)聯(lián)調(diào)用、外部文件、信號處理、工作線程(WorkerScript)。
交互方式說明
方式一:內(nèi)聯(lián)調(diào)用
演示效果:

適用場景:邏輯簡單,僅在當前組件內(nèi)部使用的短代碼。
在 QML 根元素內(nèi)直接定義 function,就像在 HTML 中寫 JS 一樣。
關(guān)鍵代碼 (來自 JSInlineFunc.qml ):
Rectangle {
// 1. 定義一個內(nèi)聯(lián) JS 函數(shù)
function calculateArea(w, h) {
return w * h
}
Text {
// 2. 屬性綁定中直接調(diào)用:當 width 或 height 變化時自動重算
text: "計算面積: " + calculateArea(this.width, this.height)
}
Button {
// 3. 在信號處理器(如 onClicked)中調(diào)用
onClicked: {
var result = calculateArea(100, 100)
textResult.text = "Area: " + result
}
}
}關(guān)鍵點:
- 作用域:這些函數(shù)可以訪問該 QML 文件內(nèi)的所有
id和屬性。 - 綁定特性:在屬性綁定(如
text: ...)中使用時,若參數(shù)發(fā)生變化,函數(shù)會自動重新執(zhí)行 。
方式二:外部文件
演示效果:

適用場景:通用的工具函數(shù)(如日期格式化、字符串處理),需要在多個 QML 文件中共享。
關(guān)鍵代碼:
首先在 Utility.js 中定義函數(shù),并使用 .pragma library 聲明這是一個共享庫 。
// Utility.js
.pragma library
function formatDate(date) {
return date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate()
}然后在 JSImportFile.qml 中導入并使用 :
import "Utility.js" as Util // 定義別名為 Util
Text {
// 使用 別名.函數(shù)名 進行調(diào)用
text: "日期: " + Util.formatDate(new Date())
}關(guān)鍵點:
- 必須使用
as關(guān)鍵字定義別名(如Util),避免命名沖突。同時注意Util首字母要大寫。 - 加上
.pragma library后,該 JS 文件在整個應(yīng)用程序中只有一份實例(單例),適合存放無狀態(tài)的工具函數(shù)。如果不加這行,每個導入它的 QML 組件都會生成一個新的 JS 上下文副本。
方式三:信號處理
演示效果:

適用場景:將復雜的邏輯封裝在 JS 函數(shù)中,通過 QML 的信號(Signal)來觸發(fā),保持代碼整潔。
關(guān)鍵代碼 (來自 JSSignal.qml ):
Text {
id: myText
property int counter: 0
// 1. 定義處理邏輯
function handleButtonClick() {
myText.counter++
}
Connections {
target: myButton // 目標按鈕
// 2. 將按鈕的 onClicked 信號連接到 JS 函數(shù)
function onClicked() { myText.handleButtonClick() }
}
}關(guān)鍵點:
- 這體現(xiàn)了 Qt 的 信號與槽 (Signal & Slot) 機制。JS 函數(shù)在 QML 中可以直接作為槽函數(shù)使用。
- 這種方式解耦了 UI 元素(Button)和業(yè)務(wù)邏輯(Text 的計數(shù)邏輯)。
方式四:工作線程 (WorkerScript)
演示效果:

適用場景:耗時操作(如圖像處理、大規(guī)模計算)。如果在主線程做這些,界面會“卡死”。
原理:使用 WorkerScript 將 JS 代碼放到后臺線程運行。注意:后臺線程不能訪問 QML 的 UI 元素(DOM),只能通過消息傳遞(Message Passing)交互。
關(guān)鍵代碼 (來自 WorkerScriptDemo.qml 和 script.mjs):
Step 1: QML 端 (發(fā)送與接收)
// 工作線程腳本
WorkerScript {
id: myWorker
source: "script.mjs"
// 接收工作線程返回的消息
onMessage: function (msgObj) {
isProcessing = false;
if (msgObj.error) {
resultText = "錯誤: " + msgObj.error;
} else {
resultText = "計算結(jié)果: " + msgObj.result +
"\n耗時: " + msgObj.time + " ms" +
"\n任務(wù)ID: " + msgObj.taskId +
"\n原始消息: " + JSON.stringify(msgObj.originalMessage)
}
}
}
//發(fā)送按鈕
Button {
id: btnCalc
text: "計算斐波那契數(shù)列"
font.pointSize: 12
enabled: !isProcessing && myWorker.ready
onClicked: {
isProcessing = true;
resultText = "計算斐波那契數(shù)列 ...";
myWorker.sendMessage({ 'taskId': 1001, 'n': textField.text, 'timestamp': Date.now() });
}
}Step 2: JS 端 (處理與回傳)
// script.mjs
// 計算斐波那契數(shù)列(遞歸,耗時操作)
function fibonacci(n) {
function fib(n) {
if (n <= 1) return n;
return fib(n - 1) + fib(n - 2);
}
return fib(n);
}
// 監(jiān)聽主線程發(fā)送的消息
WorkerScript.onMessage = function(message) {
try {
var startTime = Date.now();
var result;
// 計算斐波那契數(shù)列
result = fibonacci(message.n || 30);
var endTime = Date.now();
var processingTime = endTime - startTime;
// 將結(jié)果發(fā)送回主線程
WorkerScript.sendMessage({
result: result,
time: processingTime,
taskId: message.taskId,
originalMessage: message
});
} catch (error) {
// 錯誤處理
WorkerScript.sendMessage({
error: error.toString(),
originalMessage: message
});
}
}關(guān)鍵點:
- 異步特性:調(diào)用
sendMessage后,主線程立即繼續(xù)執(zhí)行,不會等待。 - 數(shù)據(jù)隔離:Worker 內(nèi)部無法訪問
id: mainWindow等 UI 對象,必須通過message對象傳遞所需的所有數(shù)據(jù)。
總結(jié)
| 方式 | 關(guān)鍵字 | 適用場景 | 備注 |
|---|---|---|---|
| 內(nèi)聯(lián)調(diào)用 | function | 簡單的 UI 邏輯 | 訪問方便,但不易復用 |
| 外部文件 | import … as | 工具類庫、常量定義 | 推薦使用 .pragma library |
| 信號連接 | Connections | 響應(yīng)事件 | 實現(xiàn) UI 與邏輯解耦 |
| 工作線程 | WorkerScript | 耗時計算、網(wǎng)絡(luò)請求 | 唯一不阻塞 UI 的方式 |
初學時從內(nèi)聯(lián)函數(shù)開始,隨著代碼量增加,逐漸將邏輯抽離到外部 JS 文件中。
到此這篇關(guān)于QML與JavaScript交互四種方式的文章就介紹到這了,更多相關(guān)QML與JS交互方式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript實現(xiàn)網(wǎng)頁電子時鐘
這篇文章主要為大家詳細介紹了JavaScript實現(xiàn)網(wǎng)頁電子時鐘,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-06-06
javascript模擬php函數(shù)in_array
就是判斷一個元素是否存在于數(shù)組中的函數(shù),既然js里string都有indexOf函數(shù),為什么不在Array對象里設(shè)置一個這樣的函數(shù)呢,其實就用indexOf這個思想挺好的,不知道制定JS標準的人是基于什么考慮,把這樣一個如此常用的功能沒考慮在內(nèi)的。2015-04-04
ECharts餅圖顏色設(shè)置的4種方式總結(jié)
這篇文章主要給大家介紹了關(guān)于ECharts餅圖顏色設(shè)置的4種方式,ECharts餅圖的顏色可以通過多種方式進行設(shè)置,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2023-09-09
詳解JavaScript如何實現(xiàn)并發(fā)控制的Promise隊列調(diào)度器
Promise是JavaScript中一種處理異步操作的技術(shù),提供了一種更優(yōu)雅的方式來處理并發(fā)任務(wù)和串行化操作,本文主要介紹了實現(xiàn)并發(fā)控制的Promise隊列調(diào)度器的方法,需要的可以參考一下2023-07-07
JavaScript?數(shù)據(jù)類型Map的用法詳解
本文通過實例代碼給大家介紹JavaScript數(shù)據(jù)類型Map的用法,本文結(jié)合實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧2025-10-10

