Reputation: 185
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
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