views:

393

answers:

4

What is the best way to "swap" one QGraphicsWidget with another in an existing view? I have a tree view widget and a label widget, and I want them to occupy the same space at different times. Specifically, when there's an error, I want to show it in the label, and when there's no error, I want to show the tree.

I have tried programmatically hiding one and showing the other with hide() and show(), but the problem is that the hidden widget occupies space in my QGraphicsLinearLayout even when it's hidden, leaving an empty gap. Alternatively, I suppose I could add and remove the widgets from the layout, but that seems heavy-handed since it implies a change in ownership of the widgets and I'd need to record their position in the layout so I could insert them back in the right place.

In Java Swing, I'd use a CardLayout to achieve this, but I don't see an equivalent in Qt.

UPDATE: I discovered QStackedWidget. However, I am working with a QGraphicsScene and so my widgets don't inherit from QWidget but rather QGraphicsWidget, so I can't add them to a QStackedWidget.

A: 

When you add a QWidget to a layout, the layout's owner will not take ownership of your widget. You have to add your widget as child of an other QWidget for that (Generally pass the parent in the constructor of the child).

So removing a widget from the lyout will only remove it from the display behaviour of the layout's owner.

In your case you can remove the widget from the layout and hide it. If you want to display it again, show it and add the widget to the layout. To insert it at the right place you have to save its place when removing it.

Hope that helps

Patrice Bernassola
You're bit wrong about the ownership of widgets in layout - all children are automatically reparented when layout is installed on the widget through setLayout method. So you don't need to specify parent for children widgets.
chalup
This is basically the "heavy-handed" approach I described in the question. I'm hoping for something a little more straightforward. (I think chalup is right on the ownership issue. The doc for QGraphicsLinearLayout.removeAt says ownership is transferred to the caller.)
Rob H
Have you tried to use a custom Layout in which hidden widgets will be ignored during positionning? This can do the trick.
Patrice Bernassola
A: 

How about QStackedWidget? http://doc.trolltech.com/qstackedwidget.html

Ben
On first pass, that does seem like the ideal solution. But I am working with a QGraphicsScene and my widgets don't inherit from QWidget but rather QGraphicsWidget, so I can't add them to a QStackedWidget. I will update the question to make that clear.
Rob H
+1  A: 

You can fairly easily emulate a QStackedWidget on your own. Create your own widget (however you want to, either from QWidget or from QGraphicsWidget and put it where you want the two different widgets to appear. Put your widgets in there, and allow it to control which one is visible. With a little work, you could even make it generic enough to be used as a QGraphicsWidget version of QStackedWidget.

Caleb Huitt - cjhuitt
How is this different from my first attempt of calling hide() and show() on the widgets? The problem is the empty gap left in the layout where the hidden widget resides.
Rob H
@Rob H: The difference is that in this case you have one widget occupying the space in your linear layout. That one widget changes what it is showing, which shouldn't affect the spacing of anything around it. I left implied that the widget containing the two others shouldn't use a layout, but merely position both of the others where they should be, and show/hide each one as appropriate.
Caleb Huitt - cjhuitt
Ahh, now I get it. +1 for an interesting idea, although I think I am going to go with the anchor layout answer if I can make it work.
Rob H
+1  A: 

There is something called QGraphicsAnchorLayout. You define "anchors" (the distances between edges or corners of items), so you can try defining the same anchors for your tree and label and hiding the widgets appropriately. Since both widgets will occupy the same area, there should be no gap after hiding one item.

chalup
Hmm... I will look into that and report back. Thanks for the pointer!
Rob H