Ver Fonte

添加文件IO,c++视图模型介绍。

cwc1987 há 9 anos atrás
pai
commit
efcb4856e4

+ 4 - 0
SUMMARY.md

@@ -111,6 +111,10 @@
    * [Qt通用类(Common Qt Classes)](qt_and_c++/common_qt_classes.md)
        * [QString](qt_and_c++/qstring.md)
        * [顺序容器(Sequential Containers)](qt_and_c++/sequential_containers.md)
+       * [组合容器(Associative Containers)](qt_and_c++/associative_containers.md)
+       * [文件IO(File IO)](qt_and_c++/file_io.md)
+   * [C++数据模型(Models in C++)](qt_and_c++/models_in_c++.md)
+       * [一个简单的模型(A simple model)](qt_and_c++/a_simple_model.md)
 * [其它(Other)](other/README.md)
    * [协作校正](other/collaboration_correction.md)
 

+ 53 - 0
qt_and_c++/a_simple_model.md

@@ -0,0 +1,53 @@
+# 一个简单的模型(A simple model)
+
+一个典型的QML C++模型继承自```QAbstractListModel```
+,并且最少需要实现```data```和```rowCount```函数。在这个例子中我们将使用由```QColor```类提供的一系列SVG颜色名称并且使用我们的模型展示它们。数据被存储在```QList<QString>```数据容器中。
+
+我们的```DataEntryModel```基础自```QAbstractListModel```并且实现了需要强制实现的函数。我们可以在```rowCount```中忽略父对象索引,这只在树模型中使用。```QModelIndex```类提供了视图检索数据需要的单元格行和列的信息,视图基于行列和数据角色从模型中拉取数据。```QAbstractListModel```在```QtCore```中定义,但是```QColor```被定义在```QtGui```中。我们需要附加```QtGui```依赖。对于QML应用程序,它可以依赖```QtGui```,但是它通常不依赖```QtWidgets```。
+
+```
+#ifndef DATAENTRYMODEL_H
+#define DATAENTRYMODEL_H
+
+#include <QtCore>
+#include <QtGui>
+
+class DataEntryModel : public QAbstractListModel
+{
+    Q_OBJECT
+public:
+    explicit DataEntryModel(QObject *parent = 0);
+    ~DataEntryModel();
+
+public: // QAbstractItemModel interface
+    virtual int rowCount(const QModelIndex &parent) const;
+    virtual QVariant data(const QModelIndex &index, int role) const;
+private:
+    QList<QString> m_data;
+};
+
+#endif // DATAENTRYMODEL_H
+```
+
+现在你可以使用QML导入命令```import org.example 1.0```来访问```DataEntryModel```,和其它QML项使用的方法一样```DataEntryModel {}```。
+
+我们在这个例子中使用它来显示一个简单的颜色条目列表。
+
+```
+import org.example 1.0
+
+ListView {
+    id: view
+    anchors.fill: parent
+    model: DataEntryModel {}
+    delegate: ListDelegate {
+        // use the defined model role "display"
+        text: model.display
+    }
+    highlight: ListHighlight { }
+}
+```
+
+ListDelegate是自定义用来显示文本的代理。ListHighlight是一个矩形框。保持例子的整洁在代码提取时进行了保留。
+
+视图现在可以使用C++模型来显示字符串列表,并且显示模型的属性。它仍然非常简单,但是已经可以在QML中使用。通常数据由外部的模型提供,这里的模型只是扮演了视图的一个接口。

+ 64 - 0
qt_and_c++/associative_containers.md

@@ -0,0 +1,64 @@
+# 组合容器(Associative Containers)
+
+映射,字典或者集合是组合容器的例子。它们使用一个键来保存一个值。它们可以快速的查询它们的元素。我们将展示使用最多的组合容器```QHash```,同时也会展示一些C++11新的特性。
+
+```
+    QHash<QString, int> hash({{"b",2},{"c",3},{"a",1}});
+    qDebug() << hash.keys(); // a,b,c - unordered
+    qDebug() << hash.values(); // 1,2,3 - unordered but same as order as keys
+
+    QVERIFY(hash["a"] == 1);
+    QVERIFY(hash.value("a") == 1);
+    QVERIFY(hash.contains("c") == true);
+
+    { // JAVA iterator
+        int sum =0;
+        QHashIterator<QString, int> i(hash);
+        while (i.hasNext()) {
+            i.next();
+            sum+= i.value();
+            qDebug() << i.key() << " = " << i.value();
+        }
+        QVERIFY(sum == 6);
+    }
+
+    { // STL iterator
+        int sum = 0;
+        QHash<QString, int>::const_iterator i = hash.constBegin();
+        while (i != hash.constEnd()) {
+            sum += i.value();
+            qDebug() << i.key() << " = " << i.value();
+            i++;
+        }
+        QVERIFY(sum == 6);
+    }
+
+    hash.insert("d", 4);
+    QVERIFY(hash.contains("d") == true);
+    hash.remove("d");
+    QVERIFY(hash.contains("d") == false);
+
+    { // hash find not successfull
+        QHash<QString, int>::const_iterator i = hash.find("e");
+        QVERIFY(i == hash.end());
+    }
+
+    { // hash find successfull
+        QHash<QString, int>::const_iterator i = hash.find("c");
+        while (i != hash.end()) {
+            qDebug() << i.value() << " = " << i.key();
+            i++;
+        }
+    }
+
+    // QMap
+    QMap<QString, int> map({{"b",2},{"c",2},{"a",1}});
+    qDebug() << map.keys(); // a,b,c - ordered ascending
+
+    QVERIFY(map["a"] == 1);
+    QVERIFY(map.value("a") == 1);
+    QVERIFY(map.contains("c") == true);
+
+    // JAVA and STL iterator work same as QHash
+```
+

+ 44 - 0
qt_and_c++/file_io.md

@@ -0,0 +1,44 @@
+# 文件IO(File IO)
+
+通常我们都需要从读写文件。```QFile```是一个```QObject```对象,但是大多数情况下它被创建在栈上。```QFile```包含了通知用户数据可读取信号。它可以异步读取大段的数据,直到整个文件读取完成。为了方便它允许使用阻塞的方式读取数据。这种方法通常用于读取小段数据或者小型文件。幸运的是我们在这些例子中都只使用了小型数据。
+
+除了读取文件内容到内存中可以使用```QByteArray```,你也可以根据读取数据类型使用```QDataStream```或者使用```QTextStream```读取unicode字符串。我们现在来看看如何使用。
+
+```
+    QStringList data({"a", "b", "c"});
+    { // write binary files
+        QFile file("out.bin");
+        if(file.open(QIODevice::WriteOnly)) {
+            QDataStream stream(&file);
+            stream << data;
+        }
+    }
+    { // read binary file
+        QFile file("out.bin");
+        if(file.open(QIODevice::ReadOnly)) {
+            QDataStream stream(&file);
+            QStringList data2;
+            stream >> data2;
+            QCOMPARE(data, data2);
+        }
+    }
+    { // write text file
+        QFile file("out.txt");
+        if(file.open(QIODevice::WriteOnly)) {
+            QTextStream stream(&file);
+            QString sdata = data.join(",");
+            stream << sdata;
+        }
+    }
+    { // read text file
+        QFile file("out.txt");
+        if(file.open(QIODevice::ReadOnly)) {
+            QTextStream stream(&file);
+            QStringList data2;
+            QString sdata;
+            stream >> sdata;
+            data2 = sdata.split(",");
+            QCOMPARE(data, data2);
+        }
+    }
+```

+ 36 - 0
qt_and_c++/models_in_c++.md

@@ -0,0 +1,36 @@
+# C++数据模型(Models in C++)
+
+在QML中的数据模型为链表视图,路径视图和其它需要为模型中的每个子项创建一个代理引用的视图提供数据。视图只创建可是区域内或者缓冲范围内的引用。这使得即使包含成千上万的子项模型仍然可以保持流畅的用户界面。代理扮演了用来渲染模型子项数据的模板。总之:视图使用代理作为模板来渲染模型中的子项。模型为视图提供数据。
+
+当你不想使用C++时,你可以在QML环境中定义模型,你有多重方法为一个视图提供模型。使用C++操作数据或者使用包含了大型数据的C++模型比在QML环境中达到相同目的更加稳定可靠。但是当你值需要少量数据时,QML模型时非常适合的。
+
+```
+ListView {
+    // using a integer as model
+    model: 5
+    delegate: Text { text: 'index: ' + index }
+}
+
+ListView {
+    // using a JS array as model
+    model: ['A', 'B', 'C', 'D', 'E']
+    delegate: Text { 'Char['+ index +']: ' + modelData }
+}
+
+ListView {
+    // using a dynamic QML ListModel as model
+    model: ListModel {
+        ListElement { char: 'A' }
+        ListElement { char: 'B' }
+        ListElement { char: 'C' }
+        ListElement { char: 'D' }
+        ListElement { char: 'E' }
+    }
+    delegate: Text { 'Char['+ index +']: ' + model.char }
+}
+```
+
+QML视图知道如何操作不同的模型。对于来自C++的模型需要遵循一个特定的协议。这个协议与动态行为一起被定义在一个API(```QAbstractItemModel```)中。这个API时为桌面窗口开发的,它可以灵活的作为一个树的基础或者多列表格或者链表。在QML中我们通常值使用API的链表版本(```QAbstractListModel```)。API包含了一些需要强制实现的函数,另外一些函数时可选的。可选部分通常是用来动态添加或者删除数据。
+
+
+

+ 2 - 2
qt_and_c++/sequential_containers.md

@@ -1,8 +1,8 @@
 # 顺序容器(Sequential Containers)
 
-链表,队列,数组都是顺序容器。最常用的顺序容器是QList类。它是一个模板类,需要一个类型才能被初始化。它也是隐式共享的,数据存放在堆中。所有的容器类应该被创建在栈上。正常情况下你不需要使用new QList<T>()这样的语句,千万不要使用new来初始化一个容器。
+链表,队列,数组都是顺序容器。最常用的顺序容器是```QList```类。它是一个模板类,需要一个类型才能被初始化。它也是隐式共享的,数据存放在堆中。所有的容器类应该被创建在栈上。正常情况下你不需要使用```new QList<T>()```这样的语句,千万不要使用new来初始化一个容器。
 
-类QList与类QString一样强大,提供了方便的接口来查询数据。下面一个简单的示例展示了如何使用和遍历链表,这里面也使用到了一些C++11的新特性。
+类```QList```与类```QString```一样强大,提供了方便的接口来查询数据。下面一个简单的示例展示了如何使用和遍历链表,这里面也使用到了一些C++11的新特性。
 
 ```
     // Create a simple list of ints using the new C++11 initialization