First of all, I'd like to clarify that I have absolutely 0 background as a software engineer and this is the first time I'm using python for something besides API's and creating excel/plots.
My issue is that I was trying to create an app using kivy and then I imported the kivy.core.window
library a blank screen appears.
I've seen that this issue is fairly common when using kivy and multiprocessing, but none of the information I found fixed my problem. Result of running my code without the kivy.core.window
library:
Result when adding said library:
Also, if I wait like 10 seconds the blank screen disappears and kills the count_time process.
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, NoTransition
import time
from datetime import datetime
import multiprocessing as mp
from multiprocessing import Process, Queue, freeze_support
Builder.load_string('''
<TestScreen>:
BoxLayout:
orientation: "vertical" # place object vertically
Label:
size_hint: 1, 1
text: 'TITLE'
font_size: 150
color: 1, 1, 1, 1
Button:
text: 'start'
on_press: root.start_mp()
Button:
text: 'stop'
on_press: root.stop_time()
''')
def count_time(x):
for i in range(x):
print('count={}'.format(i))
time.sleep(1)
class Test(App):
def build(self):
sm.add_widget(TestScreen(name='test'))
return sm
class TestScreen(Screen):
def __init__(self, **kwargs):
super(TestScreen, self).__init__(**kwargs)
def start_mp(self):
self.p1 = mp.Process(target=count_time, args=(10, ))
self.p1.start()
def stop_time(self):
pass
if __name__ == '__main__':
mp.freeze_support()
sm = ScreenManager(transition=NoTransition())
Test().run()
The problem is that when you run Process
, it starts a new python proces and imports the current .py
file. On most platforms, the line:
if __name__ == '__main__':
protects the Test().run()
from being executed and starting another App
and is enough to protect from another window being opened. However, it appears that importing kivy.core.window
is enough to open another window (on Windows platform) when the original .py
file is imported for multiprocessing. You can read about it here.
A really ugly work around is to protect all kivy imports (and as a result, all the kivy code) with a if __name__ == '__main__':
line. Like this:
import time
import multiprocessing as mp
def count_time(x):
for i in range(x):
print('count={}'.format(i))
time.sleep(1)
if __name__ == '__main__':
mp.freeze_support()
from kivy.core.window import Window
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, NoTransition
Builder.load_string('''
<TestScreen>:
BoxLayout:
orientation: "vertical" # place object vertically
Label:
size_hint: 1, 1
text: 'TITLE'
font_size: 150
color: 1, 1, 1, 1
Button:
text: 'start'
on_press: root.start_mp()
Button:
text: 'stop'
on_press: root.stop_time()
''')
class Test(App):
def build(self):
sm = ScreenManager(transition=NoTransition())
sm.add_widget(TestScreen(name='test'))
return sm
class TestScreen(Screen):
def __init__(self, **kwargs):
super(TestScreen, self).__init__(**kwargs)
def start_mp(self):
self.p1 = mp.Process(target=count_time, args=(10,))
self.p1.start()
def stop_time(self):
pass
Test().run()