8

I am trying to find the simplest example of a custom widget being written for Gtk-3.

So far the best thing I've found is this (using PyGTK), but it seems to be targeted to Gtk-2.

BTW: I don't care the language it is written in, but if we can avoid C++, much better!

knocte
  • 16,941
  • 11
  • 79
  • 125

3 Answers3

14

Python3 Gtk3 it is, then:

from gi.repository import Gtk

class SuperSimpleWidget(Gtk.Label):
    __gtype_name__ = 'SuperSimpleWidget'

Here is a non-trivial example that actually does something, namely paints its background and draws a diagonal line through it. I'm inheriting from Gtk.Misc instead of Gtk.Widget to save some boilerplate (see below):

class SimpleWidget(Gtk.Misc):
    __gtype_name__ = 'SimpleWidget'

    def __init__(self, *args, **kwds):
        super().__init__(*args, **kwds)
        self.set_size_request(40, 40)

    def do_draw(self, cr):
        # paint background
        bg_color = self.get_style_context().get_background_color(Gtk.StateFlags.NORMAL)
        cr.set_source_rgba(*list(bg_color))
        cr.paint()
        # draw a diagonal line
        allocation = self.get_allocation()
        fg_color = self.get_style_context().get_color(Gtk.StateFlags.NORMAL)
        cr.set_source_rgba(*list(fg_color));
        cr.set_line_width(2)
        cr.move_to(0, 0)   # top left of the widget
        cr.line_to(allocation.width, allocation.height)
        cr.stroke()

Finally, if you really want to derive from Gtk.Widget then you also have to set up a drawing background. Gtk.Misc does that for you, but Gtk.Widget could be a container that doesn't actually draw anything itself. But inquiring minds want to know, so you could do it like so:

from gi.repository import Gdk

class ManualWidget(Gtk.Widget):
    __gtype_name__ = 'ManualWidget'

    def __init__(self, *args, **kwds):
        # same as above

    def do_draw(self, cr):
        # same as above

    def do_realize(self):
        allocation = self.get_allocation()
        attr = Gdk.WindowAttr()
        attr.window_type = Gdk.WindowType.CHILD
        attr.x = allocation.x
        attr.y = allocation.y
        attr.width = allocation.width
        attr.height = allocation.height
        attr.visual = self.get_visual()
        attr.event_mask = self.get_events() | Gdk.EventMask.EXPOSURE_MASK
        WAT = Gdk.WindowAttributesType
        mask = WAT.X | WAT.Y | WAT.VISUAL
        window = Gdk.Window(self.get_parent_window(), attr, mask);
        self.set_window(window)
        self.register_window(window)
        self.set_realized(True)
        window.set_background_pattern(None)

Edit and to actually use it:

w = Gtk.Window()
w.add(SimpleWidget())
w.show_all()
w.present()
import signal    # enable Ctrl-C since there is no menu to quit
signal.signal(signal.SIGINT, signal.SIG_DFL)
Gtk.main()

Or, more fun, use it directly from the ipython3 REPL:

from IPython.lib.inputhook import enable_gtk3
enable_gtk3()
w = Gtk.Window()
w.add(SimpleWidget())
w.show_all()
w.present()
vbraun
  • 1,851
  • 17
  • 14
  • The custom widget can also be added to glade as described [here](https://askubuntu.com/a/1471492/78169) – Olumide Jun 08 '23 at 13:11
0

Here's a tutorial about writing a GTK 3 custom container widget in C: http://ptomato.name/advanced-gtk-techniques/html/custom-container.html It's probably more complicated than you need for writing a simple widget. You might also check out the migration guide from GTK 2 to 3: https://developer.gnome.org/gtk3/stable/gtk-migrating-2-to-3.html

ptomato
  • 56,175
  • 13
  • 112
  • 165
  • this is from your blog right? when you say "This is rather different from the way things worked in GTK 2, and there are probably plenty of GTK 2 instructions still floating around on the Internet." I recommend you to explicitly say that it's a GTK 3 technique, to make it more explicit. – knocte Aug 11 '13 at 09:58
  • and not sure I'm going to mark this answer as SOLVED because it doesn't really provide a sample, but thanks for the link – knocte Aug 11 '13 at 09:59
  • Right, I don't think it answers your question satisfactorily either. :-( – ptomato Aug 12 '13 at 03:40
  • For starters, I don't think there's a simple answer for that question. No one use python to write simple widgets. There's the code inside gtk+ itself. GtkButton is a supersimple widget to start with. You can read it. – erick2red Aug 12 '13 at 17:52
  • I would use Python to write simple widgets, I just have never gotten around to writing a tutorial about it! ;-) – ptomato Aug 13 '13 at 03:32
0

SO far the best reference to:
- understand Gobject (from wich gtk widget derive)
- have some boiler code and c code

https://developer.gnome.org/gobject/stable/howto-gobject.html

I know it's not Python written, but converting from c to python is a piece of cake (what matter is the algorithm, not the language)

sinner73
  • 157
  • 8