Qt QML डेटा मॉडल C++ के साथ काम करने के लिए नहीं लगता
model-view-controller datamodel (1)
यह पता चला है कि एक बहुत ही सरल कारण है कि cppModel
की count
संपत्ति उपलब्ध नहीं है - ऐसा इसलिए है क्योंकि न तो QAbstractListModel
और न ही QList<>
एक count
संपत्ति है!
मैंने यह मान लिया था कि एक ListModel
को एक सी ++ आधारित ऑब्जेक्ट के साथ प्रतिस्थापित किया जा सकता है जैसे कि QList <> इसका मतलब था कि वे बहुरूपक थे और एक सूचीदृश्य या पथव्यू एक count
संपत्ति का उपयोग सही ढंग से उन्हें संभालना होगा
सबसे पहले, न तो QAbstractListModel
और न ही QList<>
एक ListModel
साथ बहुरूप हैं। यह पता चला है कि वे सभी केवल विशेष-स्थिति वाले हैं - एक ListView
जानता है कि इसमें एक ListModel
या QList<>
या एक QAbstractListModel
और प्रत्येक का उपयोग करने के लिए अलग कोड पथ हैं ListView
को QList<>
या QList<>
प्रबंधित करने के लिए कोई भी count
संपत्ति की आवश्यकता नहीं है। वास्तव में, यह मुझे स्पष्ट नहीं है कि ListView
और PathView
भी ListModel
की count
संपत्ति का उपयोग करें count
संपत्ति ज्यादातर QML प्रोग्रामर के लाभ के लिए प्रतीत होती है। मेरे उदाहरण में, मैं PathView
में Path
ऑब्जेक्ट बनाने के लिए count
गुण का उपयोग कर रहा था। मेरा उदाहरण पूरी तरह से काम करता है अगर मैं इसके बजाय एक length
प्रॉपर्टी का उपयोग करता हूं क्योंकि QList<>
length
संपत्ति होती है
ब्लैक और टॉइसर के लिए धन्यवाद इस पर मुझे मदद करने के लिए # क्यूटी-क्यूएमएल पर (इस जवाब को पोस्ट करके स्टैकवर्फरफ्लो पॉइंट्स एकत्र नहीं करना चाहते थे, इसलिए मैं इसे समुदाय के लाभ के लिए पोस्ट कर रहा हूं)।
मैं http://doc.qt.digia.com/4.7/qdeclarativemodels.html में उदाहरणों के साथ काम कर रहा हूं जो QML घोषणात्मक डेटा मॉडल पर क्यूटी पेज है। विशेष रूप से, मैं objectlistmodel
उदाहरण के साथ काम कर रहा हूं जो क्यूटी एसडीके (उदाहरण / घोषणात्मक / मॉडल दृश्य / वस्तुसूची मॉडल में) के साथ आता है। यह सब ठीक से काम करने लगता है, जब तक कि मैं इसे http://www.developer.nokia.com/Community/Wiki/How_to_create_a_Page_Control_component_in_QML पर QMLPageControl उदाहरण के साथ संयोजित करने का प्रयास नहीं करता।
जब मैं QML- आधारित लिस्ट मॉडेल (QML लिस्टइलेमेंट्स के साथ आबादी) को एक 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 }
}
}
}
... सब कुछ बहुत अच्छी तरह से काम करता है यह पूरी तरह से अपेक्षित काम करता है - एक विंडो बैंड के रंगीन पृष्ठभूमि में कुछ पाठ के साथ फ़ैशन करती है।
फिर, मैं थोड़ा और अधिक जटिल कर सकता हूं, जैसे कि पथव्यू का उपयोग करें:
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
}
}
}
}
फिर से, यह सब अपेक्षित काम करता है - एक खिड़की रंगीन बक्से की एक झीझने योग्य, ड्रैगनीय सूची के साथ चली जाती है।
बैक अप, मैं उसके बाद सी ++ में डेटा ऑब्जेक्ट परिभाषित कर सकता हूं:
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
dataobject.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 }
}
}
}
एक बार फिर, यह सिर्फ ठीक काम करता है - बैंड में व्यवस्थित रंगीन पृष्ठभूमि के पाठ के साथ एक संवाद प्रकट होता है। एक सी + + मॉडल द्वारा समर्थित सूचीदृश्य प्रदर्शित करना प्रत्येक बिट के साथ-साथ एक QML ListModel द्वारा समर्थित सूचीदृश्य को प्रदर्शित करता है।
मैं क्या काम करना चाहता हूं एक ऐसा सी + + मॉडल है जिस तरह से एक पाथव्यू का समर्थन किया जाता है:
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 की एक मूल आकृति है जो कि एक सूची दृश्य के लिए एक QML ListModel / ListItem संग्रह के लिए पर्याप्त है, लेकिन प्रदर्शित करने के लिए पथव्यू के लिए पर्याप्त नहीं है।
क्या किसी को पता है कि क्या गलत हो सकता है? दुर्भाग्य से क्यूएमएल क्लास दस्तावेज वास्तव में कन्फॉर्मेंट सी ++ स्टैंड-इन लिखने के लक्ष्य के साथ नहीं जुटाए गए हैं उदाहरण के लिए, http://kt-project.org/doc/qt-4.8/qml-pathview.html पर PathView ऑब्जेक्ट दस्तावेज यह नहीं कहता कि इसके मॉडल को किस प्रकार समर्थन की आवश्यकता है इसके अलावा, लिस्टमोडल प्रलेखन निश्चित नहीं है - यह बिल्कुल नहीं बताता है कि सूचीमॉडल का क्या गुण है और कोई स्पष्ट दस्तावेज नहीं है कि किस प्रकार QList उन आवश्यकताओं को ठीक करता है और यह कैसे नहीं करता।
अद्यतनः मैंने विंडोज पर क्यूटी 5 के साथ यह कोशिश की है, और मुझे अभी भी यही समस्या है।