PDA

View Full Version : Focus/Activation problem for widget in nested QGraphicsScenes



peers
3rd May 2012, 16:12
Hi,

I've got an editable QComboBox which I put into a QGraphicsScene. The graphics scene gets visualised by a QGraphicsView which itself gets added to another QGraphicsScene. This second graphics scene gets again visualised by a second QGraphicsView. (see code below)

I've got a few issues with this configuration:

1. I have to set the cache mode to ItemCoordinateCache or DeviceCoordinateCache in order to see the drop down list of the combo box. Not a major issue so far, but why is this necessary?

2. When hoovering with the mouse over the edit field of the combo box then I expect the mouse cursor to change into the caret symbol, this does not happen.

3. When clicking once into the edit field the text caret does not appear, typing however changes the text, so the edit field 'somehow' gets the keyboard events.

Has anyone any idea what I have to do so that the combo box behaves as if it would be added directly into the outer scene? Any idea or suggestion is welcome and appreciated.

Following the sourcecode which shows the described behaviour. This is just a simplified example of what I want to do. Later I want to use all kind of other widgets and dialogs for where I use the combo box at the moment.


#include <QApplication>
#include <QComboBox>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsProxyWidget>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);

QComboBox* combo = new QComboBox();
combo->addItem("First");
combo->addItem("Second");
combo->setEditable(true);
combo->setObjectName("the combo box");

// Create the outer scene and view, it may contain several 'inner' graphics
// views and scenes.
QGraphicsScene* outerScene = new QGraphicsScene();
outerScene->setObjectName("the outer scene");
QGraphicsView* outerView = new QGraphicsView(outerScene);
outerView->setObjectName("the outer view");

// The outer graphics view is our 'main window'
outerView->show();

// if set to 0 then the combo box gets added directly into the outer scene,
// if set to 1 then the combo box gets added into a graphics scene which
// gets visualised by a graphics view added to the outer scene.
if (0)
{
// In this scenario we add the combo box into the outer scene.
outerScene->addWidget(combo);
}
else
{
// In the second scenario we add another QGraphicsScene and QGraphicsView,
// the inner scene and inner view. The inner view gets added to the outer
// scene using a QProxyWidget. The combo box now gets added to this inner
// scene.
// Adding the combo box to its 'own' scene allows us to do all kind of
// funny things like scaling, rotation, etc.

QGraphicsScene* innerScene = new QGraphicsScene();
innerScene->setObjectName("the inner scene");
QGraphicsView* innerView = new QGraphicsView(innerScene);
innerView->setObjectName("the inner view");

QGraphicsProxyWidget* innerViewProxy = outerScene->addWidget(innerView);
innerViewProxy->setObjectName("the inner view proxy");

QGraphicsProxyWidget* proxy = innerScene->addWidget(combo);
proxy->setObjectName("the combo proxy");

// Seems like we have to set the cache mode to Item or DeviceCorrdinateCaching
// in order to see the drop down list.
proxy->setCacheMode(QGraphicsItem::ItemCoordinateCache);
//proxy->setCacheMode(QGraphicsItem::DeviceCoordinateCache) ;

innerScene->setActiveWindow(proxy);

// Turn the combo box upside down and scale it a bit. It gets rotated and
// scaled independent of objects in the outer scene, Nice!
innerView->scale(2.0, 2.0);
innerView->rotate(180.0);
}

return a.exec();
}


Thank You!
Peer

Spitfire
9th May 2012, 14:08
I would question your approach. To me it seems very wrong.

You don't need scene in the scene to be able to manipulate widgets.
You can do whatever you want to the proxy object.



// part of your example:
if(1)
{
// In this scenario we add the combo box into the outer scene.
QGraphicsProxyWidget* proxy = outerScene->addWidget(combo);
proxy->rotate( 90 );
proxy->scale(2.0, 2.0);
}

This will do all you want (I'm guessing) without issues you're having.

Unless there's another reason why you do the nesting but I can't see anything convincing.

peers
9th May 2012, 15:54
Thanks a lot for your reply Spitfire.

I missed that I can do the transformations on the proxy, thanks for telling me about it.

However this solves only one part of what I want to do. I also need to display several items painting using OpenGL, and I need to display them in parallel. Because I cannot add QGLWidgets to a proxy, I have to use several scenes, one for each OpenGL item. All items, OpenGL and 'normal' items have to appear in the same scene at the end.

If you know about a better way of getting what I need then I would love to here about it ;)

Spitfire
9th May 2012, 16:36
I know almost nothing about OpenGL, but the first thing that springs to my mind is: use OpenGL only :)
You should be able to add any widget to gl scene and render it in single view.

Like I've said - I've never done it, but maybe this (http://doc.qt.nokia.com/qq/qq26-openglcanvas.html) article will help you.

peers
9th May 2012, 16:54
You should be able to add any widget to gl scene and render it in single view.

Like I've said - I've never done it, but maybe this (http://doc.qt.nokia.com/qq/qq26-openglcanvas.html) article will help you.

What do you mean with single view?

I know that article, however as I understood it I can only render one openGL scene per graphics scene. But because I need to show several openGL scenes at once I think I need more than one graphics scene. And because I would like to handle these 'inner' scenes like any QGraphicsItem (thats why I add the associated views to the outer scene via a proxy) I need the 'nested' scenes.

Thanks anyway :)

Spitfire
10th May 2012, 12:49
What I can't figure out is why you need many scenes?
It doesn't seem right to me.

From what I see you want to have gl and q items and widgets in a scene.
have signle gl scene, add what you want to it and that's it. Where you get other scenes? Is it imposed on you?
If you want to manipulate group of elements together, create a widget from that elements, or group them together, or use layout in the scene.

You didn't say what you're trying to do but I'm guessing that nested scenes will be troublesome in many ways and you should think about different solution.

Anyway, good luck :)

peers
11th May 2012, 12:05
I am working on a system which has to display measurement data. This data is of different kind, curves, images, etc., some of it we visualise using OpenGL. The reason for several OpenGL scenes is that we display data from multiple sources in parallel, sometimes we display data from one source in more than one scene because the visualisation of the same data can be done different to see different things in it. This is the motivation for wanting to have different OpenGL scenes in an 'outer' scene.

The Graphics Scene/View framework provides all the flexibility we need now and it provides enough flexibility for what we want in the future, that is why, at the moment, I try to find out how we can realise our current application using this framework. The only problem I have so far is the described problem with multiple OpenGl scene.

What I am doing now is to evaluate whether we really need OpenGL. Before we needed it because we had to display image data with a high update rate. The system was designed and first developed almost 10 years ago, that time OpenGL was what we needed. Now, however, I think we could get away with using a QImage as off buffer and then, in the paint routine of a QGraphicsItem, paint modified parts of the QImage. So far my first tests are promising.

Regards
Peer