没有用python3 / gtk +显示启动画面

时间:2017-10-15 15:42:06

标签: python-3.x gtk splash

我的一个应用程序需要一段时间来收集所需的所有数据并显示窗口。所以,我决定创建一个简单的启动画面来通知用户发生了什么。不幸的是,启动窗口没有完全绘制:它显示一个黑色矩形,完成后消失。

我使用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函数(包含“Show the splash screen”注释中的代码),但这并没有解决问题。

我在看什么?

1 个答案:

答案 0 :(得分:1)

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

正如格特纳德所指出的那样:它做了它需要做的事情并且它是可以接受的,因为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"))