views:

60

answers:

2

Hi,

I have a QGraphicsItem (actually, a QDeclarativeItem) and I want it to take up the entire visible space of the QGraphicsView (again, its actually the derived QDeclarativeView class) to which it was added. Normally, you can use QDeclarativeView::setResizeMode(QDeclarativeView::SizeRootObjectToView) and QDeclarativeView will automatically resize the root object to fit the view.

The problem I'm having is that I am manually creating the root widget using

QDeclarativeComponent component(declarativeView->engine(), QUrl(qml));
QDeclarativeItem* object = qobject_cast<QDeclarativeItem*>(component.create());
if (object)
{
    declarativeView->scene()->addItem(object);
    ...

instead of letting QDeclarativeView do it automatically by calling setSource(). The reason I'm doing this is because I want to swap the QML scene when certain events occur, but I don't want to destroy the previous scene. Calling setSource() deletes all items that were added before setSource() is called. So, instead I'm creating the "root object" myself and adding it to the scene manually.

I am using the windows resizeEvent to resize my QDeclarativeItem, like this:

void AppWindow::resizeEvent (QResizeEvent* event)
{
    QDeclarativeItem* object = sceneCache.value(sceneName, 0);
    if (object)
    {
        object->setWidth(declarativeView->viewport()->width());
        object->setHeight(declarativeView->viewport()->height());
    }
}

This does work! But, its not very pretty. If you resize the window quickly, the QDeclarativeItem is not resized quickly enough and you briefly see a gray background before it catches up and resizes it. Its also not very smooth.

This only happens if I have a complex item being resized (in my case, its a QWebKit widget). It works fine for simpler items. The thing is, however, that if I let QDeclarativeView do it, I have neither of these problems: its resized correctly and smoothly.

I imagine this is not specific to the QtDeclarative stuff, but rather QGraphicsView, though maybe I'm wrong there.

Does anyone have any ideas?

+1  A: 

I am not sure if this will get rid of the flickering but you can use fitInView in your resizeEvent():

declarativeView->fitInView(object, Qt::IgnoreAspectRatio);
Stephen Chu
Thanks for that, I seem to have missed that function.
Dan
+1  A: 

I have solved my problems.

The problem seems to be with QML's WebView element. I switched it out for a QGraphicsProxyWidget registered from C++, with the widget set to a normal QWebView and all the problems disappear. It now behaves exactly how I expected the WebView to behave.

The downside is that I need to manually expose the QWebView signals/slots/properties to QML. (EDIT: I've solved this by having a read-only property called object, which returns the set widget. Since QObjects are automagically converted to javascript accessible objects, I can access the web view, for exmaple, like this: object.url = 'http://google.com'. For convenience, I also invoke an init javascript function ont he QML object, if it exists, so I simply set the web view up there - works great!)

Another change I made since I asked the question is to move the "root object" switching from C++ into QML itself, by creating a fullscreen Rectangle with a C++ -callable javascript function that uses Qt.createComponent() to load the "actual" QML file and anchor it with anchors.fill. This way the logic (and caching of objects) is done in QML, instead of C++, so I can simply setSource(), let Qt handle resizing and such and I work purely in QML (for this part of the app, anyway).

Dan