GTK4: momentary button with pressed and released signal (with working Python example)

I create a new topic with an example of how to implement a custom button widget with button pressed and released signals like requested in this old discussion:

gtkMomentaryButton.ui

<?xml version="1.0" encoding="UTF-8"?>
<interface>
  <template class="GtkMomentaryButton" parent="GtkBox">
    <property name="focusable">True</property>
    <property name="can-target">True</property>
    <property name="valign">center</property>
    <property name="halign">center</property>
    <style>
      <class name="button"/>
    </style>
    <child>
      <object class="GtkLabel" id="label_id">
        <property name="label">Momentary Button</property>
      </object>
    </child>
    <child>
      <object class="GtkGestureClick">
        <signal name="pressed" handler="on_pressed"/>
        <signal name="released" handler="on_released"/>
        <signal name="unpaired-release" handler="on_released"/>
      </object>
    </child>
  </template>
</interface>

gtkMomentaryButton.py

import gi

gi.require_version('Gtk', '4.0')

from gi.repository import Gtk, GObject

@Gtk.Template(filename="gtkMomentaryButton.ui")
class GtkMomentaryButton(Gtk.Box):
    __gtype_name__ = "GtkMomentaryButton"

    label_id = Gtk.Template.Child()

    @GObject.Property(type=str, default="Momentary Button")
    def label(self):
        return self.label_id.get_label()

    @label.setter
    def label(self, value):
        self.label_id.set_label(value)

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

    __gsignals__ = {
        'pressed': (GObject.SignalFlags.RUN_FIRST, None, ()),
        'released': (GObject.SignalFlags.RUN_FIRST, None, ()),
    }

    @Gtk.Template.Callback()
    def on_pressed(self, gesture, n_press, x, y):
        self.add_css_class("active") # Visual "depressed" look
        self.emit("pressed")

    @Gtk.Template.Callback()
    def on_released(self, gesture, n_press, x, y):
        self.remove_css_class("active")
        self.emit("released")

    def on_activate(self, widget, data):
        print("Button activated by keyboard!")
        return True

GtkMomentaryButton.set_css_name('button')

CustomButtonExample.py

import gi

gi.require_version("Gst", "1.0")
gi.require_version("GstBase", "1.0")
gi.require_version("Gtk", "4.0")

from gi.repository import Gst, GstBase, GLib, GObject, Gtk, Gdk, Gio # noqa: E402

from pathlib import Path

from gtkMomentaryButton import GtkMomentaryButton

class CustomButtonExample(Gtk.Application):
    def __init__(self):
        super().__init__(application_id="com.example.CustomButton")

    def do_activate(self):
        win = Gtk.ApplicationWindow(application=self, title="Custom Button Demo")
        win.set_default_size(300, 200)

        # create a box in the center to hold the button
        box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10)
        box.set_valign(Gtk.Align.CENTER)
        box.set_halign(Gtk.Align.CENTER)

        btn = GtkMomentaryButton()
        btn.connect('pressed', self.on_pressed)
        btn.connect('released', self.on_released)
        box.append(btn)

        win.set_child(box)
        win.present()

    def on_pressed(self, widget):
        print("Button pressed!")

    def on_released(self, widget):
        print("Button released!")

app = CustomButtonExample()
app.run(None)

Thanks for your work and the support here in the forum that allowed me to piece this together.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.