1

I have this summarized code to display tabs in a notebook in Gtk. Basically, I have created a custom struct with a embedded label, that is added to the notebook. After that, I want to get back that custom widget, but I get a Invalid type assertion. I have read a lot about structs and interfaces, but I can't get it to work.

package main

import "github.com/gotk3/gotk3/gtk"

type NotebookPage struct {
    gtk.Label
}


func main() {

    gtk.Init(nil)

    win, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)

    notebook, _ := gtk.NotebookNew()
    win.Add(notebook)

    content1, _ := gtk.LabelNew("Content 1")
    page1 := NotebookPage{Label: *content1}
    label1, _ := gtk.LabelNew("Label 1")
    notebook.AppendPage(&page1, label1)

    content2, _ := gtk.LabelNew("Content 2")
    page2 := NotebookPage{Label: *content2}
    label2, _ := gtk.LabelNew("Label 2")
    notebook.AppendPage(&page2, label2)

    win.ShowAll()
    win.Connect("destroy", func() {
        gtk.MainQuit()
    })

    backwidget1, _ := notebook.GetNthPage(0)
    backpage1, _ := backwidget1.(*NotebookPage)

    gtk.Main()

}
Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
okelet
  • 716
  • 1
  • 8
  • 23
  • What is the full error you receive? – Kenny Grant Oct 24 '17 at 14:02
  • At compile time, test.go:35: invalid type assertion: backwidget1.(*NotebookPage) (non-interface type *gtk.Widget on left) – okelet Oct 24 '17 at 14:16
  • 1
    Type assertions only work on interface types. `.()` or `.()`. You can't type-assert a concrete type to another type, interface or otherwise. From the error message, it appears that `backwidget1` is a concrete type (a struct, most likely), not an interface, so your type-assertions are invalid. Also, as an aside, you're not checking the boolean second value of your type assertions (the `_`), which would tell you if the type assertion succeeded. If it didn't, `backpage1` will be nil. You should really check that boolean value. – Kaedys Oct 24 '17 at 15:28
  • Thanks all for your help; I usually code in Python and Java, but interfaces and structs are very different in Go. I'll try to find a workaround. – okelet Oct 25 '17 at 06:39

1 Answers1

1

Looks like your problem is here on line 35 as the message says:

backpage1, _ := backwidget1.(*NotebookPage)

notebook.GetNthPage returns a *Widget, *NotebookPage is not a *Widget, so you're not allowed to cast to it. If the function didn't return a concrete type (if it returned the same IWidget interface), and if it didn't roundtrip through gtk C libraries, you could do this.

As it is if you want to get your custom widget back you probably need to get at the underlying gtk widget or serialisation (which presumably stores your custom label), extract the label and build a new NotebookPage.

So you need something like :

func NewNotebookPage(widget *Widget) {
   return &NotebookPage{Label: widget.GetLabelSomehow()}
}

It looks like Label is also a widget :) This is painful because it's trying to work with C++ inheritance in Go. You'll have to find out how to unfreeze your label from the widget.C.GtkWidget

Kenny Grant
  • 9,360
  • 2
  • 33
  • 47