PDA

View Full Version : Custom QGraphicsItem - Adding a QListWidget



El Bazza
12th September 2012, 09:42
I've created a custom QGraphicsItem, inheriting from QGraphicsRectItem, to be precise. This custom class contains (at the moment) two other QGraphicsRectItems, one bounding a QGraphicsTextItem as a holder for a Name, and the other QGraphicsRectItem is added to act as a placeholder for a List of information. So far, so good...

I've tried to add a QListWidget, but cannot get list information to display correctly within the bounds of the QGraphicsRectItem that I've set as its parent.

I know I'm doing something wrong, and perhaps what I'm attempting isn't really possible with QGraphicsScene/QGraphicsView?

Either way, if anyone can steer me in an appropriate direction, I'd be most grateful!

Using Qt Creator 1.3.1, Qt 4.6.2.

wysota
12th September 2012, 10:25
Where did you try to add QListWidget? Why did you inherit the item class instead of just composing items using parent-child relationship?

El Bazza
12th September 2012, 10:44
It's probably easier if I add code snippets to show what I've done:

Header File Info:


class CommunityDisplay : public QGraphicsRectItem
{
// Attributes
public:

protected:
QListWidget *m_pListView;

private:
QGraphicsRectItem *m_pNameRectItem;
QGraphicsRectItem *m_pListRectItem;
QGraphicsTextItem *m_pName;

//Methods
public:
CommunityDisplay(QGraphicsScene *pParentScene,
qreal xPos,
qreal yPos,
QString strName);

};

Source Code for the Constructor


CommunityDisplay::CommunityDisplay(QGraphicsScene *pParentScene,
qreal xPos,
qreal yPos,
QString strName)
{
// Set up the Outer Rectangle for the shape
setRect(xPos, yPos, 225.0, 250.0);
QRectF Rect = rect();
QPoint point;

// Set up the inner QGraphicsRectItem for the Name area
m_pNameRectItem = new QGraphicsRectItem(this, pParentScene);
m_pNameRectItem->setRect(Rect.x() + 5.0,
Rect.y() + 5.0,
Rect.width() - 10.0,
45.0);

// Set up the inner QGraphicsRectItem for the List
m_pListRectItem = new QGraphicsRectItem(this, pParentScene);
m_pListRectItem->setRect(Rect.x() + 5.0,
Rect.y() + 55.0,
Rect.width() - 10.0,
Rect.height() - m_pNameRectItem->rect().height() - 15.0);

// Set up the Name Text Item
m_pName = new QGraphicsTextItem(strName, this, pParentScene);
m_pName->setPos(m_pNameRectItem->rect().x() + 5.0,
m_pNameRectItem->rect().y() + 2.0);

// Set up the List Widget within the bounds of its QGraphicsRectItem
m_pListView = new QListWidget(dynamic_cast<QWidget *>(m_pListRectItem));
m_pListView->setBaseSize(m_pListRectItem->rect().width() - 4,
m_pListRectItem->rect().height() - 4);

m_pListView->setViewMode(QListView::ListMode);
m_pListView->setFlow(QListView::TopToBottom);
m_pListView->setSelectionMode(QListView::SingleSelection);
// m_pListView->setViewport(dynamic_cast<QWidget *>(m_pCryptosListRectItem));
point.setX((int)(m_pCryptosListRectItem->rect().x() + 2));
point.setY((int)(m_pCryptosListRectItem->rect().y() + 2));
m_pListView->mapToParent(point);
m_pListView->setEnabled(true);
m_pListView->setShown(true);
m_pListView->setVisible(true);

// DEBUG Attempt to see if the list widget will be displayed
m_pListView->addItem("Unit1");

setActive(true);
setEnabled(true);
setFlag(QGraphicsItem::ItemIsMovable);
setFlag(QGraphicsItem::ItemIsSelectable);
}

Hope this helps to clarify what I'm trying to do.

PS I know that adding an item to the list widget in the constructor of the class is naughty, I'm just doing it to make sure the list view is actually visible, and I'll concentrate on adding items to the list correctly once I can get it inside the rectangle it's supposed to be in

wysota
12th September 2012, 11:57
So what exactly is the problem?

El Bazza
12th September 2012, 12:53
It's easier if I draw a picture to explain what's happening.

What I want is something like this:

8216

with the QListWidget inside the lower of the two inner QGraphicsRectItems.

What I get is the basic graphics classes drawing on the View OK, but the QListWidget is in a window of its own, in a different location, not attached to the inner rectangle. Something like this:

8217

Obviously, I've done something wrong, but I'm not exactly sure what. Hope this helps to clarify my problem.

wysota
12th September 2012, 13:13
You are not adding the list widget to the scene anywhere. And you certainly cannot pass a QGraphicsRectItem as a parent to QListWidget since the former is not a widget at all (dynamic_cast will return 0 here).

El Bazza
12th September 2012, 14:18
The code snippets I've provided don't show the addition of the Custom CommunityDisplay Class to the scene. That is done elsewhere, and pointers to the created CommunityDisplay class are added to the scene using QGraphicsScene::addItem.

I'd assumed that the QListWidget internal to the custom class would have been added to the scene with the scene.add(customclass) call I'm doing. Is this not the case?

I'd also suspected that I couldn't force the QGraphicsRectItem to be a parent to the QListWidget, so thanks for confirming that - I'll remove that. I would also guess that the main reason that the QListWidget is being displayed in its own window is that the mapToParent method won't work when the parent was invalid (0, as you pointed out in the previous reply).

I'm still a little stumped as to how to get the List to display within the custom class on the scene. Any further thoughts?

EDIT: Actually, you're absolutely right about not having added the QListWidget to the scene - all the other graphics items within the custom class have the parent scene passed in the constructor when they're newed. However, that still doesn't fix the problem, as I'm not sure there's a valid way of adding the widget to the scene, as scene.addItem requires a QGraphicsItem pointer, and I won't be able to dynamic_cast it to QGraphicsItem * from QWidget * in the same way as I couldn't dynamically cast in the opposite direction...
So, I guess the question is: Is it actually possible to add a QListWidget (or QListView) to a QGraphicsScene?

wysota
12th September 2012, 15:45
The code snippets I've provided don't show the addition of the Custom CommunityDisplay Class to the scene.
You don't understand. You are not adding the list widget object to the scene. It doesn't have a parent (as I explained in the previous post) and thus is not tied to the scene in any way and shows up as a separate window.

Have a look at QGraphicsProxyWidget class to see how to add a widget to a scene. However be prepared for major slowdowns if you intend to animate the item. Widgets are not supposed to be placed on graphics scenes.

El Bazza
12th September 2012, 16:19
Thanks wysota, I realised that after I'd posted the reply, hence the edit :)

Thanks also for the pointer to QGraphicsProxyWidget, I think I see how it should all work now. The QListWidget remains in the custom class, along with a pointer to a QGraphicsProxyWidget, which is used to display the information held within the QListWidget

EDIT: I've just checked the basics of the principle, and I now have a List Widget inside my Graphics Scene. Thanks once again, wysota :)