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

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

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

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

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

