It required small effort to embed QWidget derived class to QML scene. Still its not great effort and its also vary straigt forward.
All you need to do is, create new class derived from QDeclarativeItem. Create instance of required widget and add that widget to QGraphicsProxyWidget. Now we need to register this newly created class to QML using qmlRegisterType. Now we can use this class from QML which display our QWidget derived class.
Following is code that demonstrate the same. For demo I have created class which embed QLabel to QML scene.
Following code is my custom QDeclarativeItem derive class which will expose QLabel to QML scene.
#include <QDeclarativeItem> class QLabel; class QmlLabel : public QDeclarativeItem { Q_OBJECT Q_PROPERTY(QString text READ text WRITE setText) public: explicit QmlLabel(QDeclarativeItem *parent = 0); ~QmlLabel(); public slots: void setText(const QString& text); QString text() const; private: QLabel* mLabel; QGraphicsProxyWidget* mProxy; };
#include <QLabel> #include <QGraphicsProxyWidget> QmlLabel::QmlLabel(QDeclarativeItem *parent) : QDeclarativeItem(parent) { mLabel = new QLabel(QString("")); mProxy = new QGraphicsProxyWidget(this); mProxy->setWidget(mLabel); } QmlLabel::~QmlLabel() { delete mLabel; } void QmlLabel::setText(const QString& text) { mLabel->setText(text); } QString QmlLabel::text() const { return mLabel->text(); }
Following code demonstrate how to register above class to QML. In qmlRegisterType first argument is component uri, which is used for importing component to QML. second and third argument is version information and fourth argument is element name in QML, By using this name we can created QML element.
#include <QtDeclarative> int main(int argc, char *argv[]) { QApplication app(argc, argv); qmlRegisterType<QmlLabel>("qmlLabel", 1, 0, "QmlLabel"); QDeclarativeView viewer; viewer.setSource(QUrl("qml/hybrid/main.qml")); viewer.show(); return app.exec(); }
Finally following is QML code. To be able to use our custom QML element we need to import component to QML using import statement.
import QtQuick 1.0 import qmlLabel 1.0 Rectangle { width: 360 height: 360 QmlLabel { x:100; y:100 text: "QML Label" } }
Following is out put from above code.
Thanks a ton!
ReplyDeletewelcome :)
ReplyDeleteThanks.. It was really helpful....
ReplyDeleteThanks, quite helpful.
ReplyDeleteThank you, I'll try this later, it's exactly what I need :)
ReplyDeleteThank you so much.
ReplyDeleteIt is the one I am ever looking for.
It save my days.
Many many thanks.
my qwidget draw lines with data points coming from a data source, I override paintEvent and used QPainter to drawLine. Most of the time it works fine but when there's an update on the other QML elements (or refresh), the lines either dissappear or disconnected.
ReplyDeleteCan you provide your source code, I will try for solution.
ReplyDeleteThank you!
ReplyDeleteBy the way, with this qml code (C++ classes are same):
Rectangle {
width: 360
height: 360
QmlLabel {
id: mylabel
x:100; y:100
text: "QML Label"
}
MouseArea {
anchors.fill: parent
onClicked: { mylabel.setText(mouseX + " " + mouseY); }
}
}
just after start I see wery short label, only a left half of letter 'Q'.
After first click I see label with width (gray field) enought to fit coordinates, but only with firt sybmol printed. After third click (especially at another place, string with coordinates must be changed) at last I see all string.
Please, can you explain?
What I should do to automatic repaint scene after all items were built?
Make sure you give a width and height for QmlLabel in your qml file
DeleteI think you need to call update after set text, but let me try what you are doing and will update the post.
ReplyDeleteAlso try this variant:
ReplyDelete#ifndef QMLLABEL_H
#define QMLLABEL_H
#include
class QLabel;
class QmlLabel : public QGraphicsProxyWidget
{
Q_OBJECT
Q_PROPERTY(QString text READ text WRITE setText)
public:
explicit QmlLabel(QGraphicsProxyWidget* parent = 0);
~QmlLabel();
public slots:
void setText(const QString& text);
QString text() const;
private:
QLabel* mLabel;
};
#endif // QMLLABEL_H
#include "qmllabel.h"
#include
QmlLabel::QmlLabel(QGraphicsProxyWidget* parent)
: QGraphicsProxyWidget(parent)
{
mLabel = new QLabel(QString(""));
mLabel->setAttribute(Qt::WA_NoSystemBackground);
setWidget(mLabel);
}
QmlLabel::~QmlLabel()
{
}
void QmlLabel::setText(const QString& text)
{
mLabel->setText(text);
}
QString QmlLabel::text() const
{
return mLabel->text();
}
I was wondering before trying that would it work for my complex custom widget(a spectrum visualizer).
ReplyDeleteAfter trying, it worked perfectly .
I would say it's simpler than other methods available.
Thanks a lot! :)
Thank you for your comment :), I am glad it helped you.
Delete