go-qml / qml

QML support for the Go language
Other
1.96k stars 187 forks source link

segvault: obj.Set("parent", win.Root()) when using ApplicationWindow #31

Closed yoo closed 10 years ago

yoo commented 10 years ago

I get a segvault when try to add QML Objects to an ApplicationWindow from Go. This can be recreated by modifying the rect.qml from the reparent example.

import QtQuick 2.0
import QtQuick.Window 2.0

ApplicationWindow {
    width: 640
    height: 480
    color: "black"
}

The segvault occurs when calling obj.Set("parent", win.Root())

func run() error {
    qml.Init(nil)

    engine := qml.NewEngine()

    base, err := engine.LoadFile("base.qml")
    if err != nil {
        return err
    }
    rect, err := engine.LoadFile("rect.qml")
    if err != nil {
        return err
    }

    win := base.CreateWindow(nil)
    obj := rect.Create(nil)

    obj.Set("parent", win.Root())

    win.Show()
    win.Wait()

    return nil
}

Here is a gdb backtrace. The program breaks when calling QQuickItem::parentItem() on the ApplicationWindow.

#0  0x00007ffff6e83780 in QQuickItem::parentItem() const () from /usr/lib/libQt5Quick.so.5
#1  0x00007ffff6e8ffc0 in QQuickItem::setParentItem(QQuickItem*) () from /usr/lib/libQt5Quick.so.5
#2  0x00007ffff6e91c89 in QQuickItem::qt_metacall(QMetaObject::Call, int, void**) () from /usr/lib/libQt5Quick.so.5
#3  0x00007ffff6fac267 in ?? () from /usr/lib/libQt5Quick.so.5
#4  0x00007ffff59814fb in QMetaProperty::write(QObject*, QVariant const&) const () from /usr/lib/libQt5Core.so.5
#5  0x00007ffff59a56df in QObject::setProperty(char const*, QVariant const&) () from /usr/lib/libQt5Core.so.5
#6  0x0000000000422682 in objectSetProperty (object=0xb5d6b0, name=0x7fffd8000a80 "parent", value=<optimized out>)
labsin commented 10 years ago

It's because ApplicationWindow is a QWindow and not a QQuickItem QWindow has a method setParent(QWindow) but the ApplicationWindow has no property and this has a whole other meaning than that of QQuickItem's parent and also of QObject. Some info: http://qt-project.org/doc/qt-5.0/qtquick/qtquick-visualcanvas-visualparent.html http://qt-project.org/doc/qt-5.1/qtquick/qquickwindow.html

Chances are high you don't want this.

niemeyer commented 10 years ago

@labsin is right: when you use a Window or ApplicationWindow as the root of your QML tree, what you get out of window.Root() is not a QQuickItem, so you cannot set the "parent" property of another QQuickItem to it. That's the reason why it crashes. You can fix your code, as described at the bottom, but there's still a bug here: crashing in such a cryptic way is terrible for such a trivial operation.

This was just fixed on commit 7c2a7c6. Now that erroneous logic will crash the application with the following message:

panic: cannot set property "parent" with type QQuickItem* to value of QQuickWindow*

This should hopefully make the problem more obvious.

So, knowing what's wrong, you can fix your code and keep the Window as the root of the QML code. For example, you can declare the QML code along the lines of:

Window {
    Rectangle {
        objectName: "rect"
    }
}

Then, inside your Go code change the parent with:

obj.Set("parent", win.Root().ObjectByName("rect"))

This should achieve the same result of the original example.