在 QML (Qt) 中读写文件
Posted
技术标签:
【中文标题】在 QML (Qt) 中读写文件【英文标题】:Reading and writing files in QML (Qt) 【发布时间】:2013-07-26 13:25:07 【问题描述】:我正在尝试实现Reading and writing files in QML,并遇到了来自诺基亚的链接文章,但未能成功使用看似明显的代码示例。我想我不必说我是这个领域的新手。
我在哪里放置这个代码sn-p(这是页面上的第二个代码sn-p。 ):
#include "fileio.h"
Q_DECL_EXPORT int main(int argc, char *argv[])
qmlRegisterType<FileIO, 1>("FileIO", 1, 0, "FileIO");
当我将上述代码 sn-p 放在我的主窗体中时,我还不断收到关于 qmlRegisterType 未在上下文中注册的错误。 有人可以就如何实现这个(或在 QML / Qt 中读写文件的任何方法)提供一些建议吗?
【问题讨论】:
这绝对是 C++ 中要做的事情。让 QML 保持其应有的薄 UI 层。 弗兰克,感谢您的回复。实际上,链接中的代码是 C++ 中文件访问的实现,我的问题是如何完成这个(再次在 C++ 中) 你的“主要形式”是什么? alexisdm - 我没有主要的 ID,它位于 main.qml 【参考方案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 允许它(即使是文件重写)。不过,不确定是设计还是错误。
【讨论】:
【参考方案2】:Nokia 在教程中写的例子并不是一个纯粹的 QML 程序。它包含 C++ 和 QML。这种程序通常是加载 QML 文件并渲染它的 C++ 程序。 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 个参数:
为了使用这个函数,你必须在你编写它的 C++ 文件中包含一个 C++ 头文件:
如果您使用 Qt 4,则标头为<QtDeclarative>
。
如果您使用 Qt 5,则标头为 <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”。
【讨论】:
air-dex - 谢谢。我想这个教程是为有经验的程序员准备的,但从来没有搞清楚 qmlRegisterTypeFileIO 的完整示例可以在此页面上找到: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();
...
我们将省略属性,因为它们是简单的 setter 和 getter。
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
【讨论】:
链接已损坏 :( 我认为这是新链接:qmlbook.github.io/ch17-extensions/… 感谢您报告损坏的链接。我已经更新了。【参考方案4】:借助 V-Play SDK,您可以使用 QML 中的FileUtils 类,访问任何平台上的文件系统。
看起来像这样:
var success = fileUtils.writeFile("TextFiles/myFile.txt", "test text")
【讨论】:
以上是关于在 QML (Qt) 中读写文件的主要内容,如果未能解决你的问题,请参考以下文章