python3/gtk+ 未显示启动画面

Splash screen not showing with python3/gtk+

我的一个应用程序需要一段时间来收集它需要的所有数据并显示 window。因此,我决定创建一个简单的启动画面来通知用户发生了一些事情。不幸的是,飞溅 window 并未完全绘制:它显示为黑色矩形并在完成后消失。

我使用 this 示例代码 (python 2.7) 作为基础。

这是我的(简化代码):

#! /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()

我什至尝试过 GObject.timeout_add 线程显示函数(包含 "Show the splash screen" 评论中的代码),但这并没有解决问题。

我在看什么?

以下代码作为编辑发布在 OP 中(已从 OP 中删除,因为它被认为是对原始问题的充分回答。

正如 theGtknerd 指出的那样:它做了它需要做的事情,这是可以接受的,因为 Gtk 对象不是从主线程更新的。

这是脚本的线程版本:

#! /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"))