My app doesn't function as soon as I use ScreenManager.
I had a problem with a stopwatch function that was solved here. In short, the stopwatch needed to pause when the pause button opens the popup menu, and to resume when the menu is closed.
The problem returned when the ScreenManager was used, so I am probably not using the ScreenManager correctly, or missing some essential basic knowledge about Kivy or Python to do what I want to do.
Python code:
import kivy
from kivy.app import App
from kivy.lang import Builder
from kivy.properties import NumericProperty
from kivy.uix.popup import Popup
from kivy.clock import Clock
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager, Screen
root_widget = Builder.load_file('app.kv')
class ExampleWidget(Screen):
time = NumericProperty(0)
paused = False
stop = False
# Keeping time
def increment_time(self, interval):
self.time += .1
print(self.time) # To check if stopwatch is running or not
# Stop should mean that the stopwatch must reset when it starts again.
# When paused it should resume when it starts again
def start(self):
# Keeping time
self.time = 0
Clock.schedule_interval(self.increment_time, .1)
def stop(self):
Clock.unschedule(self.increment_time)
print('Stopped')
def pause(self):
# Pause stopwatch
if self.paused:
Clock.unschedule(self.increment_time)
print("!!", self.time) # To make it easier to see if stopwatch actually resumes where it left off
print('unscheduled') # Just to confirm and to make it a bit easier to see
# resume stopwatch
elif not self.paused:
Clock.schedule_interval(self.increment_time, .1)
class PopupMenu(Popup):
example = ExampleWidget()
class Menu(Screen, BoxLayout):
pass
class WindowManager(ScreenManager):
pass
class MyApp(App):
ExampleWidget = ExampleWidget()
WindowManager = WindowManager()
def build(self):
return self.WindowManager
MyApp().run()
.kv file:
#:import Factory kivy.factory.Factory
#: import WipeTransition kivy.uix.screenmanager.WipeTransition
<WindowManager>:
transition: WipeTransition()
canvas.before:
Color:
rgba: 0, 0, 0, 1
Rectangle:
pos: self.pos
size: self.size
Menu:
ExampleWidget:
<PopupMenu@Popup>
auto_dismiss: False
size_hint_y: .8
size_hint_x: .9
title: 'Pause'
example: app.ExampleWidget
BoxLayout:
Button:
text: 'resume'
on_press: root.example.paused = False
on_release: root.dismiss(); root.example.pause()
size: self.size
<Menu>:
id: menu
name: "first"
orientation: 'vertical'
size: root.width, root.height
secondary_color: .4,.4,.4,1
secondary_color2: 0,.7,.7,1
canvas.before:
Color:
rgba: 1, 1, 1, 1
Rectangle:
pos: self.pos
size: self.size
Button:
id: start_button
text: "Start"
font_size: 32
on_release: app.root.current = "second"
size: root.width/2, root.height/12
size_hint: None, None
pos: root.width/4, root.height/2.5
background_color: 0, 0, 0, 0
canvas.before:
Color:
rgba: menu.secondary_color if start_button.state=='normal' else menu.secondary_color2
RoundedRectangle:
size: start_button.width, start_button.height
pos: start_button.pos
<ExampleWidget>:
name: 'second'
GridLayout:
col: 2
rows: 3
size: root.size
Button:
text: 'start'
size: self.size
on_press: root.start()
Button:
text: 'stop'
size: self.size
on_press: root.stop()
Button:
text: 'Pause menu'
size: self.size
on_press: root.paused = True
on_release: Factory.PopupMenu().open(); root.pause()
Label:
text: str(round(root.time))
size: self.size
Thank you in advance for your help or ideas.
The problem is that you have references to an ExampleWidget
that is not part of your GUI. The code:
class PopupMenu(Popup):
example = ExampleWidget()
is creating a reference to a new instance of ExampleWidget
that is not the one in your GUI. This can be just replaced with:
class PopupMenu(Popup):
pass
Then, in your kv
, if you add an id
for the ExampleWidget
instance that is actually in your GUI:
<WindowManager>:
transition: WipeTransition()
canvas.before:
Color:
rgba: 0, 0, 0, 1
Rectangle:
pos: self.pos
size: self.size
Menu:
ExampleWidget:
id: example # added to enable accessing this instance of ExampleWidget
Now your MyApp
class can be:
class MyApp(App):
WindowManager = WindowManager()
def build(self):
self.ExampleWidget = self.WindowManager.ids.example
return self.WindowManager
Now app.ExampleWidget
will be a reference to the ExampleWidget
instance that is in your GUI.