QML 宣言型データ モデルに関する Qt ページであるhttp://doc.qt.digia.com/4.7/qdeclarativemodels.htmlの例を使用してきました。特に、objectlistmodel
Qt SDK (examples/declarative/modelviews/objectlistmodel 内) に付属の例を使用しています。http://www.developer.nokia.com/Community/Wiki/How_to_create_a_Page_Control_component_in_QMLで QMLPageControl の例と組み合わせようとするまで、すべてがうまく機能しているようです。
QML ベースの ListModel (QML ListElements が入力された) を QML ListView で表示しようとすると、次のようになります。
import QtQuick 1.0
Rectangle {
width: 200; height: 200
ListModel {
id: qmlModel
ListElement { name: "qml entry1 (red)"; colour: "red" }
ListElement { name: "qml entry2 (orange)"; colour: "orange" }
ListElement { name: "qml entry3 (yellow)"; colour: "yellow" }
ListElement { name: "qml entry4 (green)"; colour: "green" }
ListElement { name: "qml entry5 (blue)"; colour: "blue" }
ListElement { name: "qml entry6 (purple)"; colour: "purple" }
}
ListView {
id: list_view
anchors.fill: parent
model: qmlModel
delegate: Rectangle {
height: 20
width: 200
color: colour
Text { text: name }
}
}
}
...すべてが非常にうまく機能します。これは完全に期待どおりに機能します。バンド内の色付きの背景にテキストが表示されたウィンドウがポップアップします。
次に、PathView を使用するなど、もう少し複雑なことを行うことができます。
import QtQuick 1.0
Rectangle {
width: 200; height: 200
ListModel {
id: qmlModel
ListElement { name: "qml entry1 (red)"; colour: "red" }
ListElement { name: "qml entry2 (orange)"; colour: "orange" }
ListElement { name: "qml entry3 (yellow)"; colour: "yellow" }
ListElement { name: "qml entry4 (green)"; colour: "green" }
ListElement { name: "qml entry5 (blue)"; colour: "blue" }
ListElement { name: "qml entry6 (purple)"; colour: "purple" }
}
// ListView {
// id: list_view
// anchors.fill: parent
// model: qmlModel
// delegate: Rectangle {
// height: 20
// width: 200
// color: colour
// Text { text: name }
// }
// }
PathView {
id: my_path_view
anchors.fill: parent
Keys.onRightPressed: if (!moving && interactive) incrementCurrentIndex()
Keys.onLeftPressed: if (!moving && interactive) decrementCurrentIndex()
flickDeceleration: 500
preferredHighlightBegin: 0.5
preferredHighlightEnd: 0.5
focus: true
interactive: true
model: qmlModel
delegate: Rectangle {
width: 100
height: 100
color: colour
Text {
anchors.centerIn: parent
text: name
}
}
path: Path {
startX: - my_path_view.width * my_path_view.model.count / 2 + my_path_view.width / 2
startY: my_path_view.height / 2
PathLine {
x: my_path_view.width * my_path_view.model.count / 2 + my_path_view.width / 2
y: my_path_view.height / 2
}
}
}
}
繰り返しますが、これはすべて期待どおりに機能します。ウィンドウがポップアップし、色付きのボックスのフリックおよびドラッグ可能なリストが表示されます。
バックアップすると、次のように C++ でデータ オブジェクトを定義できます。
dataobject.h
#ifndef DATAOBJECT_H
#define DATAOBJECT_H
#include <QObject>
class DataObject : public QObject
{
Q_OBJECT
Q_PROPERTY( QString name READ name WRITE setName NOTIFY nameChanged )
Q_PROPERTY( QString colour READ colour WRITE setColour NOTIFY colourChanged )
public:
DataObject( QObject * parent = 0 );
DataObject( const QString &_name, const QString &_color, QObject * parent=0 );
QString name() const;
void setName(const QString &);
QString colour() const;
void setColour(const QString &);
signals:
void nameChanged();
void colourChanged();
private:
QString m_name;
QString m_colour;
};
#endif // DATAOBJECT_H
データオブジェクト.cpp
#include "dataobject.h"
#include <QDebug>
DataObject::DataObject( QObject * parent )
: QObject( parent )
{
qDebug() << "DataObject::DataObject() has been called.\n";
}
DataObject::DataObject( const QString &_name, const QString &_colour, QObject * parent )
: QObject( parent )
, m_name( _name )
, m_colour( _colour )
{
qDebug() << "DataObject::DataObject(name, color) has been called.\n";
}
QString DataObject::name() const {
qDebug() << "name() has been called.\n";
return m_name;
}
void DataObject::setName(const QString &name) {
qDebug() << "setName has been called.\n";
if ( name != m_name ) {
m_name = name;
emit nameChanged();
}
}
QString DataObject::colour() const {
qDebug() << "colour() has been called.\n";
return m_colour;
}
void DataObject::setColour(const QString &colour) {
qDebug() << "setColour has been called.\n";
if ( colour != m_colour ) {
m_colour = colour;
emit colourChanged();
}
}
そして、それを QML コンテキストに追加します。
#include <QApplication>
#include <QDialog>
#include <QDeclarativeView>
#include <QDeclarativeContext>
#include <QLayout>
#include <QDir>
#include "qmlapplicationviewer.h"
#include "dataobject.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QList<QObject*> dataList;
dataList.append( new DataObject( "c++ entry1 (red)", "red" ) );
dataList.append( new DataObject( "c++ entry2 (orange)", "orange" ) );
dataList.append( new DataObject( "c++ entry3 (yellow)", "yellow" ) );
dataList.append( new DataObject( "c++ entry4 (green)", "green" ) );
dataList.append( new DataObject( "c++ entry5 (blue)", "blue" ) );
dataList.append( new DataObject( "c++ entry6 (purple)", "purple" ) );
QmlApplicationViewer viewer;
viewer.rootContext()->setContextProperty( "cppModel", QVariant::fromValue(dataList) );
viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto);
#if defined( Q_OS_MAC )
viewer.setMainQmlFile("../Resources/qml/main.qml");
#elif defined( Q_OS_WIN32 )
viewer.setMainQmlFile("qml/main.qml");
#else
#error - unknown platform
#endif
viewer.showExpanded();
return app.exec();
}
最後に、QML で、この C++ モデルを ListView に追加します。
import QtQuick 1.0
Rectangle {
width: 200; height: 200
ListModel {
id: qmlModel
ListElement { name: "qml entry1 (red)"; colour: "red" }
ListElement { name: "qml entry2 (orange)"; colour: "orange" }
ListElement { name: "qml entry3 (yellow)"; colour: "yellow" }
ListElement { name: "qml entry4 (green)"; colour: "green" }
ListElement { name: "qml entry5 (blue)"; colour: "blue" }
ListElement { name: "qml entry6 (purple)"; colour: "purple" }
}
ListView {
id: list_view
anchors.fill: parent
//model: qmlModel
model: cppModel
delegate: Rectangle {
height: 20
width: 200
color: colour
Text { text: name }
}
}
}
繰り返しますが、これは問題なく機能します。帯状に配置された色付きの背景に対するテキストを含むダイアログが表示されます。C++ モデルに裏打ちされた ListView の表示は、QML ListModel に裏打ちされた ListView を表示するだけでなく、すべての部分で機能しているようです。
私がやりたいのは、次のような PathView をサポートする C++ モデルです。
import QtQuick 1.0
Rectangle {
width: 200; height: 200
ListModel {
id: qmlModel
ListElement { name: "qml entry1 (red)"; colour: "red" }
ListElement { name: "qml entry2 (orange)"; colour: "orange" }
ListElement { name: "qml entry3 (yellow)"; colour: "yellow" }
ListElement { name: "qml entry4 (green)"; colour: "green" }
ListElement { name: "qml entry5 (blue)"; colour: "blue" }
ListElement { name: "qml entry6 (purple)"; colour: "purple" }
}
// ListView {
// id: list_view
// anchors.fill: parent
// model: qmlModel
// //model: cppModel
// delegate: Rectangle {
// height: 20
// width: 200
// color: colour
// Text { text: name }
// }
// }
PathView {
id: my_path_view
anchors.fill: parent
Keys.onRightPressed: if (!moving && interactive) incrementCurrentIndex()
Keys.onLeftPressed: if (!moving && interactive) decrementCurrentIndex()
flickDeceleration: 500
preferredHighlightBegin: 0.5
preferredHighlightEnd: 0.5
focus: true
interactive: true
//model: qmlModel
model: cppModel
delegate: Rectangle {
width: 100
height: 100
color: colour
Text {
anchors.centerIn: parent
text: name
}
}
path: Path {
startX: - my_path_view.width * my_path_view.model.count / 2 + my_path_view.width / 2
startY: my_path_view.height / 2
PathLine {
x: my_path_view.width * my_path_view.model.count / 2 + my_path_view.width / 2
y: my_path_view.height / 2
}
}
}
}
これは機能しません。色付きの長方形が表示されますが、マウスで操作できず、qmlviewer ダイアログの中央に配置されていません。
そして、デバッグ コンソールに次のように表示されます。
QDeclarativeDebugServer: Waiting for connection on port 3768...
QDeclarativeDebugServer: Connection established
QPainterPath::lineTo: Adding point where x or y is NaN or Inf, ignoring call
QPainterPath::lineTo: Adding point where x or y is NaN or Inf, ignoring call
colour() has been called.
name() has been called.
colour() has been called.
name() has been called.
colour() has been called.
name() has been called.
colour() has been called.
name() has been called.
colour() has been called.
name() has been called.
colour() has been called.
name() has been called.
QPainterPath::lineTo: Adding point where x or y is NaN or Inf, ignoring call
QPainterPath::lineTo: Adding point where x or y is NaN or Inf, ignoring call
QPainterPath::lineTo: Adding point where x or y is NaN or Inf, ignoring call
QPainterPath::lineTo: Adding point where x or y is NaN or Inf, ignoring call
QPainterPath::lineTo: Adding point where x or y is NaN or Inf, ignoring call
QList には、ListView を表示するには QML ListModel/ListItem コレクションに十分近いが、PathView を表示するには十分に近い基本的な形状があるようです。
何がうまくいかないのか誰にも分かりませんか?残念ながら、QML クラスのドキュメントは、適合する C++ スタンドインを作成するという目標に合わせてまとめられたものではありません。たとえば、http://qt-project.org/doc/qt-4.8/qml-pathview.html にある PathView オブジェクトのドキュメントには、そのモデルがサポートする必要のあるプロパティが記載されていません。さらに、ListModel のドキュメントは決定的なものではありません。ListModel がサポートするプロパティが正確に記載されておらず、QList がそれらの要件をどの程度正確に満たし、どのように満たしていないかについての明確なドキュメントもありません。
更新: Windows 上の Qt 5 でこれを試しましたが、まだ同じ問題が発生しています。