Print and clear output on screen with Kivy - python

I'm trying to print some words on screen with kivy.
What I'm looking for is print first word then sleep 2 seconds then clear first word and print second word
What I'm currently doing:
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from random import choice
from time import sleep
xWords = ["hello1", "hello2", "hello3", "hello4", "hello5"]
class Test(GridLayout):
def __init__(self, **kwargs):
super(Test, self).__init__(**kwargs)
self.cols = 1
for x in xrange(2):
# I want it to show frist word then sleep 2 sec then clear first word from screen then print second word
self.add_widget(Label(text = "[b]"+choice(xWords)+"[/b]", markup = True, font_size = "40sp"))
sleep(2)
# then clear all words in screen
for x in xrange(5):
# then show the new 4 words
self.add_widget(Label(text = "[b]"+choice(xWords)+"[/b]", markup = True, font_size = "40sp"))
class TestApp(App):
def build(self):
return Test()
if __name__ == "__main__":
TestApp().run()
How can I do this?

Don't use time.sleep, this blocks the gui because the whole function doesn't return until time.sleep does.
Use Clock.schedule_once instead. Below is a simple example to call a function called update in 2 seconds, you can do whatever you want within that function including scheduling another one.
from kivy.clock import Clock
class Test(GridLayout):
def __init__(self, **kwargs):
super(Test, self).__init__(**kwargs)
Clock.schedule_once(self.update, 2) # 2 is for 2 seconds
def update(self, *args):
self.clear_widgets()
# then add some more widgets here

Related

It is necessary to transfer to the SecondScreen class, the text that the button_press function returns from the ScreenMain class

Please help, I'm trying to make an application for a child to learn the alphabet, I'm just learning programming and working with classes.
I need to pass to the SecondScreen class the text that the button_press function returns from the ScreenMain class.
`
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from itertools import chain
from kivy.uix.screenmanager import ScreenManager, Screen
class ScreenMain(Screen):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.alphabet = [chr(i) for i in chain(range(1040, 1046), range(1025, 1026), range(1046, 1069), range(32, 33),
range(1069, 1072))]
gr = GridLayout(cols=5, padding=[35], spacing=3)
for i in self.alphabet:
gr.add_widget(Button(text=i, on_press=self.button_press))
self.add_widget(gr)
def button_press(self, instance):
self.manager.transition.direction = 'left'
self.manager.current = 'second_screen'
print(instance.text) # I output to the console, everything is ok
return instance.text
class SecondScreen(Screen):
def __init__(self, **kwargs):
super().__init__(**kwargs)
get = ScreenMain.button_press # I'm trying to pass a letter from a function to a class button_press
layout = GridLayout(cols=5, rows=5, padding=[35], spacing=10)
layout.add_widget(Button(
text=str(get))) # Trying to create a button on the second page with the text of the letter pressed on the first screen
self.add_widget(layout)
def _on_press_button_new_layout(self, *args):
self.manager.transition.direction = 'right'
self.manager.current = 'main_screen'
class MyApp(App):
def build(self):
sm = ScreenManager()
sm.add_widget(ScreenMain(name='main_screen'))
sm.add_widget(SecondScreen(name='second_screen'))
return sm
if __name__ == '__main__':
MyApp().run()
`

How to get ID of the button pressed in kivy?

Here is the example code that I am working with.
I am creating a pre-set number of buttons, each with their own ID numbers, based on the for loop
All the buttons have the same function attached to them when they are pressed
My goal is to get the ID name of the button that was pressed
Currently, my code is printing out the specific object address(?) like 0xAABBCCEE
I want to know how to print out the code in ID format, like "Button 3"
class MainScreen(GridLayout):
def __init__(self, **kwargs):
super(MainScreen, self).__init__(**kwargs)
self.cols = 1
MainScreenLayout = GridLayout()
MainScreenLayout.cols = 3
#for loop creating buttons with varying IDs
NumberToCreate = 4
for x in range(int(NumberToCreate)):
aButton = Button(text='button text ' + str(x), on_press=self.press_auth)
MainScreenLayout.add_widget(aButton)
self.ids['button' + str(x)] = aButton
self.add_widget(MainScreenLayout)
#function for when button is pressed
def press_auth(self, instance):
print(str(instance)) #ulimate goal is get ID name and x number, to use later in code
class MyApp(App):
def build(self):
return MainScreen()
if __name__== '__main__':
MyApp().run()
IDs in kivy are usually used in conjunction with kv files to track objectes through inheritance. You probably shouldn't use the instance variable ids as a setter like you do as it is normally set internally to kivy and used as a getter by the developer.
An easier way to do what you want is to just set an arbitrary variable on each Button instance and track the differences there. If you plan on using deep inheritance and that's why you want to use ids then I would set the id on the instance before adding it to the MainScreen.
The first way could be done simply like this:
class MainScreen(GridLayout):
def __init__(self, **kwargs):
super(MainScreen, self).__init__(**kwargs)
self.cols = 1
MainScreenLayout = GridLayout()
MainScreenLayout.cols = 3
#for loop creating buttons with varying IDs
NumberToCreate = 4
for x in range(int(NumberToCreate)):
aButton = Button(text='button text ' + str(x), on_press=self.press_auth)
aButton.my_id = x # or 'button' + str(x) or whatever you want to use to track buttons
MainScreenLayout.add_widget(aButton)
self.add_widget(MainScreenLayout)
#function for when button is pressed
def press_auth(self, instance):
print(str(instance.my_id)) #ulimate goal is get ID name and x number, to use later in code
class MyApp(App):
def build(self):
return MainScreen()
if __name__== '__main__':
MyApp().run()
this is should work for you
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
class MainScreen(GridLayout):
def __init__(self, **kwargs):
super(MainScreen, self).__init__(**kwargs)
self.cols = 1
MainScreenLayout = GridLayout()
MainScreenLayout.cols = 3
# for loop creating buttons with varying IDs
NumberToCreate = 4
for x in range(int(NumberToCreate)):
aButton = Button(text='button text ' + str(x), on_press=self.press_auth)
MainScreenLayout.add_widget(aButton)
# let us make the id similar to the text to simplify the searching
self.ids['button text ' + str(x)] = aButton
self.add_widget(MainScreenLayout)
# function for when button is pressed
def press_auth(self, instance):
# here we can accuses the button id using button text
print(self.ids[instance.text])
class MyApp(App):
def build(self):
return MainScreen()
if __name__ == '__main__':
MyApp().run()
Update
you can not get the ID by the button instance because its stored as MainScreen ids I my example is to show you how you can get an instance using using one of the instance property like text

Python Kivy: Update Label

i am new in the Kivy Topic and i have got a simple question (i think).
With the function "zufall" i create a random number.
This number should update every 2 seconds in the label.
But when i am running the code, the error "Label.text accept only str" occurs.
But from my opinion i made the "random_number" to a string. Or is there another problem, with my thinking?
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
import random
from kivy.clock import Clock
from kivy.properties import StringProperty
class ConnectPage(GridLayout):
# runs on initialization
def zufall(self, *args):
random_number = random.randrange(10)
random_number = str(random_number)
print(random_number)
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.cols = 2 # used for our grid
self.add_widget(Label(text='OEE'))
self.add_widget(Label(text=self.zufall))
class EpicApp(App):
def build(self):
t = ConnectPage()
Clock.schedule_interval(t.zufall, 2)
return t
if __name__ == "__main__":
EpicApp().run()
Can someone of you give me a hint?
Firstly you have to return your random number from your zufall function, and call that function from your __init__ like this:
# runs on initialization
def zufall(self, *args):
random_number = random.randrange(10)
random_number = str(random_number)
return random_number
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.cols = 2 # used for our grid
self.add_widget(Label(text='OEE'))
self.add_widget(Label(text=self.zufall()))

Python How to influence running program

Button Start alarm starts ringing of alarm. I want to stop ringing by button Stop alarm. I don't know to influece running program. How must I repair function stop_alarm?
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.widget import Widget
import winsound
class ControlPanel(BoxLayout):
def __init__(self, **kwargs):
# make sure we aren't overriding any important functionality
super(ControlPanel, self).__init__(**kwargs)
self.alarm_status = True
self.orientation = "vertical"
butOn = Button(text = "Start alarm: ", on_release = self. start_alarm)
butStop = Button(text = "Stop alarm: ", on_release = self.stop_alarm)
self.add_widget(butOn)
self.add_widget(butStop)
def start_alarm(self, obj):
while self.alarm_status == True:
winsound.PlaySound("alarm.wav", winsound.SND_FILENAME)
def stop_alarm(self, obj):
self.alarm_status = False
class LifeApp(App):
def build(self):
return ControlPanel()
if __name__ == '__main__':
LifeApp().run()
The main problem with your code is that you have a while loop on your main GUI thread. So what you need to do is to run the start_alarm on a different thread than your main GUI thread for the GUI thread to be responsive.
As for not being able to play alarm next time, you didn't set the alarm_status flag to True again.Once you have that you can start and stop the sound as many times you want.
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.widget import Widget
import time
import winsound
import threading
class ControlPanel(BoxLayout):
def __init__(self, **kwargs):
# make sure we aren't overriding any important functionality
super(ControlPanel, self).__init__(**kwargs)
self.alarm_status = True
self.orientation = "vertical"
butOn = Button(text = "Start alarm: ", on_release = self.start_thread)
butStop = Button(text = "Stop alarm: ", on_release = self.stop_alarm)
self.add_widget(butOn)
self.add_widget(butStop)
def start_alarm(self, obj):
while self.alarm_status == True:
winsound.PlaySound("alarm.wav", winsound.SND_FILENAME)
#Set Alarm_Status True so that next time it works
self.alarm_status = True
def stop_alarm(self, obj):
self.alarm_status = False
#Function to run your start_alarm on a different thread
def start_thread(self,obj):
t1 = threading.Thread(target=self.start_alarm,args=(obj,))
t1.start()
class LifeApp(App):
def build(self):
return ControlPanel()
if __name__ == '__main__':
LifeApp().run()
Hope this helps!

Change screens with python logic (Kivy Screen manager)

I can't find the syntax for setting on_press in python code to change the screen anywhere. I keep getting errors for anything like Button(text = 'hi', on_press = self.current = 'start_menu. Here's the code and it works as is.
class LoadMenu(Screen):
def __init__(self, **kwargs):
super(LoadMenu, self).__init__(**kwargs)
Clock.schedule_once(self.update)
def update(self, dt):
L = [x for x in range(len(os.listdir('saves')))]
for x in L:
x = self.add_widget(Button(text = os.listdir('saves')[x]))
I haven't positioned the buttons so they just are on top of each other but I can fix that later. What I need to happen is for each button to change to the play screen on press so that will be the same for each button but I also need each one to load the Shelve file they a referencing.(I know I'll need another function for that) Can I have an on_press trigger two events at once, and again how do I set it in the python code?
Consider the following programme:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen
from kivy.uix.button import Button
from kivy.clock import Clock
from kivy.properties import StringProperty
dirlist = ['aaa', 'bbb', 'ccc', 'ddd']
class MyButton(Button):
prop = StringProperty('')
def on_press(self):
print "Class-defined on_press handler (I'm {})".format(self.text)
def other_on_press_handler(sender):
print "other_on_press_handler, from {}".format(sender.text)
def some_func(text):
print "yeah: " + text
class LoadMenu(Screen):
def __init__(self, **kwargs):
super(LoadMenu, self).__init__(**kwargs)
Clock.schedule_once(self.update)
def on_press_handler(self, sender):
print "on_press_handler, from {}".format(sender.text)
self.parent.current = 'sc2'
def yet_another_on_press_handler(self, sender):
print "yet_another_on_press_handler, from {}".format(sender.text)
self.parent.current = 'sc2'
def update(self, dt):
for x in range(len(dirlist)):
my_b = Button(text = dirlist[x], on_press=self.on_press_handler)
self.parent.ids.button_container.add_widget(my_b)
if x > 1:
my_b.bind(on_press=other_on_press_handler)
if x == 3:
my_b.bind(on_press=lambda sender: some_func("Whoa, lambda was here ({})".format(sender.text)))
for x in range(len(dirlist)):
my_b = MyButton(text = 'my '+ dirlist[x], prop="{} {}".format(dirlist[x], x))
self.parent.ids.button_container.add_widget(my_b)
my_b.bind(on_press=self.yet_another_on_press_handler)
root = Builder.load_string("""
ScreenManager:
LoadMenu:
name: 'sc1'
GridLayout:
cols: 4
id: button_container
Screen:
name: 'sc2'
BoxLayout:
Button:
text: "Go back"
on_press: root.current = 'sc1'
""")
class MyApp(App):
def build(self):
return root
if __name__ == '__main__':
a = MyApp()
a.run()
Let's start by looking at the update method in LoadMenu: In the first loop, a bunch of buttons is generated, and each receives an on_press callback at creation. The last two buttons in the loop get bound to another callback, and the last example shows how to use a lambda expression to generate a callback.
In the second for loop, we instantiate object of class MyButton, a child of Button. Note that we also define an on_press handler in the class definition; this gets called in addition to other functions we may have bound.
But really, this is actually all pretty nicely explained in the kivy Events and Properties docs.

Categories