QML 对本地文件的读写

QML 里似乎没有提供直接访问本地文件的模块,但是我们能够自己扩展 QML,给它加上访问本地文件的能力。

Qt 官方文档对 QML 是这样介绍的:

It defines and implements the language and engine infrastructure, and provides an API to enable application developers to extend the QML language with custom types and integrate QML code with JavaScript and C++.

自定义模块

我们可以通过自定义 C++ 类,实现文件的读写并整合进 QML 中,使其作为一个文件读写的独立模块。

C++ 里这个类叫做 FileContent

头文件 FileContent.h:

#ifndef FILECONTENT_H
#define FILECONTENT_H #include <QObject>
#include <QFile>
#include <QTextStream> class FileContent : public QObject
{ Q_OBJECT
public: Q_PROPERTY(QString content READ getContent) Q_PROPERTY(QString filename READ getFileName WRITE setFileName) Q_INVOKABLE QString getContent(); Q_INVOKABLE QString getFileName(); FileContent(QObject *parent = 0); ~FileContent();
private: QFile   *file; QString content; QString filename;
public slots: void setFileName(const QString& filename); void clearContent();
}; #endif // FILECONTENT_H 

FileContent 的实现:

#include "filecontent.h"
#include <QDebug> FileContent::FileContent(QObject *parent) { } FileContent::~FileContent() { delete file;
} QString FileContent::getFileName() { return this->filename;
} void FileContent::setFileName(const QString &filename) { this->filename = filename; file = new QFile(filename); } QString FileContent::getContent() { if( content.length() == 0 ) { file->open(QIODevice::ReadOnly | QIODevice::Text); QTextStream in(file); content = in.readAll(); if( content.length() == 0) { qDebug() << "[Warning] FileContent: file " << this->filename << "is empty" << endl; } } return content;
} void FileContent::clearContent() { content.clear();
} 

FileContent 需要继承 QObject 类,并且在类内使用 Qt 的一系列宏。
这里用到了 Q_PROPERTY 宏,声明该类的一个属性,并给出 set 和 get 对应的方法名。还有 Q_INVOKABLE 宏,以便在 QML 中可以调用 FileContent 类的方法。

这里的 FileContent 类有两个属性,一个是文件名 filename,另一个是文件的内容 content。这两个属性可以直接在 QML 中作为 Item 的属性进行赋值。

我们把 FileContent 在 QML 中的名字叫做 FileContentItem,但现在还不能直接在 QML 文件中引用 FileContentItem,我们还需要通过 QmlEngine 提供的 qmlRegisterType 方法,向 Qml 系统注册我们写的这个类。

在 main 函数里面添加:

qmlRegisterType<FileContent>("test.filecontent", 1, 0, "FileContentItem");

然后在 QML 文件里面引用我们定义的 FileContent,然后就可以像使用普通的 Item 一样使用 FileContentItem 了。

import test.filecontent 1.0 FileContentItem { id: content filename: ":/obj/craft.obj"   // default is craft.obj property bool ready: false Component.onCompleted: { ready = true; GLcode.readFile = processContent; } function processContent(process, source) { while( !ready ) { ; } if( source !== undefined ) { filename = source; } console.time('Read file: "' + source + '"'); process(getContent()); console.timeEnd('Read file: "' + source + '"'); clearContent();  // save memory }
} 

这里 FileContentItem 里的 filename 和 content 属性其实分别对应的 C++ 里面用 Q_PROPERTY 定义的属性。这里并没有考虑要读取的文件内容大小,而是直接用 getContent() 方法直接返回文件的所有内容,如果文件过大,也可以考虑流式读取文件内容。

JavaScript 异步读取文件

如果需要在 QML 里面读取资源文件而不需要将数据写入到文件中,那么其实可以使用 JavaScript 的 XMLHttpRequest 方法来读取文件。当然这个方法与浏览器里面的使用有一点点区别。

这是我从 Qt 自带的 Planets Example 中扎到的实现:

/**
* this function is copied from planets demo of qt version of threejs
* I modified some of it, now it works fine for me
**/
function readFile(url, onLoad, onProgress, onError) {var request = new XMLHttpRequest();request.onreadystatechange = function() {if (request.readyState === XMLHttpRequest.DONE) {// TODO: Re-visit https://bugreports.qt.io/browse/QTBUG-45581 is solved in Qtif (request.status == 200 || request.status == 0) {
//                var response;
//                response = request.responseText;console.time('Process file: "' + url + '"');onLoad( request.responseText );console.timeEnd('Process file: "' + url + '"');}else if ( onError !== undefined ) {onError();}}else if (request.readyState === XMLHttpRequest.HEADERS_RECEIVED) {if ( onProgress !== undefined ) {onProgress();}}};request.open( 'GET', url, true );request.send( null );
}

因为我暂时只需要回调 onLoad 方法,所以我只关注这一部分的逻辑,该方法和浏览器中 AJAX 的异步请求并没有太大区别,不过需要注意的是这里有个 bug: request 放回的状态码有可能是 0,而这有可能意味着请求成功。所以在检测请求是否成功返回时应该要加上 request.status == 0 的判断。

总结

此外,如果想要在 QML 里面读写本地的配置文件,还可以使用 QML 已经提供的 Settings 模块,它对应的是 C++ 部分的 QSettings 类,提供平台无关的程序配置。

在 QML 中实现文件的读写有多种方法,具体的做法需要结合具体的需求,由于我做的程序可能需要迁移到 Web 上,因此最终使用 JavaScript 提供的 XMLHttpRequest 来进行异步请求。

转载于:https://www.cnblogs.com/brifuture/p/8463576.html

QML 读取本地文件内容相关推荐

  1. Electron教程(五)读取本地文件内容, icpMain icpRenderer 之间的交互

    Electron教程(五)读取本地文件内容, ipcMain ipcRenderer 之间的交互 Electron教程(一)什么是 Electron,由来.适用场景 和 Electron 的环境搭建 ...

  2. 保存页面文本到本地文件读取本地文件内容到页面

    问题描述:假设网页有个文本框之类的东西,想通过点击某一按钮后,将用户在文本框中输入的内容直接保存在本地某个文件中.同理,也想通过页面直接读取本地文件中的内容. 问题分析:因为整个处理过程不涉及到后台的 ...

  3. Java读取本地文件内容并输出

    下面是读取本地文件并输出内容的Java代码. 如果文件有中文,可能会乱码需要设置软件的编码格式. public static void readFile() {FileReader fileReade ...

  4. 读文件 —— WEB前端读取本地文件内容哪些事(前台解析txt文件)……

    强制让浏览器允许JS读写本地文件--的操作! 问题描述: 让自己的浏览器允许js读写本地文件,尽可能多的兼容各种浏览器.(即本机的js文件读写本机的文件) 问题回复--1: 您的意思是不需要浏览器与用 ...

  5. vue 读取本地文件内容

    将本地文件中内容显示在页面上 <el-button type="success" id="fileImport" v-on:click="cli ...

  6. vue中读取本地文件内容

    其实就是使用 FileReader对象,h5提供的异步api,可以读取文件中的数据. <input @change="uploadCode($event)" type=&qu ...

  7. Javascript 04 读取本地文件内容

    let fs = require('fs') const path = "E:\\test\\koukou.txt" console.log(path)const content ...

  8. 用Groovy读取本地文件的代码

    下面这些包默认已经被导入了,不需要使用import再次显式导入: java.io.* java.lang.* java.math.BigDecimal java.math.BigInteger jav ...

  9. cordova js(javascript)读取本地文件(将本地的bin文件转成字节数组)

    此问题已经解决,解决方法参考我的博客: cordova本地存储(存取): 读取项目里的本地文件 文章目录 1.下面两个比较有用: 2.下面两篇博客证明不用input标签的情况下,无法获取本地文件(包括 ...

最新文章

  1. 新的sublime text已经上传网盘,地址写在下面
  2. 微信开放JS-SDK,助力网页开发[转自微信官方]
  3. oauth最后的确认按钮_spring-oauth集成cas单点登录,登陆完成进入授权页面后,按回退按钮进入404页面的问题...
  4. 仿联想商城laravel实战---7、lavarel中如何给用户发送邮件
  5. php 数组导出csv_php导出CSV抽象类实例
  6. 计算机网络必备知识,非常全面!
  7. windows系统git服务器启动,windowsServer服务器上搭建GIt服务器
  8. JIURL文档-Linux的虚拟内存与分页机制(x86-64位)(一)
  9. vuebaidumap 删除覆盖物_VUE BAIDU MAP覆盖物 - 自定义覆盖物手记
  10. 诗和远方:无题(四十四)- 曾经写给妹子的一首诗
  11. 大赛评委共论技术趋势,大咖观点干货满满!
  12. 用 Python 爬取了 14 年的福彩 3D 信息!彩民们,只能帮你们到这了
  13. 06LaTeX学习系列之---TeXstudio的使用
  14. 金蝶K/3WISE V14.0安装包下载地址,金蝶K3 WISE V14.0安装包资源包下载链接
  15. 两个平面之间的关系—平行、垂直、相交
  16. autoware中pure_pursuit控制和MPC控制解析
  17. tftpd获取文件失败
  18. 转载Flickr 网站架构分析
  19. 本本CPU控制让游戏3D效果最佳境界
  20. navcat导入mdf数据库文件教程

热门文章

  1. Redis面试常问-- Redis常用数据类型
  2. 微信小程序scroll-view去掉滚动条
  3. Docker操作补充
  4. oracle或mysql分组查询并且获取前3条排序后的数据
  5. oracle 如何创建游标,Oracle--plsql游标创建和使用
  6. 高效实用Kafka-Kafka消息处理(底层原理)
  7. java文件上传总结
  8. springboot整合mongodb changestream
  9. jquery一个元素绑定了多个 click 事件,如何取消其中的一个
  10. 12.C++ string 操作