Creating a splash screen with a shaped window

207 views
Skip to first unread message

ST

unread,
May 23, 2020, 5:46:16 AM5/23/20
to Kivy users support
I am trying to create a splash screen with a shaped window, using a png file with transparent areas.
I want it to appear at the center of the screen at startup, then make the main screen appear at the top left corner of the screen some time afterwards.

I've tried to do this both by using ScreenManager (sm.py) and by running 2 separate apps (2apps.py), but I can't seem to make the main screen appear properly.
The splash screen is displayed OK, but the main screen is still trimmed to the image file in the splash screen.

I would be grateful if anyone can offer a solution.
Any help is appreciated. Thanks in advance!

Below are the codes. They are also attached to this post, along with the image files.

--------------------------------------------------

sm.py

from kivy.config import Config
Config.set('graphics','shaped',1)
from kivy.app import App
from kivy.core.window import Window
from kivy.clock import Clock
from kivy.uix.image import Image
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition

# get screen size
import ctypes
user32 = ctypes.windll.user32
screensize = user32.GetSystemMetrics(0), user32.GetSystemMetrics(1)

sm = ScreenManager(transition = FadeTransition())

def switchToMain():
    sm.current = 'main'
    
class MainScreen(Screen):
    pass
    
class SplashScreen(Screen):

    def on_leave(self):
    
        Clock.schedule_once(self.set)
        Window.borderless = False
        Window.size = (800, 600)
        Window.left = 0
        Window.top = 33
        
    def set(self,dt):
    
        Window.shape_image = 'defaultshape.png' # doesn't work
        Window.shape_mode = 'default'

class TestApp(App):

    def build(self):
    
        Clock.schedule_once(self.set)
        
        global sm
        sm.add_widget(SplashScreen(name='splash'))
        sm.add_widget(MainScreen(name='main'))
        return sm
        
    def set(self,dt):    
    
        Window.shape_image = 'kivy-icon-256.png'
        Window.shape_mode = 'binalpha'


if __name__ == '__main__':

    Window.fullscreen = False
    Window.borderless = True
    Window.size = (256, 256)
    Window.left = int((screensize[0]-Window.size[0])/2)
    Window.top = int((screensize[1]-Window.size[1])/2)
    
    Clock.schedule_once(lambda dt: switchToMain(), 2)
    TestApp().run()

2apps.py

from kivy.config import Config
Config.set('graphics','shaped',1)
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.core.window import Window
from kivy.clock import Clock
from kivy.uix.image import Image

# get screen size
import ctypes
user32 = ctypes.windll.user32
screensize = user32.GetSystemMetrics(0), user32.GetSystemMetrics(1)

class MainScreen(FloatLayout):
    pass
    
class SplashScreen(FloatLayout):
    pass

class TestApp(App):

    def build(self):
    
        Window.fullscreen = False
        Window.borderless = False # doesn't work
        Window.size = (800, 600)
        Window.left = 0
        Window.top = 30
        
        Clock.schedule_once(self.set)
        
        return MainScreen()
        
    def set(self,dt):
    
        Window.shape_image = 'defaultshape.png' # doesn't work
        Window.shape_mode = 'default'

class IconApp(App):

    def build(self):
    
        Window.fullscreen = False
        Window.borderless = True
        Window.size = (256, 256)
        Window.left = int((screensize[0]-Window.size[0])/2)
        Window.top = int((screensize[1]-Window.size[1])/2)
        
        Clock.schedule_once(self.set)
        
        icon = BoxLayout()
        icon.add_widget(Image(source='kivy-icon-256.png'))
        return icon
        
    def set(self,dt):
    
        Window.shape_image = 'kivy-icon-256.png'
        Window.shape_mode = 'binalpha'

def switchToMain():

    IconApp().stop()
    TestApp().run()
    
def switchToLogo():

    TestApp().stop()
    IconApp().run()
    

if __name__ == '__main__':

    # desired order:
    # both logo and main are shaped
    
    Clock.schedule_once(lambda dt: switchToMain(), 2)
    IconApp().run()
    
    # reverse order:
    # only logo is shaped, but main screen is borderless
    
    #Clock.schedule_once(lambda dt: switchToLogo(), 2)
    #TestApp().run()

test.kv

#:kivy 1.11.1
            
<MainScreen>:

    BoxLayout:      
        Label:
            text: 'Main screen'
            
<SplashScreen>:

    BoxLayout:
        Image:
            source: 'kivy-icon-256.png'
sm.py
2apps.py
test.kv
kivy-icon-256.png
defaultshape.png

Elliot Garbus

unread,
May 23, 2020, 4:19:44 PM5/23/20
to kivy-...@googlegroups.com

Perhaps someone else knows a definitive answer, here is my results after a few experiments, and an exchange with Inclement on the Discord Channel.

The short answer, this use case is not supported on Windows.

 

What you have done is very clever, setting:  Config.set('graphics','shaped', '1')

It is interesting to note that ‘shaped’ is not documented in config, and Windows.shaped is read only.

 

Looking at SDL2 it looks like there is a different call to create a shaped window vs a regular window.  Further complicating things this call does not appear to be documented. 

 

If I use Config.set('graphics','shaped', '1')  I can not add visible border back to the window. 

 

Possible Solutions:

  1. The easy way – live with the constraint, and create a rectangular image for the splash screen.
  2. Create 2 programs –
    1. program 1, draws a shaped screen.
    2. Program 2, opens program 1, displaying a splash screen.  Then P2 launches the main kivy program, perhaps with the window minimized.  Then it closes the splash screen program, and shows the main kivy window.

 

You could also do something similar to creating 2 programs by using multi-processing.

--
You received this message because you are subscribed to the Google Groups "Kivy users support" group.
To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/095797af-19f4-49be-8335-2a78713d3188%40googlegroups.com.

 

ST

unread,
May 24, 2020, 8:04:45 PM5/24/20
to Kivy users support
Thank you for taking your time to look into this issue.

For now I have (sadly) settled with a rectangular splash screen, and am considering your second solution using another program such as wx.

If that doesn't work, I will try multi-processing.
Thank you for your clear advice!

----------------------------------------------------------------------
sidenote:

The method Config.set('graphics','shaped', '1') is something I found here:


But that is about all I could find on this topic.
I hope there will be support for this in future versions of kivy.

To unsubscribe from this group and stop receiving emails from it, send an email to kivy-...@googlegroups.com.

Elliot Garbus

unread,
May 25, 2020, 12:42:37 AM5/25/20
to kivy-...@googlegroups.com

You could use kivy for both programs.  The first would just be the shaped splash screen, the second, the full app.

 

As I learned the issues is really the way SDL2 is structured and the way kivy is using it.  Kivy is set up to only have 1 window.  In SDL you decide to create a shaped window or a regular window.  There is not a capability – that I saw after a rather brief look – to convert a shaped window back to a conventional window.

To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/91080b80-027c-4c5c-92bc-10b9e63c5549%40googlegroups.com.

 

ST

unread,
May 25, 2020, 4:36:50 AM5/25/20
to Kivy users support
You could use kivy for both programs.  The first would just be the shaped splash screen, the second, the full app.

Oh, yes, of course! Thank you for the workaround, and for the helpful info regarding SDL.
Reply all
Reply to author
Forward
0 new messages