Write custom widget with GTK3
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()
knocte
I'm a project maintainer leading a team of F# and Rust developers, and looking to expand this team (and hire Linux DevOps specialists and/or build engineers). Get in touch if you want to know more. If you're interested in my technical background, read below: In the low-level front, I've used Assembly, C, C++, and starting to learn Rust (could maybe give a go to D too). In the too-high-level front, I've used PHP, Python, JavaScript, Ruby, but not willing to use them again if I can avoid it. These days all my new code is written in F# (or TypeScript if I need to use some JavaScript library), although I still need to touch a lot of C# code. When I was freelancing, I was willing to learn Elm in case I needed to do some web+frontend development and they didn't let me write TypeScript in strict mode (plus tslint), or Gleam in case I had to interoperate with any BEAM-based language, or Ceylon/Frege (along with ParparVM if iOS is needed) or maybe Swift, in case I needed to implement mobile apps and they didn't let me use Xamarin.Forms+F#. In regards to databases, I'm an old-school guy who thinks normalized data usually beats any NoSQL/NewSQL solution, except for rare BigData indexing/denormalization scenarios.
Updated on June 04, 2022Comments
-
knocte almost 2 years
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 over 10 yearsthis 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 over 10 yearsand not sure I'm going to mark this answer as SOLVED because it doesn't really provide a sample, but thanks for the link
-
ptomato over 10 yearsRight, I don't think it answers your question satisfactorily either. :-(
-
erick2red over 10 yearsFor 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.
-
ptomato over 10 yearsI would use Python to write simple widgets, I just have never gotten around to writing a tutorial about it! ;-)