Search code examples
juliagtkgtk.jl

how can I modify the content of GtkListStore inside a Composed Widgets after its initialisiation in julia?


I want to use GTK in a Julia program to display a list of properties that changes over time. I am now to both GTK and Julia

I tried to combine the tutorial for composed widgets with the one for liststore, but that didn't work, since I get errors when I try to access the ListStore from outside the struct.

For my specific purpose I don't even need to push to the listStore. It would be enough if I could modify rows that are already there. Also I am still in an early stage of development, so I am still be able to change to another gui-framework, so recommendations are also appreciated.

The following works, as I long as I don't try to access myListStore.

using Gtk

mutable struct CustomStore <: Gtk.GtkListStore
    handle::Ptr{Gtk.GObject}
    listStore
    # listStore::Gtk.GtkListStoreLeaf
    # listStore::Ptr{Gtk.GObject}

    function CustomStore()
        container = GtkBox(:v)
        infoLabel= GtkLabel("container")
        push!(container, infoLabel)

        listStore = GtkListStore(String, Int)
        push!(listStore,("aaa",123))
        push!(listStore,("bbb",234))

        print("typeof(listStore): ")
        println(typeof(listStore)) # typeof(listStore): GtkListStoreLeaf

        tv = GtkTreeView(GtkTreeModel(listStore))
        rTxt = GtkCellRendererText()
        c1 = GtkTreeViewColumn("Name", rTxt, Dict([("text",0)]))
        c2 = GtkTreeViewColumn("Value", rTxt, Dict([("text",1)]))
        push!(tv, c1, c2)
        push!(container,tv)
        push!(listStore,("ccc",345))

        print("typeof(listStore): ")
        println(typeof(listStore)) # typeof(listStore): GtkListStoreLeaf

        return Gtk.gobject_move_ref(new(container.handle), container)
    end
end

function main()
    win = GtkWindow("My First Gtk.jl Program", 800, 600)
    myStore = CustomStore()
    push!(win, myStore)
    showall(win)
      
    # Some things I tried but yielded errors:
    # myListStore::GtkTreeStore = getproperty(myStore, :ts) 
    # myListStore::GtkListStoreLeaf = getproperty(myStore, :ts) 
    # myListStore = get_gtk_property(myStore,:ts,String) 

    myListStore = getproperty(myStore, :ts)
    print("typeof(myListStore): ")
    println(typeof(myListStore)) # typeof(myListStore): Gtk.GLib.FieldRef{CustomStore}


    println("Here is what my goal is: Modifying the listStore after the custom widget has been initialized: ")
    # push!(myListStore,("zzz",999))
    # --> ERROR: LoadError: MethodError: no method matching push!(::Gtk.GLib.FieldRef{CustomStore}, ::Tuple{String, Int64})
    # Closest candidates are:
    #   push!(::Any, ::Any, ::Any) at /opt/julia-1.7.2/share/julia/base/abstractarray.jl:2952
    #   push!(::Any, ::Any, ::Any, ::Any...) at /opt/julia-1.7.2/share/julia/base/abstractarray.jl:2953
    #   push!(::GtkTreeStore, ::Tuple) at ~/.julia/packages/Gtk/B6LVT/src/lists.jl:224
    
    
    if !isinteractive()
        @async Gtk.gtk_main()
        Gtk.waitforsignal(win,:destroy)
    end    
end

main()

Solution

  • In your constructor you should return the new() struct as you declared it: a handle and a list store.

    You also sometimes need to update the window after you change the listing. Hiding and showing the window should do this:

    using Gtk
    
    mutable struct CustomStore <: Gtk.GtkListStore
        handle::Ptr{GObject}
        listStore::GtkListStoreLeaf
        function CustomStore()
            container = GtkBox(:v)
            infoLabel= GtkLabel("container")
            push!(container, infoLabel)
    
            listStore = GtkListStore(String, Int)
            push!(listStore,("aaa",123))
            push!(listStore,("bbb",234))
    
            print("typeof(listStore): ")
            println(typeof(listStore)) # typeof(listStore): GtkListStoreLeaf
    
            tv = GtkTreeView(GtkTreeModel(listStore))
            rTxt = GtkCellRendererText()
            c1 = GtkTreeViewColumn("Name", rTxt, Dict([("text",0)]))
            c2 = GtkTreeViewColumn("Value", rTxt, Dict([("text",1)]))
            push!(tv, c1, c2)
            push!(container,tv)
            push!(listStore,("ccc",345))
    
            print("typeof(listStore): ")
            println(typeof(listStore)) # typeof(listStore): GtkListStoreLeaf
    
            return Gtk.gobject_move_ref(new(container.handle, listStore), container)
        end
    end
    
    function main()
        win = GtkWindow("My First Gtk.jl Program", 800, 600)
        myStore = CustomStore()
        push!(win, myStore)
        showall(win)
    
        println("Here is what my goal is: Modifying the listStore after the custom widget has been initialized: ")
        push!(myStore.listStore,("zzz",999))
        hide(win)
        show(win)
    
        if !isinteractive()
            @async Gtk.gtk_main()
            Gtk.waitforsignal(win,:destroy)
        end
    end
    
    main()