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 来进行异步请求。

原文地址:https://www.cnblogs.com/brifuture/p/8463576.html

时间: 2024-10-08 17:15:50

QML 读取本地文件内容的相关文章

java读取本地文件内容

1.要在F盘下有一个叫test的条形图格式的文件, Java代码   package test; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; public class ReaderFile { public static void main(String[] args) throws Exception { String fileName = "F://test.txt";

前台JS(type=‘file’)读取本地文件的内容,兼容各种浏览器

[自己测了下,能兼容各种浏览器,但是读取中文会出现乱码.自己的解决方法是用notepad++把txt文件编码改为utf-8(应该是和浏览器编码保持一致吧?..)] 原文  http://blog.csdn.net/xwq1012/article/details/41941895 参考如下: http://blog.csdn.net/lejuo/article/details/11528243 前台JS读取本地文件内容,兼容IE7.8.9.10 FF Chrome等各种版本,纠结了好长时间,终于找

jquery读取本地文件

<html> <head> <script type="text/javascript" src="/jquery/jquery.js"></script> <script type="text/javascript"> $(document).ready(function(){ $("#b01").click(function(){ htmlobj=$.ajax({

H5读取本地文件操作

H5读取本地文件操作 本文转自:转:http://hushicai.com/2014/03/29/html5-du-qu-ben-di-wen-jian.html感谢大神分享. 常见的语言比如php.shell等,是如何读取文件的呢? 实际上,大多数语言都需要先获取文件句柄,然后调用文件访问接口,打开文件句柄,读取文件! 那么,HTML5是否也是这样的呢? 答案是肯定的! HTML5为我们提供了一种与本地文件系统交互的标准方式:File Api. 该规范主要定义了以下数据结构: File Fil

JS读取本地文件及目录的方法

Javascript是网页制作中离不开的脚本语言,依靠它,一个网页的内容才生动活泼.富有朝气.但也许你还没有发现并应用它的一些更高级 的功能吧?比如,对文件和文件夹进行读.写和删除,就象在VB.VC等高级语言中经常做的工作一样.怎么样,你是否需要了解这方面的知 识?那就请跟我来,本文将详细描述如何使用Javascript语言进行文件操作. 一.功能实现核心:FileSystemObject 对象 其实,要在Javascript中实现文件操作功能,主要就是依靠FileSystemobject对象.

Cocos2d-x读取本地文件

在公司在项目开发的时候需要读取本地的文件,于是在网上搜索了一下以下关于Cocos2d-x文件读取的操作,用了两种方法都可以实现,一种是使用C++另种是Cocos2d-x代码如下: //读取文件(参数分别为文件名和文本框) void GameRegistry::readFile(const char *pFileName,UILabel *pLabel) { /*方法一 ifstream inFile; inFile.open(pFileName);//打开文件 string pSaveStr;/

FileReader读取本地文件

FileReader是一种异步读取文件机制,结合input:file可以很方便的读取本地文件. 一.input:type[file] file类型的input会渲染为一个按钮和一段文字.点击按钮可打开文件选择窗口,文字表示对文件的描述(大部分情况下为文件名).file类型的input会有files属性,保存着文件的相关信息. <input type="file" name="" id="fileBox"> 点击按钮,上传一个文件后,在

.NET读取Office文件内容(word、excel、ppt)

引用命名空间 1 using Microsoft.Office.Core; 2 using Word = Microsoft.Office.Interop.Word; 3 using Excel = Microsoft.Office.Interop.Excel; 4 using PowerPoint = Microsoft.Office.Interop.PowerPoint; Word文件的读取 1 public string ReadFile() 2 { 3 string text = str

五种方式让你在java中读取properties文件内容不再是难题

一.背景 最近,在项目开发的过程中,遇到需要在properties文件中定义一些自定义的变量,以供java程序动态的读取,修改变量,不再需要修改代码的问题.就借此机会把Spring+SpringMVC+Mybatis整合开发的项目中通过java程序读取properties文件内容的方式进行了梳理和分析,先和大家共享. 二.项目环境介绍 Spring 4.2.6.RELEASE SpringMvc 4.2.6.RELEASE Mybatis 3.2.8 Maven 3.3.9 Jdk 1.7 Id