QML与JavaScript交互的四种方式(内联调用、外部文件、信号处理与工作线程)

 更新时间:2026年03月26日 10:13:38   作者:Quz  
JavaScript作为一种强大的编程语言,用于实现业务逻辑和与用户交互,下面这篇文章主要介绍了QML与JavaScript交互的四种方式,分别是内联调用、外部文件、信号处理与工作线程,需要的朋友可以参考下

引言

在Qt6中,QML引擎深度集成了JavaScript。本文将用四个示例,展示QML与Javascript的四种交互方式:内联调用、外部文件、信号处理、工作线程(WorkerScript)。

交互方式说明

方式一:内联调用

演示效果

适用场景:逻辑简单,仅在当前组件内部使用的短代码。

在 QML 根元素内直接定义 function,就像在 HTML 中写 JS 一样。

关键代码 (来自 JSInlineFunc.qml ):

Rectangle {
    // 1. 定义一个内联 JS 函数
    function calculateArea(w, h) {
        return w * h
    }
    Text {
        // 2. 属性绑定中直接调用:当 width 或 height 变化时自动重算
        text: "计算面积: " + calculateArea(this.width, this.height) 
    }
    Button {
        // 3. 在信号处理器(如 onClicked)中调用
        onClicked: {
            var result = calculateArea(100, 100)
            textResult.text = "Area: " + result
        }
    }
}

关键点

  • 作用域:这些函数可以访问该 QML 文件内的所有 id 和属性。
  • 绑定特性:在属性绑定(如 text: ...)中使用时,若参数发生变化,函数会自动重新执行 。

方式二:外部文件

演示效果

适用场景:通用的工具函数(如日期格式化、字符串处理),需要在多个 QML 文件中共享。

关键代码
首先在 Utility.js 中定义函数,并使用 .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 {
    // 使用 别名.函数名 进行调用
    text: "日期: " + Util.formatDate(new Date()) 
}

关键点

  • 必须使用 as 关键字定义别名(如Util),避免命名冲突。同时注意Util首字母要大写
  • 加上 .pragma library 后,该 JS 文件在整个应用程序中只有一份实例(单例),适合存放无状态的工具函数。如果不加这行,每个导入它的 QML 组件都会生成一个新的 JS 上下文副本。

方式三:信号处理

演示效果

适用场景:将复杂的逻辑封装在 JS 函数中,通过 QML 的信号(Signal)来触发,保持代码整洁。

关键代码 (来自 JSSignal.qml ):

Text {
    id: myText
    property int counter: 0
    // 1. 定义处理逻辑
    function handleButtonClick() {
        myText.counter++
    }
    Connections {
        target: myButton // 目标按钮
        // 2. 将按钮的 onClicked 信号连接到 JS 函数
        function onClicked() { myText.handleButtonClick() } 
    }
}

关键点

  • 这体现了 Qt 的 信号与槽 (Signal & Slot) 机制。JS 函数在 QML 中可以直接作为槽函数使用。
  • 这种方式解耦了 UI 元素(Button)和业务逻辑(Text 的计数逻辑)。

方式四:工作线程 (WorkerScript)

演示效果

适用场景:耗时操作(如图像处理、大规模计算)。如果在主线程做这些,界面会“卡死”。

原理:使用 WorkerScript 将 JS 代码放到后台线程运行。注意:后台线程不能访问 QML 的 UI 元素(DOM),只能通过消息传递(Message Passing)交互。

关键代码 (来自 WorkerScriptDemo.qmlscript.mjs):

Step 1: QML 端 (发送与接收)

// 工作线程脚本
WorkerScript {
    id: myWorker
    source: "script.mjs"
    // 接收工作线程返回的消息
    onMessage: function (msgObj) {
        isProcessing = false;
        if (msgObj.error) {
            resultText = "错误: " + msgObj.error;
        } else {
            resultText = "计算结果: " + msgObj.result +
                    "\n耗时: " + msgObj.time + " ms" +
                    "\n任务ID: " + msgObj.taskId +
                    "\n原始消息: " + JSON.stringify(msgObj.originalMessage)
        }
    }
}
//发送按钮
Button {
    id: btnCalc
    text: "计算斐波那契数列"
    font.pointSize: 12
    enabled: !isProcessing && myWorker.ready
    onClicked: {
        isProcessing = true;
        resultText = "计算斐波那契数列 ...";
        myWorker.sendMessage({ 'taskId': 1001, 'n': textField.text, 'timestamp': Date.now() });
    }
}

Step 2: JS 端 (处理与回传)

// script.mjs
// 计算斐波那契数列(递归,耗时操作)
function fibonacci(n) {
    function fib(n) {
        if (n <= 1) return n;
        return fib(n - 1) + fib(n - 2);
    }
    return fib(n);
}
// 监听主线程发送的消息
WorkerScript.onMessage = function(message) {   
    try {
        var startTime = Date.now();
        var result;
        // 计算斐波那契数列
        result = fibonacci(message.n || 30);        
        var endTime = Date.now();
        var processingTime = endTime - startTime;
        // 将结果发送回主线程
        WorkerScript.sendMessage({
            result: result,
            time: processingTime,
            taskId: message.taskId,
            originalMessage: message
        });
    } catch (error) {
        // 错误处理
        WorkerScript.sendMessage({
            error: error.toString(),
            originalMessage: message
        });
    }
}

关键点

  • 异步特性:调用 sendMessage 后,主线程立即继续执行,不会等待。
  • 数据隔离:Worker 内部无法访问 id: mainWindow 等 UI 对象,必须通过 message 对象传递所需的所有数据。

总结

方式关键字适用场景备注
内联调用function简单的 UI 逻辑访问方便,但不易复用
外部文件import … as工具类库、常量定义推荐使用 .pragma library
信号连接Connections响应事件实现 UI 与逻辑解耦
工作线程WorkerScript耗时计算、网络请求唯一不阻塞 UI 的方式

初学时从内联函数开始,随着代码量增加,逐渐将逻辑抽离到外部 JS 文件中。

到此这篇关于QML与JavaScript交互四种方式的文章就介绍到这了,更多相关QML与JS交互方式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • javascript基础知识讲解

    javascript基础知识讲解

    本篇适合javascript新手或者学了前端一段时间,对js概念不清晰的同学。本文将讲述几点对于初学者遇到的javascript的坑,相信对javascript基础薄弱的同学,可以加深对javascript的理解
    2017-01-01
  • js prototype截取字符串函数

    js prototype截取字符串函数

    prototype它是用Javascript写好的一些API,包括对Javascript中的类如String,Array等进行的扩充,把JS文件嵌入后直接用就行了
    2010-04-04
  • js constructor的实际作用分析

    js constructor的实际作用分析

    大家讨论下constructor的作用哈,需要的朋友可以参考下。从51js摘编而来。
    2011-11-11
  • JavaScript判断输入是否为数字类型的方法总结

    JavaScript判断输入是否为数字类型的方法总结

    这篇文章主要介绍了JavaScript判断输入是否为数字类型的方法总结的相关资料,希望通过本文能帮助到大家,需要的朋友可以参考下
    2017-09-09
  • 学习JavaScript一定要知道的3个小技巧

    学习JavaScript一定要知道的3个小技巧

    这篇文章主要给大家分享的是学习JavaScript一定要知道的3个小技巧,通常在 Angular 或 React 项目中,code review 时看到一些老式的 JavaScript 代码,就会将开发人员归类为初学者,下面我们就来一起看看初学者需要知道的三个小技巧,需要的朋友可以参考一下
    2021-12-12
  • 详解JavaScript实现监听路由变化

    详解JavaScript实现监听路由变化

    前端实现路由变化主要有两种方式,本文主要介绍了这两种方法的实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • 细说webpack源码之compile流程-rules参数处理技巧(2)

    细说webpack源码之compile流程-rules参数处理技巧(2)

    这篇文章主要介绍了webpack源码之compile流程-rules参数处理技巧的相关知识,需要的朋友参考下吧
    2017-12-12
  • JavaScript trim 实现去除字符串首尾指定字符的简单方法

    JavaScript trim 实现去除字符串首尾指定字符的简单方法

    下面小编就为大家带来一篇JavaScript trim 实现去除字符串首尾指定字符的简单方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-12-12
  • JS模拟Dialog弹出浮动框效果代码

    JS模拟Dialog弹出浮动框效果代码

    这篇文章主要介绍了JS模拟Dialog弹出浮动框效果代码,涉及JavaScript可拖动窗口的创建及布局相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-10-10
  • JavaScript生成的动态下雨背景效果实现方法

    JavaScript生成的动态下雨背景效果实现方法

    这篇文章主要介绍了JavaScript生成的动态下雨背景效果实现方法,通过自定义函数实现动态背景效果,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-02-02

最新评论