我正在尝试实施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读写文件的方法)提供一些建议吗?
答案 0 :(得分:19)
如果您的文件只是文本,您可以使用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. ";
}
}
P.S。请注意,如果您尝试使用上述功能,所有现代浏览器都将抛出安全性异常,但QML允许它(即使是文件重写)。但不确定是设计还是错误。
答案 1 :(得分:8)
诺基亚在教程中编写的示例不是纯粹的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个参数:
要使用此功能,您必须在C ++文件中包含C ++标题:
<QtDeclarative>
。<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 ”,以避免混淆。
答案 2 :(得分: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
答案 3 :(得分:1)
使用V-Play SDK,您可以使用QML中的FileUtils类来访问任何平台上的文件系统。
这看起来像这样:
var success = fileUtils.writeFile("TextFiles/myFile.txt", "test text")