首页 文章

用QML(Qt)读写文件

提问于
浏览
8

我正在尝试实现Reading and writing files in QML并且遇到了诺基亚的链接文章,但未能成功使用看似明显的代码示例 . 我想我不必说我是这个领域的新手 .

我在哪里放置此代码段(这是页面上的第二个代码段 . ):

#include "fileio.h"
Q_DECL_EXPORT int main(int argc, char *argv[])
{
    qmlRegisterType<FileIO, 1>("FileIO", 1, 0, "FileIO");
}

当我将上面的代码片段放在我的主窗体中时,我也继续收到关于qmlRegisterType未在上下文中注册的错误 . 有人可以就如何实现这个(或任何在QML / Qt中读写文件的方法)提供一些建议吗?

4 回答

  • 7

    诺基亚在本教程中编写的示例不是纯粹的QML程序 . 它包含C和QML . 这种程序通常是一个C程序,它加载一个QML文件并呈现它 . C程序通常以一个名为 int main(int argc, char *argv[]); 的函数开头 . 在您的情况下,这是"main()"函数,它加载您的QML主文件( main.qml )文件并呈现它 .

    但在加载QML主文件之前,您必须告诉QML系统您将使用名为 FileIO 的自定义QML类 . 为此,您必须使用 int qmlRegisterType<T>(const char * package, int majorVersion, int minorVersion, char * classNameInQML); C函数 . 它需要大约5个参数:

    • T :C模板参数 . 这是你的C类(FileIO) .

    • package :所有QML类都包含在版本中 . 这是包的名称 .

    • majorVersion :所有QML类都在包中,版本化 . 这是包的主要版本号 .

    • minorVersion :所有QML类都在包中,版本化 . 这是包的次要版本号 .

    • classNameInQML :所有QML类都在包中,版本化 . 这是您将在QML文件中使用的类的名称大多数情况下,名称与C类名称相同 .

    要使用此功能,您必须在C文件中包含一个C头,您可以在其中编写它:

    • 如果使用Qt 4, Headers 为 <QtDeclarative> .

    • 如果使用Qt 5, Headers 为 <QtQml> .

    最后你应该有这样的东西:

    main.cpp(带有main()C函数的文件):

    // C++ header to include for using qmlRegisterType();
    #include <QtDeclarative>    // If you use Qt4
    #include <QtQml>            // If you use Qt5
    
    // Some stuff used by the main(); function
    #include <QApplication>
    #include <QLatin1String>
    
    #include "ui/qtquickapplicationviewer.hpp"    // Something which manages your QML files. Qt Creator will generate it for you if you use it to code..
    #include "fileio.h"    // Your FileIO C++ class
    
    /**
     * @fn Q_DECL_EXPORT int main(int argc, char *argv[])
     * @brief The C++ main(); function. Your program begins HERE.
     */
    Q_DECL_EXPORT int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
    
        // ...
    
        // Declaring your C++ class to the QML system
        qmlRegisterType<FileIO>("MyCustomClasses", 1, 0, "FileIOQML");
    
        // ...
    
        // Loading your main QML file
        QLatin1String mainQMLFile = "./ui/qml/main.qml";
        QtQuickApplicationViewer viewer;
        viewer.setMainQmlFile(mainQMLFile);
    
        // Showing how beautiful your QML interface is :)
        viewer.showExpanded();
    
        // Now let's play with your QML interface is :)
        return app.exec();
    }
    

    要加载的main.qml文件(从诺基亚教程开始):

    import QtQuick 1.1
    import MyCustomClasses 1.0
    
    Rectangle {
        width: 360
        height: 360
        Text {
            id: myText
            text: "Hello World"
            anchors.centerIn: parent
        }
    
        FileIOQML {
            id: myFile
            source: "my_file.txt"
            onError: console.log(msg)
        }
    
        Component.onCompleted: {
            console.log( "WRITE"+ myFile.write("TEST"));
            myText.text =  myFile.read();
        }
    }
    

    注意:我已经从诺基亚教程中更改了一些“FileIO”以避免混淆 .

  • 1

    如果您的文件只是文本,您可以使用XMLHttpRequest(用于读取和写入),如下所示:

    function openFile(fileUrl) {
        var request = new XMLHttpRequest();
        request.open("GET", fileUrl, false);
        request.send(null);
        return request.responseText;
    }
    
    function saveFile(fileUrl, text) {
        var request = new XMLHttpRequest();
        request.open("PUT", fileUrl, false);
        request.send(text);
        return request.status;
    }
    

    这是演示应用程序(Qt 5.6):

    import QtQuick 2.6
    import QtQuick.Dialogs 1.2
    import QtQuick.Controls 1.5
    
    ApplicationWindow {
        visible: true
        width: 640
        height: 480
        title: qsTr("Demo App")
    
        function openFile(fileUrl) {
            var request = new XMLHttpRequest();
            request.open("GET", fileUrl, false);
            request.send(null);
            return request.responseText;
        }
    
        function saveFile(fileUrl, text) {
            var request = new XMLHttpRequest();
            request.open("PUT", fileUrl, false);
            request.send(text);
            return request.status;
        }
    
        FileDialog {
            id: openFileDialog
            nameFilters: ["Text files (*.txt)", "All files (*)"]
            onAccepted: textEdit.text = openFile(openFileDialog.fileUrl)
        }
    
        FileDialog {
            id: saveFileDialog
            selectExisting: false
            nameFilters: ["Text files (*.txt)", "All files (*)"]
            onAccepted: saveFile(saveFileDialog.fileUrl, textEdit.text)
        }
    
        menuBar: MenuBar {
            Menu {
                title: qsTr("File")
                MenuItem {
                    text: qsTr("&Open")
                    onTriggered: openFileDialog.open()
                }
                MenuItem {
                    text: qsTr("&Save")
                    onTriggered: saveFileDialog.open()
                }
                MenuItem {
                    text: qsTr("Exit")
                    onTriggered: Qt.quit();
                }
            }
        }
    
        TextArea {
            id: textEdit
            anchors.fill: parent
            text:
                "Lorem ipsum dolor sit amet, consectetur adipisicing elit, " +
                "sed do eiusmod tempor incididunt ut labore et dolore magna " +
                "aliqua. Ut enim ad minim veniam, quis nostrud exercitation " +
                "ullamco laboris nisi ut aliquip ex ea commodo cosnsequat. ";
        }
    }
    

    附:请注意,如果您尝试使用上述功能,所有现代浏览器都将抛出安全性异常,但QML允许它(即使是文件重写) . 但不确定是设计还是错误 .

  • 18

    使用V-Play SDK,您可以使用QML中的FileUtils类来访问任何平台上的文件系统 .

    这看起来像这样:

    var success = fileUtils.writeFile("TextFiles/myFile.txt", "test text")
    
  • 1

    可以在此页面上找到FileIO的完整示例:https://qmlbook.github.io/ch17-extensions/extensions.html#fileio-implementation

    class FileIO : public QObject {
        ...
        Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
        Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
        ...
    public:
        Q_INVOKABLE void read();
        Q_INVOKABLE void write();
        ...
    }
    

    我们将遗漏这些属性,因为它们是简单的制定者和吸气剂 . read方法以读取模式打开文件,并使用文本流读取数据 .

    void FileIO::read()
    {
        if(m_source.isEmpty()) {
            return;
        }
        QFile file(m_source.toLocalFile());
        if(!file.exists()) {
            qWarning() << "Does not exits: " << m_source.toLocalFile();
            return;
        }
        if(file.open(QIODevice::ReadOnly)) {
            QTextStream stream(&file);
            m_text = stream.readAll();
            emit textChanged(m_text);
        }
    }
    

    更改文本时,必须使用emit textChanged(m_text)通知其他人有关更改的信息 . 否则,属性绑定将不起作用 . write方法执行相同操作但在写入模式下打开文件并使用流写入内容 .

    void FileIO::write()
    {
        if(m_source.isEmpty()) {
            return;
        }
        QFile file(m_source.toLocalFile());
        if(file.open(QIODevice::WriteOnly)) {
            QTextStream stream(&file);
            stream << m_text;
        }
    }
    

    源代码可以在这里找到:https://github.com/qmlbook/qmlbook/tree/master/docs/ch17-extensions/src/fileio

相关问题