therecipe / qt

Qt binding for Go (Golang) with support for Windows / macOS / Linux / FreeBSD / Android / iOS / Sailfish OS / Raspberry Pi / AsteroidOS / Ubuntu Touch / JavaScript / WebAssembly
GNU Lesser General Public License v3.0
10.49k stars 748 forks source link

QGraphicsItem couldn't be subclassed #681

Open frubi opened 6 years ago

frubi commented 6 years ago

I want to "subclass" QGraphicsItem to create my own graphics item. Here is the skeleton of the application:

package main

import (
    "os"
    "fmt"
    "github.com/therecipe/qt/core"
    "github.com/therecipe/qt/gui"
    "github.com/therecipe/qt/widgets"
)

type CustomGraphicsItem struct {
    widgets.QGraphicsItem
    _ func() `constructor:"init"`
}

func (i *CustomGraphicsItem) init() {
    i.ConnectPaint(i.paint)
    i.ConnectBoundingRect(i.boundingRect)
}

func (i *CustomGraphicsItem) boundingRect() *core.QRectF {
    return core.NewQRectF4(-10, -10, 20, 20)
} 

func (i *CustomGraphicsItem) paint(painter *gui.QPainter, item *widgets.QStyleOptionGraphicsItem, widget *widgets.QWidget) {
}

func main() {
    app := widgets.NewQApplication(len(os.Args), os.Args)

    // window setup omitted

    scene := widgets.NewQGraphicsScene(nil)
    view := widgets.NewQGraphicsView(nil)

    i := NewCustomGraphicsItem(nil)

    scene.AddItem(i)
    view.SetScene(scene)
    widget.Layout().AddWidget(view)

    window.Show()
    app.Exec()
}

The application won't compile, because the moc code for NewCustomGraphicsItem is not generated. After digging through the source code of qtdeploy, I found a call to IsSubClassOfQObject(). QGraphicsItem is not a subclass of QObject, so no moc code is generated.

What is the right way to create a custom graphics item?

Greetings Frubi

therecipe commented 6 years ago

Hey

You can subclass a QObject instead and then make the QGraphicsItem an anonymous field to work around this.

Something like this should work:

package main

import (
    "os"

    "github.com/therecipe/qt/core"
    "github.com/therecipe/qt/gui"
    "github.com/therecipe/qt/widgets"
)

type CustomGraphicsItem struct {
    core.QObject
    *widgets.QGraphicsItem
    _ func() `constructor:"init"`
}

func (i *CustomGraphicsItem) init() {
    i.QGraphicsItem = widgets.NewQGraphicsItem(nil)
    i.ConnectPaint(i.paint)
    i.ConnectBoundingRect(i.boundingRect)
}

func (i *CustomGraphicsItem) boundingRect() *core.QRectF {
    return core.NewQRectF4(-10, -10, 20, 20)
}

func (i *CustomGraphicsItem) paint(painter *gui.QPainter, item *widgets.QStyleOptionGraphicsItem, widget *widgets.QWidget) {
    painter.SetPen(gui.NewQPen3(gui.NewQColor2(core.Qt__blue)))
    painter.DrawRect(i.BoundingRect())
}

func main() {
    app := widgets.NewQApplication(len(os.Args), os.Args)

    window := widgets.NewQMainWindow(nil, 0)

    scene := widgets.NewQGraphicsScene(nil)
    view := widgets.NewQGraphicsView(nil)

    i := NewCustomGraphicsItem(nil)

    scene.AddItem(i)
    view.SetScene(scene)
    window.SetCentralWidget(view)

    window.Show()
    app.Exec()
}
frubi commented 6 years ago

Hi,

it works like a charm!

Thank you Frubi

yshurik commented 6 years ago

QObject for every QGraphicsItem will be heavy for memory usage :(