I am making a program with several screens and each one has its own size, so each time I change of screen I must re-size the App.
The problem is that, when I change the size of the window, Kivy only increase or reduce the lenght of the right and the bottom sides, not the four sides, so the screen always get “uncentered” after change the size.
I’ll try to make an example with lines:
-------------------------------- -------------------------------- | Monitor | | | | -------- | | -------------- | | | My | | | | | | | | App | | > | | | | | -------- | | | | | | | | |______________| | -------------------------------- --------------------------------
Like you can see the program only change the lengh of the right and bottom sides.
How can I center again the screen or better change the size of the four sides and not only two?
This is an example of my code but I don’t have any idea of what to do:
This is an .py
example:
from kivy.app import App from kivy.uix.screenmanager import Screen, ScreenManager from kivy.core.window import Window class Screen_Manager(ScreenManager): pass class Main(Screen): def __init__(self, **kwargs): super(Main, self).__init__(**kwargs) def on_pre_enter(self): Window.size = (900, 500) class Login(Screen): def __init__(self, **kwargs): super(Login, self).__init__(**kwargs) def on_pre_enter(self): Window.size = (400, 300) class MyApp(App): def build(self): return Screen_Manager() MyApp().run()
This is an my.kv
example (my
in order to work with MyApp
):
<Screen_Manager>: id: screen_manager Main: Login: <Login>: name: 'login' Button: text: 'Go to Main' on_press: root.manager.current = 'main' <Main>: name: 'main' Button: text: 'Go to Login' on_press: root.manager.current = 'login'
I have found a way but I don’t like it much:
def on_pre_enter(self): # New size size = (NEW_X, NEW_Y) # Get the actual pos and knowing the old size calculate the new one top = Window.top * Window.size[1] / size[1] left = Window.left * Window.size[0] / size[0] # Change the size Window.size = size # Fixing pos Window.top = top Window.left = left
Advertisement
Answer
I couldn’t find any hint that kivy was able to supply the screen size of the host device, so I hope if there is one, someone will tell us. In the meantime, I borrowed some setup code from another forum. I’ve only tested it on my macbook, and it seems to work, getting the screen size. I don’t know what will happen on windows, or linux, or multiple monitors. But here’s the new code:
import sys """ returns Monitor size x and y in pixels for desktop platforms, or None for mobile platforms Found at: https://groups.google.com/forum/#!topic/kivy-users/uZYrghb87g0 """ if sys.platform == 'linux2': import subprocess output = subprocess.Popen( 'xrandr | grep "*" | cut -d" " -f4', shell=True, stdout=subprocess.PIPE).communicate()[0] screenx = int(output.replace('n', '').split('x')[0]) screeny = int(output.replace('n', '').split('x')[1]) elif sys.platform == 'win32': from win32api import GetSystemMetrics screenx = GetSystemMetrics(0) screeny = GetSystemMetrics(1) elif sys.platform == 'darwin': from AppKit import NSScreen frame_size = NSScreen.mainScreen().frame().size screenx = frame_size.width screeny = frame_size.height else: # For mobile devices, use full screen screenx,screeny = 800,600 # return something #print "screenx,screeny = ",repr((screenx,screeny)) from kivy.config import Config # config should appear before any other kivy stuff Config.set('graphics','position','custom') from kivy.app import App from kivy.uix.screenmanager import Screen, ScreenManager from kivy.core.window import Window class Screen_Manager(ScreenManager): pass def center_window(sizex,sizey): Window.size = (sizex, sizey) Window.left = (screenx - sizex)/2 Window.top = (screeny - sizey)/2 class Main(Screen): def __init__(self, **kwargs): super(Main, self).__init__(**kwargs) def on_pre_enter(self): center_window(900,500) class Login(Screen): def __init__(self, **kwargs): super(Login, self).__init__(**kwargs) def on_pre_enter(self): center_window(400, 300) class MultiScreenApp(App): def build(self): return Screen_Manager() MultiScreenApp().run()