qml
C ++ में कस्टम एलिमेंट्स बनाना
खोज…
C ++ में कस्टम एलिमेंट्स बनाना
QML दृश्य तत्वों के समृद्ध सेट के साथ आया था। केवल QML का उपयोग करके हम इन तत्वों के साथ जटिल अनुप्रयोगों का निर्माण कर सकते हैं। इसके अलावा अपने स्वयं के तत्व का निर्माण करना बहुत आसान है जैसे कि आयत, बटन, छवि आदि जैसे मानक वस्तुओं के सेट के आधार पर, हम कस्टम पेंटिंग के साथ तत्व बनाने के लिए कैनवास जैसी वस्तुओं का उपयोग कर सकते हैं। ऐसा लगता है कि हम सीएमएल की क्षमताओं को छूने के बिना केवल क्यूएमएल में विभिन्न प्रकार के अनुप्रयोगों का निर्माण कर सकते हैं। और यह वास्तव में सच है, लेकिन फिर भी कभी-कभी हम अपने आवेदन को तेज करना चाहते हैं या हम इसे क्यूटी की शक्ति के साथ विस्तारित करना चाहते हैं या कुछ अवसर जोड़ना चाहते हैं जो क्यूएमएल में उपलब्ध नहीं हैं। और निश्चित रूप से QML में ऐसी संभावना है। मूल रूप से QtQuick अपनी सामग्री को OpenGL पर आधारित उच्च-प्रदर्शन रेंडरिंग इंजन को चित्रित करने के लिए दृश्य ग्राफ़ का उपयोग करता है। अपने स्वयं के दृश्य तत्व को लागू करने के लिए हम 2 तरीकों का उपयोग कर सकते हैं:
- QPainter ( QQuickPaintedItem ) का उपयोग करते हुए Qt के लिए पारंपरिक।
- QQuickItem और OpenGL कार्यक्षमता का उपयोग करके सामान्य QML तरीका।
यह संभव है कि पहली विधि आसान लगती है, लेकिन यह विचार करने योग्य है कि यह पहले वाले की तुलना में धीमी है क्योंकि QtQuick किसी सतह पर आइटम की सामग्री को पेंट करता है और फिर इसे दृश्य ग्राफ में सम्मिलित करता है ताकि रेंडरिंग दो-चरणीय ऑपरेशन हो। इसलिए दृश्य ग्राफ एपीआई का उपयोग करना हमेशा काफी तेज होता है।
दोनों तरीकों को करीब से जानने के लिए आइए अपना एक तत्व बनाएं जो निश्चित रूप से क्यूएमएल में मौजूद नहीं है, उदाहरण के लिए एक त्रिकोण।
वर्ग घोषणा
class QQuickCustomItem : public QQuickItem
{
Q_OBJECT
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
public:
QQuickCustomItem(QQuickItem *parent = Q_NULLPTR);
protected:
QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData);
QColor color() const;
void setColor(const QColor &color);
private:
QColor m_color;
bool m_needUpdate;
signals:
void colorChanged();
};
हम संकेतों के साथ काम करने के लिए Q_OBJECT मैक्रो जोड़ते हैं। साथ ही हम अपने आयत का रंग निर्दिष्ट करने के लिए कस्टम गुण जोड़ते हैं। यह काम करने के लिए हमें केवल वर्चुअल फ़ंक्शन QQuiclItem :: updatePaintNode () की आवश्यकता है ।
कक्षा कार्यान्वयन।
सबसे पहले हम एक कंस्ट्रक्टर को परिभाषित करते हैं।
QQuickCustomItem::QQuickCustomItem(QQuickItem *parent) :
QQuickItem(parent),
m_color(Qt::red),
m_needUpdate(true)
{
setFlag(QQuickItem::ItemHasContents);
}
कृपया ध्यान दें कि setFlag () फ़ंक्शन कॉल अनिवार्य है अन्यथा आपकी वस्तु दृश्य ग्राफ़ में नहीं जोड़ी जाएगी। अगला, हम दर्द के लिए एक फ़ंक्शन को परिभाषित करते हैं।
QSGNode *QQuickCustomItem::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *updatePaintNodeData)
{
Q_UNUSED(updatePaintNodeData)
QSGGeometryNode *root = static_cast<QSGGeometryNode *>(oldNode);
if(!root) {
root = new QSGGeometryNode;
QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 3);
geometry->setDrawingMode(GL_TRIANGLE_FAN);
geometry->vertexDataAsPoint2D()[0].set(width() / 2, 0);
geometry->vertexDataAsPoint2D()[1].set(width(), height());
geometry->vertexDataAsPoint2D()[2].set(0, height());
root->setGeometry(geometry);
root->setFlag(QSGNode::OwnsGeometry);
root->setFlag(QSGNode::OwnsMaterial);
}
if(m_needUpdate) {
QSGFlatColorMaterial *material = new QSGFlatColorMaterial;
material->setColor(m_color);
root->setMaterial(material);
m_needUpdate = false;
}
return root;
}
फ़ंक्शन के लिए पहली कॉल पर हमारा नोड अभी तक नहीं बनाया गया है इसलिए oldNode होगा। इसलिए हम नोड बनाते हैं और इसे ज्यामिति और सामग्री असाइन करते हैं। यहां हम ठोस आयत को चित्रित करने के लिए अपनी ज्यामिति के लिए GL_TRIANGLE_FAN का उपयोग करते हैं। यह बिंदु OpenGL के समान है। उदाहरण के लिए त्रिकोण फ्रेम खींचने के लिए हम कोड को इसमें बदल सकते हैं:
geometry->setDrawingMode(GL_LINE_LOOP);
geometry->setLineWidth(5);
आप अन्य आकारों के लिए जाँच करने के लिए OpenGL मैनुअल का उल्लेख कर सकते हैं। इसलिए, हमारी संपत्ति के लिए सेटर / गेट्टर को परिभाषित करना बाकी है:
QColor QQuickCustomItem::color() const
{
return m_color;
}
void QQuickCustomItem::setColor(const QColor &color)
{
if(m_color != color) {
m_color = color;
m_needUpdate = true;
update();
colorChanged();
}
}
अब इसे काम करने के लिए केवल एक छोटा सा विवरण है। हमें नए आइटम के QtQuick को सूचित करने की आवश्यकता है। उदाहरण के लिए, आप इस कोड को अपने main.cpp में जोड़ सकते हैं:
qmlRegisterType<QQuickCustomItem>("stackoverflow.qml", 1, 0, "Triangle");
और यहाँ हमारी QML परीक्षण फ़ाइल है:
import QtQuick 2.7
import QtQuick.Window 2.0
import stackoverflow.qml 1.0
Window {
width: 800
height: 800
visible: true
Rectangle {
width: 200
height: 200
anchors.centerIn: parent
color: "lightgrey"
Triangle {
id: rect
width: 200
height: 200
transformOrigin: Item.Top
color: "green"
onColorChanged: console.log("color was changed");
PropertyAnimation on rotation {
from: 0
to: 360
duration: 5000
loops: Animation.Infinite
}
}
}
Timer {
interval: 1000
repeat: true
running: true
onTriggered: rect.color = Qt.rgba(Math.random(),Math.random(),Math.random(),1);
}
}
जैसा कि आप देखते हैं कि हमारा आइटम अन्य सभी QML वस्तुओं की तरह व्यवहार करता है। अब QPainter का उपयोग करके समान आइटम बनाते हैं:
हम सभी को बदलने की जरूरत है
QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData);
साथ में
void paint(QPainter *painter);
और, QQuickPaintedItem जगह QQuickPaintedItem से हमारे वर्ग को QQuickPaintedItem बदले QQuickItem । यहाँ हमारे पेंटिंग समारोह है:
void QQuickCustomItem::paint(QPainter *painter)
{
QPainterPath path;
path.moveTo(width() / 2, 0);
path.lineTo(width(), height());
path.lineTo(0, height());
path.lineTo(width() / 2, 0);
painter->fillPath(path, m_color);
}
बाकी सब कुछ अपरिवर्तित रहता है।