Arjen Balfoort
Arjen Balfoort

Reputation: 185

Splash screen not showing with python3/gtk+

One of my applications takes a while to collect all data it needs and show the window. So, I decided to create a simple splash screen to notify the user that there is something happening. Unfortunately, the splash window is not drawn completely: it shows a black rectangle and disappears when done.

I've used this example code (python 2.7) as base.

Here's my (simplified code):

#! /usr/bin/env python3

# Make sure the right Gtk version is loaded
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from time import sleep

class Splash(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self)

        # Set position and decoration
        self.set_position(Gtk.WindowPosition.CENTER)
        self.set_decorated(False)

        # Add box and label
        self.box = Gtk.Box()
        self.add(self.box)
        self.lbl = Gtk.Label()
        self.lbl.set_label("My app is loading...")
        self.box.pack_start(self.lbl, True, True, 0)

        # Show the splash screen without causing startup notification
        # https://developer.gnome.org/gtk3/stable/GtkWindow.html#gtk-window-set-auto-startup-notification
        self.set_auto_startup_notification(False)
        self.show_all()
        self.set_auto_startup_notification(True)

        # Ensure the splash is completely drawn before moving on
        while Gtk.events_pending():
            Gtk.main_iteration()

if __name__ == '__main__':
    # Initiate and show the splash screen
    splash = Splash()

    # Simulate the start of my app which takes a while
    sleep(5)

    # Destroy the splash window
    splash.destroy()

I've even experimented with GObject.timeout_add to thread the show function (contained the code from "Show the splash screen" comment onward), but that didn't solve the problem.

What am I over looking?

Upvotes: 0

Views: 1103

Answers (1)

Arjen Balfoort
Arjen Balfoort

Reputation: 185

The following code was posted as an edit in the OP (removed from OP as it is considered as an adequate answer to the original question.

As theGtknerd pointed out: it does what it needs to do and it's acceptable because the Gtk objects are not updated from the main thread.

Here's the threaded version of the script:

#! /usr/bin/env python3

# Make sure the right Gtk version is loaded
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from threading import Thread
from time import sleep


class Splash(Thread):
    def __init__(self):
        super(Splash, self).__init__()

        # Create a popup window
        self.window = Gtk.Window(Gtk.WindowType.POPUP)
        self.window.set_position(Gtk.WindowPosition.CENTER)
        self.window.connect('destroy', Gtk.main_quit)
        self.window.set_default_size(400, 250)

        # Add box and label
        box = Gtk.Box()
        lbl = Gtk.Label()
        lbl.set_label("My app is loading...")
        box.pack_start(lbl, True, True, 0)
        self.window.add(box)

    def run(self):
        # Show the splash screen without causing startup notification
        # https://developer.gnome.org/gtk3/stable/GtkWindow.html#gtk-window-set-auto-startup-notification
        self.window.set_auto_startup_notification(False)
        self.window.show_all()
        self.window.set_auto_startup_notification(True)

        # Need to call Gtk.main to draw all widgets
        Gtk.main()

    def destroy(self):
        self.window.destroy()


class MainUI(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self)

        # Set position and decoration
        self.set_position(Gtk.WindowPosition.CENTER)
        self.lbl = Gtk.Label()
        self.lbl.set_label("Main window started")
        self.add(self.lbl)
        self.connect('destroy', Gtk.main_quit)

        # Initiate and show the splash screen
        print(("Starting splash"))
        splash = Splash()
        splash.start()

        print(("Simulate MainUI work"))
        sleep(5)

        # Destroy splash
        splash.destroy()
        print(("Splash destroyed"))

        print(("Starting MainUI"))
        self.show_all()


if __name__ == '__main__':
    # Now show the actual main window
    MainUI()
    Gtk.main()
    print(("MainUI ended"))

Upvotes: 2

Related Questions