PDA

View Full Version : qwidget into QML



Le_B
7th March 2011, 13:15
hi all,

I'm trying to put a treeview in my QML application.
The last thing i was trying was to put a qwidget (QTreewidget) into my QML file.
so i used qmlRegisterType, and have :

import QtQuick 1.0
import Test 1.0

Rectangle {
id:ttt
width: 360
height: 360
CustomTree{
id:customW
parent:ttt
// anchors.fill: parent
}
}

as my QML file but nothing happens
can someone help me ?

wysota
7th March 2011, 14:21
Did you implement a subclass of QDeclarativeItem for yout widget?

Le_B
7th March 2011, 16:40
this is the part i'm not sure of
i create an object subclassed from QDeclarativeItem with
this->setFlag(QGraphicsItem::ItemHasNoContents, false);

my problem is how to paint it. I'm not familiar with the paint() function

wysota
7th March 2011, 17:06
I don't see your point. In my opinion your declarative item should create a tree view, a proxy item for it and set that item as the child of the declarative item. Then you can forward all calls you want from the item to the widget.

Le_B
7th March 2011, 18:00
i must be really @#?! or tired
when i try this

CustomWidget::CustomWidget(QDeclarativeItem *parent) :
QDeclarativeItem(parent)
{
this->setFlag(QGraphicsItem::ItemHasNoContents, false);

tree = new QTreeWidget;
new QTreeWidgetItem(tree, QStringList()<<"First");
new QTreeWidgetItem(tree, QStringList()<<"Second");
new QTreeWidgetItem(tree, QStringList()<<"Third");
new QTreeWidgetItem(tree, QStringList()<<"Fourth");

proxy = new QGraphicsProxyWidget;
proxy->setWidget(tree);
proxy->setParentItem(this);


}

in the constructor of my QDeclarativeItem it doesn't display anything

here is the qml file


import QtQuick 1.0
import Test 1.0

Rectangle {
id:ttt
width: 360
height: 360
CustomTree{
id:customW
anchors.fill:parent
}
}

wysota
7th March 2011, 23:25
This works for me:

#include <QtDeclarative>
#include <QtGui>

class PushButtonItem : public QDeclarativeItem {
Q_OBJECT
public:
PushButtonItem(QDeclarativeItem *parent =0) : QDeclarativeItem(parent) {
pb = new QPushButton("text");
proxy = new QGraphicsProxyWidget(this);
proxy->setWidget(pb);
proxy->setPos(-pb->sizeHint().width()/2, -pb->sizeHint().height()/2);
}
private:
QPushButton *pb;
QGraphicsProxyWidget *proxy;
};


#include "main.moc"

int main(int argc, char **argv) {
QApplication app(argc, argv);
QDeclarativeView view;
qmlRegisterType<PushButtonItem>("PushButton", 1, 0, "PushButtonItem");
view.setSource(QUrl::fromLocalFile("file.qml"));
view.show();
return app.exec();
};

with file.qml:
import Qt 4.7
import PushButton 1.0


Rectangle {
width: 300
height: 300
PushButtonItem {
anchors.centerIn: parent
}
}

Le_B
8th March 2011, 10:57
i had a strange case mismatch warning that i didn't see

anyway, thanks to you i understand it much better

thank you

Le_B
10th March 2011, 16:52
I discovered that you can directly subclass QGraphicsProxyWidget and that works even better for resizing and positioning with QML

keriuonlesmar
26th March 2011, 06:52
the code of third snippet does not understand.

nouch64
6th April 2011, 18:37
Hi,

I used the same way to try to embedded a QX11EmbedContainer into QML but the result is not really good :
My goal is to use the QX11EmbedContainer to execute mplayer and to declare this one as a QML Element to be able to manipulate it into my *.qml files.
The result is, when I execute it, the video is played on a new window and not on my QML window.

Here is the code :



/* videodisplayitem.h */

#include <QDeclarativeItem>
#include <QX11EmbedContainer>
#include <QtDeclarative>
#include <QProcess>
#include <QtGui>

class VideoDisplayItem : public QDeclarativeItem
{
Q_OBJECT
public:
VideoDisplayItem(QDeclarativeItem *parent =0) : QDeclarativeItem(parent) {
container = new QX11EmbedContainer(NULL);

// if I execute container->show(); here, I get the video on a new window
container->show();

QProcess * process = new QProcess(container);
QString executable("/usr/bin/mplayer");
QStringList arguments;
arguments << "-wid";
arguments << QString::number(container->winId());
arguments << "/myvideo.mp4";
process->start(executable, arguments);

proxy = new QGraphicsProxyWidget(this);
proxy->setWidget(container);
proxy->setPos(-container->sizeHint().width()/2, -container->sizeHint().height()/2);

// if I execute container->show(); here, I get nothing visible
// container->show();
}
private:
QX11EmbedContainer *container;
QGraphicsProxyWidget *proxy;

};





/* main.cpp */

#include <QtGui/QApplication>
#include "videodisplayitem.h"

int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QDeclarativeView view;
qmlRegisterType<VideoDisplayItem>("VideoDisplay", 1, 0, "VideoDisplayItem");
view.setSource(QUrl::fromLocalFile("file.qml"));
view.show();
return app.exec();
}




/* file.qml */

import Qt 4.7
import VideoDisplay 1.0

Rectangle {
width: 300
height: 300

VideoDisplayItem {
anchors.centerIn: parent
}
}


If you get any idea or advise, thanks for all.
My way to proceed might be totally wrong but I dont have any other ideas how to do.

Thanks for all.

wysota
6th April 2011, 20:27
It won't work with Embed. Use appropriate API from QtMultimedia instead.

nouch64
7th April 2011, 04:14
Thanks for the answer.
That is not a good news for me as I develop for embedded platform and I have to use a optimized version of MPlayer.
Are there any other possibility using the Qt layouts ?

There is an other thin I can't do for now, it's to display a transparent window over the QX11EmbedContainer, like an overlay..

Thanks for all the advices.

wysota
7th April 2011, 12:05
The thing is that QML is implemented using Graphics View and items in the graphics view are not widgets so XEmbed won't work with them. You can use XEmbed with regular widgets. What exactly do you mean by "optimized" MPlayer? Because video decoding is done not by MPlayer but rather by codecs and Qt's multimedia tools will use the same codecs.

Kung Foo
15th August 2011, 12:50
I'm also trying to embed a QWidget into QML implementation (since there's no proper drawing primitives for QML like QWidget has).
I tried the example wysota provided (the PushButton example above), but I stumbled upon a problem. It seems that resizing or setting the QWidget's size wont work.

I tried:


PushButtonItem {
width: 300
height: 300
anchors.centerIn: parent
}


And also:


PushButtonItem {
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
}


But with no luck :(

So how to set the size of QDeclarativeItem that has a QWidget in it with QML?
Or could this be a bug in the Symbian implementation of QDeclarativeItem?

wysota
15th August 2011, 15:57
Why would it work? Do you understand what my code does? Why would it resize the widget if you resize the declarative item? If you want to modify the widget in any way, you have to provide appropriate code that does that.

Kung Foo
26th August 2011, 13:52
So what do I need to implement? Is there some example that I could use to study how the resize events should be handled from "main QML" -> QDeclarativeItem -> QWidget?

So what do I need to implement? Is there some example that I could use to study how the resize events should be handled from "main QML" -> QDeclarativeItem -> QWidget?

Added after 1 47 minutes:

I tied experimenting a bit.

If I override the geometryChanged() default implementation with this, the resizing events propagate to the QWidget.



void customDeclarativeItem::geometryChanged(const QRectF& newGeometry, const QRectF& oldGeometry)
{
mProxy->setGeometry(newGeometry);
QDeclarativeItem::geometryChanged(newGeometry, oldGeometry);
update();
}


But the size of the widget seems to be wrong, so I'm not doing it right.
Also the widget is not correctly drawn when needed. It worked OK before this, so there's something more I don't yet understand here.

Can anyone help me with this?

So the question is that how to get the QWidget inside a QGraphicsProxyWidget to automatically fill the QGraphicsProxyWidget completely?

Kung Foo
27th August 2011, 19:43
This is starting to sound like a monolog, but lets continue still..
Here's how I got the QWidget-based component to show in correct size:



void RadarItem::geometryChanged(const QRectF& newGeometry, const QRectF& oldGeometry)
{
if (newGeometry != oldGeometry) {
// Solution #1:
// mProxy->resize(newGeometry.width(), newGeometry.height());
// Solution #2:
// mProxy->setGeometry(QRectF(0.0, 0.0, newGeometry.width(), newGeometry.height()));
}
QDeclarativeItem::geometryChanged(newGeometry, oldGeometry);
}


Both resize() and setGeometry() work, but there is now another problem.
When I uncomment either of the solution lines above, the drawing of the widget ceases. The widget automatically redraws itself and it should show immediately on the UI. Now it doesnt, and the changes are only shown after I go to some other view and return back.

How is this possible? How can resize() or setGeometry() cause this?

wysota
27th August 2011, 22:52
Maybe it sounds like a monolog, because I said everything I had to say in the subject. If someone uses some code he doesn't understand, there is nothing more to be said apart "understand the code before using it". If one understands the code and expands on it, he knows more than I do, because I didn't dig into the topic further. My plain simple answer is still the same -- "forward all the calls you want from the item to the widget". If you resize the item and you want the widget to resize as well then do exactly that -- resize the widget when the item is resized.