If you prefer to create this without Glade, you can use something like this (based off the previous answer):
Assuming your current code has something like:
window = Gtk.ApplicationWindow(application=self)
window.add(main_widget)
Then you would change the code to something like this:
window = Gtk.ApplicationWindow(application=self)
overlay = Gtk.Overlay()
window.add(overlay)
overlay.add(main_widget)
self._notify_timeout = None
# Notification overlay widget
self._revealer = Gtk.Revealer(valign=Gtk.Align.START, halign=Gtk.Align.CENTER)
box = Gtk.Box(orientation="horizontal", spacing=18)
box.get_style_context().add_class("app-notification")
self._notify_label = Gtk.Label(wrap=True)
box.pack_start(self._notify_label, expand=False, fill=True, padding=18)
button = Gtk.Button.new_from_icon_name("window-close-symbolic", Gtk.IconSize.BUTTON)
button.set_relief(Gtk.ReliefStyle.NONE)
button.set_receives_default(True)
button.connect("clicked", functools.partial(self._revealer.set_reveal_child, False))
box.pack_start(button, expand=False, fill=True, padding=18)
self._revealer.add(box)
overlay.add_overlay(self._revealer)
Then to display a notification, you can add a method like:
def notify(self, message, timeout=5):
if self._notify_timeout is not None:
self._notify_timeout.cancel()
self._notify_label.set_text(message)
self._revealer.set_reveal_child(True)
if timeout > 0:
self._notify_timeout = asyncio.get_event_loop().call_later(
timeout, functools.partial(self._revealer.set_reveal_child, False))
In addition to what the existing answer provides, this adds a timeout to automatically remove the notification after a few seconds. That code assumes you are using asyncio, if not then update the above method to use another timer method.