QML 读取本地文件内容
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 Qt
if (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 来进行异步请求。
QML 读取本地文件内容的更多相关文章
- 手工创建tomcat应用,以及实现js读取本地文件内容
手工创建tomcat应用: 1.在webapps下面新建应用目录文件夹 2.在文件夹下创建或是从其他应用中复制:META-INF,WEB-INF这两个文件夹, 其中META-INF清空里面,WEB-I ...
- HTML-点击Div读取本地文件内容
<!DOCTYPE html> <html> <div id="container" onclick="choosefile();" ...
- 前台JS(type=‘file’)读取本地文件的内容,兼容各种浏览器
[自己测了下,能兼容各种浏览器,但是读取中文会出现乱码.自己的解决方法是用notepad++把txt文件编码改为utf-8(应该是和浏览器编码保持一致吧?..)] 原文 http://blog.cs ...
- ios本地文件内容读取,.json .plist 文件读写
ios本地文件内容读取,.json .plist 文件读写 本地文件.json .plist文件是较为常用的存储本地数据的文件,对这些文件的操作也是一种常用的基础. 本文同时提供初始化变量的比较标准的 ...
- H5读取本地文件操作
H5读取本地文件操作 本文转自:转:http://hushicai.com/2014/03/29/html5-du-qu-ben-di-wen-jian.html感谢大神分享. 常见的语言比如php. ...
- python 读取本地文件批量插入mysql
Uin_phone.txt 本地文件内容 有1000条,这里只是展示前几条,供参考 133584752 133584759 133584764 133584773 133584775 13358477 ...
- FileReader读取本地文件
FileReader是一种异步读取文件机制,结合input:file可以很方便的读取本地文件. 一.input:type[file] file类型的input会渲染为一个按钮和一段文字.点击按钮可打开 ...
- 五种方式让你在java中读取properties文件内容不再是难题
一.背景 最近,在项目开发的过程中,遇到需要在properties文件中定义一些自定义的变量,以供java程序动态的读取,修改变量,不再需要修改代码的问题.就借此机会把Spring+SpringMVC ...
- .NET 读取本地文件绑定到GridViewRow
wjgl.aspx.cs: using System; using System.Collections; using System.Configuration; using System.Data; ...
随机推荐
- 自己写的Log记录组件
常规的Debug组件的封装,然后加了一个文件log,分异步和同步(可跨平台使用). /// <summary> /// 常用IO操作类 /// </summary> publi ...
- .NET 开源GIS解决方案一 概述
写在前面 最近开始研究开源GIS,国内开源GIS的资料很少,而基于.net的又是少之又少.所以决定把自己研究的资料进行总结整理,技术在于分享,本系列(计划是写一个系列,如果我可以坚持下来的话)部分是自 ...
- Matplotlib中plot画点图和折线图
引入: import matplotlib.pyplot as plt 基本语法: plt.plot(x, y, format_string, **kwargs) x:x轴数据,列表或数组,可选 y: ...
- DOS下修改IP地址
这两天不知道怎么回事,IPV4竟然无法修改,郁闷之极下,想到用命令行试试. 于是敲入下面的代码: >netsh <Enter> netsh>interface <Ente ...
- 树状数组【bzoj1103】: [POI2007]大都市meg
1103: [POI2007]大都市meg 在经济全球化浪潮的影响下,习惯于漫步在清晨的乡间小路的邮递员Blue Mary也开始骑着摩托车传递邮件了. 不过,她经常回忆起以前在乡间漫步的情景.昔日,乡 ...
- 【模板】文艺平衡树(Splay) 区间翻转 BZOJ 3223
您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 N,M<= ...
- HashMap 1.8的源码分析三
线程安全问题: 在添加时候并没有进行安全考虑,枷锁 所以是线程不安全的,接下来进行代码测试; package com.mmall.concurrency.example.commonUnsafe; i ...
- 对DeepLung数据预处理部分的详细展示
之前有解释预处理部分的函数,不过觉得还不够详细,同时文字解释还不够直观,所以现在想一步步运行下,打印输出 首先读取原始数据,包括相应的注释(即结节标签)[注意]注释文件中的标签是按x,y,z的顺序给的 ...
- 对bootstrap模态框的小尝试
bootstrap中有一个“模态框”插件,我理解的意思就是一个具有全局遮罩的弹窗提示,官方解释是:模态框(Modal)是覆盖在父窗体上的子窗体.通常,目的是显示来自一个单独的源的内容,可以在不离开父窗 ...
- Android RecyView 滑动置指定位置
1,直接回到顶部 recyview.getLinearLayoutManager().scrollToPositionWithOffset(0, 0); 2,慢慢的回到顶部 private void ...