Errors when trying to implement Second Screen to Clock App

34 views
Skip to first unread message

Abraham Francisco

unread,
Apr 9, 2020, 2:03:23 PM4/9/20
to Kivy users support
My Code:

from time import strftime
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.clock import Clock
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager, Screen
import os


kv = """
BoxLayout:
orientation: 'vertical'
MyClock:
font_size: 50
id:my_clock
Button:
text: 'Set Alarm'
on_press: aggro_alarm.screen_manger.current = "SetAlarmPage"
"""


class MyClock(Label):
pass


class SetAlarmButton(Label):
def __init__(self, **kwargs):
super().__init__(**kwargs)

self.set_alarm = Button(text="Set Alarm")
# self.set_alarm.bind(on_press=)
self.add_widget(Label())
self.add_widget(self.set_alarm)


class MainApp(App):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.SetAlarmPage = SetAlarmPage()
self.screen_manager = ScreenManager()
self.home_screen = Builder.load_string(kv)

def build(self):
screen = Screen(name='Home')
screen.add_widget(self.home_screen)
self.screen_manager.add_widget(screen)

screen = Screen(name="SetAlarmPage")
screen.add_widget(self.SetAlarmPage)
self.screen_manager.add_widget(screen)

return self.screen_manager

def on_start(self):
t = strftime("%I:%M:%S %p")
self.root.ids.my_clock.text = t
Clock.schedule_interval(self.update_time, 1)

def update_time(self, dt):
t = strftime("%I:%M:%S %p")
self.root.ids.my_clock.text = t


class SetAlarmPage(GridLayout):
def __init__(self, *args, **kwargs):
super().__init__(**kwargs)
self.cols = 2

self.add_widget(Label(text="Alarm 1:"))
self.A1 = TextInput(multiline=False)
self.add_widget(self.A1)


if __name__ == "__main__":
aggro_alarm = MainApp()
aggro_alarm.run()


I'm trying to pull up "SetAlarmPage" from the button in kv on press. Now on load of the app I get this error:

    File "kivy\properties.pyx", line 860, in kivy.properties.ObservableDict.__getattr__
 KeyError: 'my_clock'

    During handling of the above exception, another exception occurred:
 
 Traceback (most recent call last):
   File "C:/Users/Owner/PycharmProjects/Aggro-Alarm/main.py", line 80, in <module>
     aggro_alarm.run()
   File "C:\Users\Owner\Anaconda3\envs\Aggro-Alarm\lib\site-packages\kivy\app.py", line 854, in run
     self.dispatch('on_start')
   File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
   File "C:/Users/Owner/PycharmProjects/Aggro-Alarm/main.py", line 60, in on_start
     self.root.ids.my_clock.text = t
   File "kivy\properties.pyx", line 863, in kivy.properties.ObservableDict.__getattr__
 AttributeError: 'super' object has no attribute '__getattr__'


What is this error trying to tell me? And ultimately, what should I do to be able to pull up a second screen with hopefully still keeping the kv string layout.

Elliot Garbus

unread,
Apr 9, 2020, 3:49:18 PM4/9/20
to kivy-...@googlegroups.com

SetAlarmPage needs to be a Screen not a GridLayout.  You can do more of this in kivy.

 

Here is an example of switching screens:

 

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.button import Button
from kivy.clock import Clock
from kivy.properties import StringProperty

from time import strftime
kv =
"""
<Home@Screen>:
    BoxLayout:
        MyClock:
            font_size: 50
            text: self.current_time
            on_release: app.root.ids.sm.current = 'alarm_page'
<AlarmPage@Screen>:
    Button:
        text: 'Put alarms on this page'
        on_release: app.root.ids.sm.current = 'home_page'

BoxLayout:
    ScreenManager:
        id: sm
        Home:
            name: 'home_page'
        AlarmPage:
            name: 'alarm_page'
       
"""


class MyClock(Button):
    current_time = StringProperty(strftime(
"%I:%M:%S %p"))

   
def __init__(self, **kwargs):
        Clock.schedule_interval(
self.update_time, 1)
       
super().__init__(**kwargs)

   
def update_time(self, dt):
       
self.current_time = strftime("%I:%M:%S %p")


class MainApp(App):
   
def build(self):
       
return Builder.load_string(kv)


if __name__ == "__main__":
    MainApp().run()

--
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/3b5ef5a0-6f73-4fc5-ad96-b7610e0fad26%40googlegroups.com.

 

Abraham Francisco

unread,
Apr 11, 2020, 5:50:37 PM4/11/20
to Kivy users support
How do I make it so that it's a centralized button that leads me to the next page and not just pressing the whole screen anywhere?

Elliot Garbus

unread,
Apr 11, 2020, 8:41:01 PM4/11/20
to kivy-...@googlegroups.com

In the code there is one button on the screen the size of the screen.  Use layouts to add other widgets.

 

For example:

 

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.label import Label
from kivy.clock import Clock
from kivy.properties import StringProperty

from time import strftime
kv =
"""
<Home@Screen>:
    BoxLayout:
        orientation: 'vertical'
        MyClock:
            size_hint_y: .75
            font_size: 50
            text: self.current_time
        Button:
            size_hint_y: .25
            text: 'Change to Alarm Page'
            font_size: 50

            on_release: app.root.ids.sm.current = 'alarm_page'
       
<AlarmPage@Screen>:
    Button:
        text: 'Put alarms on this page'
        on_release: app.root.ids.sm.current = 'home_page'

BoxLayout:
    ScreenManager:
        id: sm
        Home:
            name: 'home_page'
        AlarmPage:
            name: 'alarm_page'
       
"""


class MyClock(Label):
    current_time = StringProperty(strftime(
"%I:%M:%S %p"))

   
def __init__(self, **kwargs):
        Clock.schedule_interval(
self.update_time, 1)
       
super().__init__(**kwargs)

   
def update_time(self, dt):
       
self.current_time = strftime("%I:%M:%S %p")


class MainApp(App):
   
def build(self):
       
return Builder.load_string(kv)


if __name__ == "__main__":
    MainApp().run()

From: Abraham Francisco
Sent: Saturday, April 11, 2020 2:50 PM
To: Kivy users support

--

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.

Abraham Francisco

unread,
Apr 15, 2020, 1:51:36 PM4/15/20
to kivy-...@googlegroups.com
Thank you so much for helping me. I was looking through the documentation and couldn't find how to change the color of a button on press, so that it doesn't highlight to blue. I know how to change the default background color but how do I change it on press. I tried using background_down but it doesn't take rgba coding.

Elliot Garbus

unread,
Apr 15, 2020, 2:29:54 PM4/15/20
to kivy-...@googlegroups.com

A Button uses 4 images to define the look of the button.  You can change the color of the button by replacing those images or by using background color.  To change the color of the button when the button is pressed you the button state (‘normal’ or ‘down’ to select the color.

 

Example:

from kivy.app import App
from kivy.lang import
Builder

kv =
"""
# set your colors for normal and down position of the button
#:set normal_color (.5, .5, .4, 1)
#:set down_color (0, 0, .3, 1)

<FlatButton@Button>:
    background_color: {'normal': normal_color, 'down': down_color}[self.state]  # this is a dict, state is 'normal or 'down'
    background_down: ''  # The standard button uses 4 bitmaps to define the look
    background_normal: ''
    background_disabled_normal: ''
    background_disabled_down: ''

BoxLayout:
    orientation: 'vertical'
    spacing: 2
    padding: 5
    FlatButton:
        text: "Hello, I'm a FlatButton"
    FlatButton:
        text: 'Press me'
    Button:
        text: 'Normal Button'
    Button:
        text: 'Disabled Button'
        disabled: True
"""


class FlatButtonApp(App):
   
def build(self):
       
return Builder.load_string(kv)


FlatButtonApp().run()

Abraham Francisco

unread,
Apr 24, 2020, 7:46:05 PM4/24/20
to kivy-...@googlegroups.com
How do I properly set the disabled normal and disabled down colors. I tried this below but the color stayed the same. Yes I changed it to a FlatButton in the boxlayout.

from kivy.app import App
from kivy.lang import Builder

kv = """
# set your colors for normal and down position of the button
#:set normal_color (.5, .5, .4, 1)
#:set down_color (0, 0, .3, 1)
#:set disabled_normal_color (0, .4, .6, 1)

<FlatButton@Button>:
background_color: {'normal': normal_color, 'down': down_color, 'disabled_normal': disabled_normal_color}[self.state] # this is a dict, state is 'normal or 'down'
    background_down: ''  # The standard button uses 4 bitmaps to define the look
background_normal: ''
background_disabled_normal: ''
background_disabled_down: ''

Elliot Garbus

unread,
Apr 24, 2020, 8:05:10 PM4/24/20
to kivy-...@googlegroups.com

The button state is either normal or down.  Disabled is a Boolean and will be True or False.

Keeping it all in kv:

background_color: {'normal': normal_color, 'down': down_color}[self.state] if not self.disabled else {'normal': disabled_normal_color, ‘down’: disabled_down_color} [self.state]

 

This uses a ternary expression.  The format is:

color =  x if y else z

this is the same as:

if(x):

    color = x

else:

    color = y

Elliot Garbus

unread,
Apr 24, 2020, 8:21:00 PM4/24/20
to kivy-...@googlegroups.com

Oops…

This uses a ternary expression.  The format is:

color =  x if y else z

this is the same as:

if(y):

    color = x

else:

    color = z

Abraham Francisco

unread,
May 2, 2020, 1:52:12 PM5/2/20
to kivy-...@googlegroups.com
I get "SyntaxError: invalid character in identifier"

on this line,

background_color: {'normal': normal_color, 'down': down_color}[self.state] if not self.disabled else {'normal': disabled_normal_color, ‘down’: disabled_down_color} [self.state] 

With an up arrow under 'down' in the disabled section of the above.

What does that mean?

Elliot Garbus

unread,
May 2, 2020, 3:54:35 PM5/2/20
to kivy-...@googlegroups.com
The quotes around down are not correct. Looks like an email program changed them. 
Bad:  ‘down’
Good :  'down'

Sent from my iPad

On May 2, 2020, at 10:52 AM, Abraham Francisco <fran...@gmail.com> wrote:


Reply all
Reply to author
Forward
0 new messages