OCR using Kivy and Screenmanager issue passing variable between screens - python

I am building an OCR application for visually impaired users. I'm wanting the app to open straight away onto the camera screen, when the user takes a pic on button press I want ocr process to occur and display the output on the text screen in a lbl or txtbox and have a TTS read out what the text says. My issue is that i am having trouble obtaining the output of ocr and displaying it, I'm not familiar with screenmanager or python. ideally the opencv and tesseract process would occur in same function as the capture however i cant get the output recognised on the following screen. heres some code, any suggestions and help appreciated!
# Importing the libraries
import cv2
import pytesseract
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen
pytesseract.pytesseract.tesseract_cmd = r'D:/pytesseract/tesseract.exe'
# voice_text = ""
# for i in ocrtext.split():
# voice_text += i + ' '
# voice_text = voice_text[:-1]
# voice_text
# engine = pyttsx3.init()
# engine.setProperty("rate", 145)
# voices = engine.getProperty('voices')
# engine.setProperty('voice', voices[0].id)
# engine.say(voice_text)
# engine.runAndWait()
class CameraScreen(Screen):
def capture(self):
camera = self.ids['camera']
camera.export_to_png("./picforocr.png")
image = cv2.imread("./picforocr.png")
ocrtext = pytesseract.image_to_string(image)
class TextScreen(Screen):
pass
GUI = Builder.load_string("""
GridLayout:
cols: 1
ScreenManager:
id: screen_manager
CameraScreen:
name: "camera_screen"
id: camera_screen
TextScreen:
name: "text_screen"
id: text_screen
<CameraScreen>:
orientation: 'vertical'
GridLayout:
cols: 1
Camera:
id: camera
resolution: (800, 800)
Button:
text: 'OCR!'
size_hint_y: None
height: '48dp'
on_press:
root.capture()
# root refers to <CameraScreen>
# app refers to TestCamera, app.root refers to the GridLayout: at the top
app.root.ids['screen_manager'].transition.direction = 'left'
app.root.ids['screen_manager'].current = 'text_screen'
<TextScreen>:
Label:
id: ocr_output
text:
Camerascreen.ocrtext
font_size: 20
Button:
text: "Do OCR Again"
size_hint_y: None
height: '48dp'
font_size: 50
on_press:
app.root.ids['screen_manager'].transition.direction = 'right'
app.root.ids['screen_manager'].current = 'camera_screen'
""")
class MyOCRApp(App):
def build(self):
return GUI
if __name__ == "__main__":
MyOCRApp().run()

This is basic code for passing texts from one class to another and also TextInput data. This is python code:
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
from kivy.uix.label import Label
from kivy.uix.screenmanager import ScreenManager, Screen, SlideTransition
class FirstPage(FloatLayout):
def switch_screen(self):
secondpage = self.login_name = self.ids.login_name.text
myapp.secondpage.update_name1(secondpage)
secondpage = self.password_name = self.ids.password_name.text
myapp.secondpage.update_name2(secondpage)
myapp.screen_manager.transition = SlideTransition(direction='left', duration=.25)
myapp.screen_manager.current = 'SecondPage'
class SecondPage(FloatLayout):
def switch_back(self):
myapp.screen_manager.transition = SlideTransition(direction='right', duration=.25)
myapp.screen_manager.current = 'FirstPage'
def update_name1(self, name_login):
self.ids.name_login.text = (f'{name_login}:')
def update_name2(self, name_password):
self.ids.name_password.text = (f'{name_password}:')
class MyApp(App):
def build(self):
self.screen_manager = ScreenManager()
self.firstpage = FirstPage()
screen = Screen(name='FirstPage')
screen.add_widget(self.firstpage)
self.screen_manager.add_widget(screen)
self.secondpage = SecondPage()
screen = Screen(name='SecondPage')
screen.add_widget(self.secondpage)
self.screen_manager.add_widget(screen)
return self.screen_manager
myapp = MyApp()
myapp.run()
And this is kivy code:
FirstPage:
<FirstPage>:
TextInput:
id: login_name
size_hint: .65, .08
multiline: False
font_size: 20
pos_hint: {'x': .2, 'y': .57}
TextInput:
id: password_name
size_hint: .65, .08
multiline: False
font_size: 20
pos_hint: {'x': .2, 'y': .47}
Button:
text: "First"
size_hint: .1, .1
on_release: root.switch_screen()
<SecondPage>:
Button:
text: "Second"
size_hint: .1, .1
on_release: root.switch_back()
Label:
id: name_login
text: "Login"
size_hint: .2, .2
pos_hint: {'x': .2, 'y': .57}
Label:
id: name_password
text: "Password"
size_hint: .2, .2
pos_hint: {'x': .2, 'y': .47}

Related

Kivy - ScreenManager saying it does not recognize another screen name despite it being there?

So, I wanted to create an app that created tasks/habits in kivy. Basically, there would be a screen that shows you your tasks/habits, and you could click on a button to take you to another screen to create a new task/habit. You would input information about the task/habit in that screen, and click the submit button. The submit button would add the task/habit to the first screen. However, when I run my code, it works the first time. I can go to the second screen, add my habit/code and then go back to the first screen. However, when I click the button on the first screen, it gives me an error.
The error being: kivy.uix.screenmanager.ScreenManagerException: No Screen with name "second".
Here is my code:
main.py:
from kivy.lang import Builder
from kivy.properties import ObjectProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.widget import Widget
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.image import Image
from PIL import Image
import numpy as np
class FirstWindow(Screen):
def add_label(self, name, time, date):
label = Label(text= f' {name}, {time}, {date}')
self.ids.boxlayout.add_widget(label)
class SecondWindow(Screen):
a_task = False
a_habit = False
name = ""
time = ""
date = ""
def task_button(self):
self.a_task = True
self.a_habit = False
def habit_button(self):
self.a_habit = True
self.a_task = False
def submit_button(self):
self.name = self.ids.the_name.text
self.time = f'{self.ids.time_spinner_1.text}:{self.ids.time_spinner_2.text}'
self.date = f'{self.ids.date_spinner_1.text}/{self.ids.date_spinner_2.text}'
def get_name(self):
return self.name
def get_time(self):
return self.time
def get_date(self):
return self.date
kv = Builder.load_file('Button.kv')
class ButtonApp(App):
def build(self):
sm = ScreenManager()
sm.add_widget(FirstWindow())
sm.add_widget(SecondWindow())
return sm
if __name__ == '__main__':
ButtonApp().run()
Button.kv:
<FirstWindow>:
name: "first"
BoxLayout:
id: boxlayout
orientation: "vertical"
canvas.before:
Color:
rgba: (0.3,0.33,0.3,1)
Rectangle:
pos: self.pos
size: self.size
FloatLayout:
Label:
text: "To Do List"
font_size: 32
pos_hint: { 'right': 0.65, 'top': 1.4 }
Button:
text: "add a task"
on_release: root.manager.current = "second"
<SecondWindow>:
name: "second"
BoxLayout:
orientation: "vertical"
spacing: "10dp"
canvas.before:
Color:
rgba: (0.3,0.33,0.3,1)
Rectangle:
pos: self.pos
size: self.size
FloatLayout:
Label:
text: "Add A Task"
font_size: 32
pos_hint: { 'right': 0.65, 'top': 1.2 }
BoxLayout:
orientation: "horizontal"
Button:
text: "task"
on_press: root.task_button()
Button:
text: "habit"
on_press: root.habit_button()
TextInput:
id: the_name
text: "Name"
Label:
text: "alert"
BoxLayout:
orientation: "horizontal"
Spinner:
id: time_spinner_1
text: "00"
values: ['1','2','3','4','5','6','7','8','9','10','11', '12']
Spinner:
id: time_spinner_2
text: "00"
values: ['01','02','03','04','05','06','07','08','09','10','11', '12', '13','14','15','16','17','18','19','20','21','22','23','24','25','26','27','28','29','30','31','32','33','34','35','36','37','38','39','40','41','42','43','44','45','46','47','48','49','50','51','52','53','54','55','56','57','58','59']
BoxLayout:
orientation: "horizontal"
Spinner:
id: date_spinner_1
text: "00"
values: ['1','2','3','4','5','6','7','8','9','10','11', '12']
Spinner:
id: date_spinner_2
text: "00"
values: ['01','02','03','04','05','06','07','08','09','10','11', '12', '13','14','15','16','17','18','19','20','21','22','23','24','25','26','27','28','29','30','31']
Button:
text: "submit"
on_press: root.submit_button()
on_release:
root.manager.current = "first"
root.manager.get_screen("first").add_label(root.get_name(), root.get_time(), root.get_date())
Your code:
def submit_button(self):
self.name = self.ids.the_name.text
self.time = f'{self.ids.time_spinner_1.text}:{self.ids.time_spinner_2.text}'
self.date = f'{self.ids.date_spinner_1.text}/{self.ids.date_spinner_2.text}'
changes the name property of the SecondWindow Screen, so trying to change Screen to the second will no longer work. It looks like you are trying to use name for some other purpose. I suggest you use a variable with a different name.

Question regarding changing screens in KivyMD

I'm new to KIVYMD and have been trying to play around by creating a log in screen that transfers the user to a new page. I've gotten making the core of the screen down, like adding the textfields and buttons, but am not sure how I can implement a screen changing functionality to my code. Any help is greatly appreciated.
For reference here is my main code block:
from kivymd.app import MDApp
from kivy.lang.builder import Builder
from helpers import username_helper,password_helper
from kivy.uix.screenmanager import Screen
from kivymd.uix.button import MDRectangleFlatButton
class Demo_app(MDApp):
def build(self):
screen = Screen()
self.theme_cls.primary_palette= "Pink"
self.username= Builder.load_string(username_helper)
screen.add_widget(self.username)
self.password = Builder.load_string(password_helper)
screen.add_widget(self.password)
login = MDRectangleFlatButton(text="Log In", pos_hint={"center_x": 0.5, "center_y":0.4})
screen.add_widget(login)
signin = MDRectangleFlatButton(text="Sign Up", pos_hint={"center_x": 0.5, "center_y": 0.3})
screen.add_widget(signin)
return screen
Demo_app().run()
And here is my .kv file:
username_helper="""
MDTextField:
hint_text: "Create/Enter your Username"
helper_text:"Or click here if you forgot your Username"
helper_text_mode: "on_focus"
icon_right: "language-python"
icon_right_color: app.theme_cls.primary_color
pos_hint:{"center_x":0.5,"center_y":0.6}
size_hint_x:None
width:300
"""
password_helper="""
MDTextField:
hint_text: "Create/Enter your Password"
helper_text:"Or click here if you forgot your password "
helper_text_mode: "on_focus"
icon_right: "language-python"
icon_right_color: app.theme_cls.primary_color
pos_hint:{"center_x":0.5,"center_y":0.5}
size_hint_x:None
width:300
"""
I think you want to transfer those textinput data to a label in different class. I think this is what you need.(keep an eye on ids):
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
from kivy.uix.label import Label
from kivy.uix.screenmanager import ScreenManager, Screen, SlideTransition
class FirstPage(FloatLayout):
def switch_screen(self):
secondpage = self.login_name = self.ids.login_name.text
myapp.secondpage.update_name1(secondpage)
secondpage = self.password_name = self.ids.password_name.text
myapp.secondpage.update_name2(secondpage)
myapp.screen_manager.transition = SlideTransition(direction='left', duration=.25)
myapp.screen_manager.current = 'SecondPage'
class SecondPage(FloatLayout):
def switch_back(self):
myapp.screen_manager.transition = SlideTransition(direction='right', duration=.25)
myapp.screen_manager.current = 'FirstPage'
def update_name1(self, name_login):
self.ids.name_login.text = (f'{name_login}:')
def update_name2(self, name_password):
self.ids.name_password.text = (f'{name_password}:')
class MyApp(App):
def build(self):
self.screen_manager = ScreenManager()
self.firstpage = FirstPage()
screen = Screen(name='FirstPage')
screen.add_widget(self.firstpage)
self.screen_manager.add_widget(screen)
self.secondpage = SecondPage()
screen = Screen(name='SecondPage')
screen.add_widget(self.secondpage)
self.screen_manager.add_widget(screen)
return self.screen_manager
myapp = MyApp()
myapp.run()
Here's kivy code:
FirstPage:
<FirstPage>:
TextInput:
id: login_name
size_hint: .65, .08
multiline: False
font_size: 20
pos_hint: {'x': .2, 'y': .57}
TextInput:
id: password_name
size_hint: .65, .08
multiline: False
font_size: 20
pos_hint: {'x': .2, 'y': .47}
Button:
text: "First"
size_hint: .1, .1
on_release: root.switch_screen()
<SecondPage>:
Button:
text: "Second"
size_hint: .1, .1
on_release: root.switch_back()
Label:
id: name_login
text: "Login"
size_hint: .2, .2
pos_hint: {'x': .2, 'y': .57}
Label:
id: name_password
text: "Password"
size_hint: .2, .2
pos_hint: {'x': .2, 'y': .47}

random screen display with kivy

i am trying to make an app, a game actually that will display random screens when the "NEXT" button is touched, so i made the screens and the labels to be displayed on each screen but i cant get it to display a random screen when the "NEXT" button is touched, it just follows a pattern, would anyone help me here? heres the code:
#: import FadeTransition kivy.uix.screenmanager.FadeTransition
#: import Image kivy.uix.image.Image
#: import SoundLoader kivy.core.audio.SoundLoader
ScreenManagement:
transition: FadeTransition()
MainScreen:
GameScreen:
GameScreen2:
GameScreen3:
GameScreen4:
<Button>:
font_size: 12
size_hint: 0.2, 0.1
<MainScreen>:
name: "main"
FloatLayout:
Button:
text: "START GAME"
color: 1,0,1,1
pos_hint: {"x": 0, "y":0}
on_release: app.root.current = "game"
Button:
text: "QUIT"
color: 1,0,0,1
pos_hint: {"x": .8, "y": 0}
on_release: quit()
Button:
text: "SOUND"
color: 0,1,0,1
pos_hint: {"x":.2 , "y": .4}
on_press: app.play_sound1()
<GameScreen>:
name: "game"
FloatLayout:
Label:
text: "Python\nSnowden\nMr.Robot"
font_size: 40
color: 0,1,0,1
pos_hint: {"x":0, "y": 0}
Button:
text: "Home"
on_release: app.root.current = "main"
color: 1,0,0,1
pos_hint: {"right":1, "top":1}
Button:
text: "Next"
on_release: app.root.current = "game2"
color: 0,1,0,1
pos_hint: {"x":0, "y":0}
<GameScreen2>:
name: "game2"
FloatLayout:
Label:
text: "Banana\n\nOrange\n\nTea\n\nSleep"
font_size: 40
color: 0,1,0,1
pos_hint: {"x":0, "y": 0}
Button:
text: "Home"
on_release: app.root.current = "main"
color: 1,0,0,1
pos_hint: {"right":1, "top":1}
Button:
text: "Next"
on_release: app.root.current = "game3"
color: 0,1,0,1
pos_hint: {"x": 0, "y": 0}
<GameScreen3>:
name: "game3"
FloatLayout:
Label:
text: "Assembly\n\nRuby\n\nC"
font_size: 40
color: 0,1,0,1
pos_hint: {"x":0, "y":0}
Button:
text: "Home"
on_release: app.root.current = "main"
color: 1,0,0,1
pos_hint: {"right":1, "top":1}
Button:
text: "Next"
on_release: app.root.current = "game4"
color: 0,1,0,1
pos_hint: {"x": 0, "y": 0}
<GameScreen4>:
name: "game4"
FloatLayout:
Label:
text: "Prolog\n\nPygame\n\nC++"
font_size: 40
color: 0,1,0,1
pos_hint: {"x":0, "y":0}
Button:
text: "Home"
on_release: app.root.current = "main"
color: 1,0,0,1
pos_hint: {"right":1, "top":1}
the above is the kv code, sorry for the mess im an amateur when it comes to kivy
and heres the python side code:
from kivy.app import App
from kivy.clock import Clock
from kivy.lang import Builder
from kivy.uix.label import Label
from kivy.uix.widget import Widget
from kivy.core.audio import SoundLoader
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
class MainScreen(Screen):
pass
class GameScreen(Screen):
pass
class GameScreen2(Screen):
pass
class GameScreen3(Screen):
pass
class GameScreen4(Screen):
pass
class ScreenManagement(ScreenManager):
pass
presentation = Builder.load_file("quora.kv")
class MainApp(App):
def build(self):
self.load_sounds()
return presentation
def load_sounds(self):
self.sounds = {}
for i in range(10):
fname = 'sound' + str(i+1) + '.wav'
self.sounds[i] = SoundLoader.load(fname)
def play_sound1(self):
sound = self.sounds.get(0)
if sound is not None:
sound.volume = 0.5
sound.play()
def play_sound2(self):
sound = self.sounds.get(1)
if sound is not None:
sound.volume = 0.5
sound.play()
if __name__ == "__main__":
MainApp().run()
this is the sample i made for you because the original one is way bigger than this i dont know how to use somewhat of a LOOP to generate screen so i made more that 20 screens on the original code so, and if you could help me figure out how can i STOP THE MENU SONG when i hit the "START" BUTTON, so that i can hit the "SONG" BUTTON on SCREEN1 to PLAY its SONG i would be gratefull. thanks you for the patience.
Display random screens when the "NEXT" button is touched
Use screen_names
screen_names
List of the names of all the Screen widgets added. The list is
read only.
screens_names is an AliasProperty and is read-only. It is updated
if the screen list changes or the name of a screen changes.
Snippets
#:import choice random.choice
...
Button:
text: "Next"
on_release:
root.manager.current = choice(root.manager.screen_names[1:])
color: 0,1,0,1
pos_hint: {"x":0, "y":0}
Stop / Play Music
You might want to use a ToggleButton instead of Button for playing music. Please refer to the example below.
Example
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.togglebutton import ToggleButton
from kivy.core.audio import SoundLoader
from kivy.properties import ObjectProperty
class MusicScreen(Screen):
enter = ObjectProperty(None)
text_input = ObjectProperty(None)
stop = ObjectProperty(None)
musicbutton = ToggleButton()
class ScreenManagement(ScreenManager):
pass
class MainApp(App):
sound = ObjectProperty(None, allownone=True)
def build(self):
return ScreenManagement()
def on_state(self, state, filename):
print("ONSTATE!!!")
print("\tstate=", state)
if self.sound is None:
self.sound = SoundLoader.load(filename)
# stop the sound if it's currently playing
if self.sound.status != 'stop':
self.sound.stop()
if state == "down":
self.sound.volume = .5
self.sound.play()
else: # if state == "normal":
if self.sound:
self.sound.stop()
# self.sound.unload()
self.sound = None
if __name__ == "__main__":
MainApp().run()
main.kv
#:kivy 1.11.0
<ScreenManagement>:
MusicScreen:
name: 'music'
<MusicScreen>:
text_input: text_input
id: "music"
name: "music"
BoxLayout:
size: root.size
pos: root.pos
orientation: "vertical"
FileChooserListView:
id: filechooser
rootpath: "/home/iam/Music/"
on_selection: text_input.text = self.selection and self.selection[0] or ''
TextInput:
id: text_input
size_hint_y: None
height: 50
multiline: False
ToggleButton:
size_hint: 1, .2
text: "Play/Stop By File"
on_state: app.on_state(self.state, text_input.text)
ToggleButton:
id: musicbutton
size_hint: 1, .2
text: "Play/Stop By Title"
on_state: app.on_state(self.state, text_input.text)

Kivy: changing image source on screen

After much headbanging, I've created an app that opens the FileChooser and picks an image. A function will then transform the image and change it on the screen.
< FirstScreen > is just something to start with, relatively unimportant.
< SecondScreen > is the file chooser. The path may need editing. < ThirdScreen > shoudl show the image along with buttons that will eventually lead elsewhere.
I suspect the problem is that the line
sm.current = "_third_screen_"
is creating a new instance separate to everything else I've passed items too. How do I show the image I selected?
from kivy.lang import Builder
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty, StringProperty
Builder.load_string("""
<MyScreenManager>:
FirstScreen:
SecondScreen:
ThirdScreen:
<FirstScreen>:
name: '_first_screen_'
BoxLayout:
orientation: "horizontal"
Label:
id: first_screen_label
text: "Hi, I'm the home page"
BoxLayout:
orientation: "vertical"
Button:
text: "Okay!"
on_press: root.manager.current = '_second_screen_'
Button:
text: "Cancel!"
on_press: app.stop()
<SecondScreen>:
name: '_second_screen_'
id: file_chooser
BoxLayout:
id: file_chooser_box_layout
orientation: "horizontal"
Button
text: "Open"
on_press:
root.callback_image_and_other_stuff(file_chooser_list_view.selection)
FileChooserListView:
id: file_chooser_list_view
<ThirdScreen>:
name: '_third_screen_'
BoxLayout:
orientation: "vertical"
id: third_screen
Label:
id: main_title
text: "Upload"
size_hint: (1, 0.1)
Image:
id: main_image
source: root.img
size_hint: (1, 0.75)
BoxLayout:
orientation: "horizontal"
padding: 10
size_hint: (1, 0.15)
Button:
text: "Okay"
size_hint: (0.5, 1)
on_press: image_viewer.image_accepted_by_user(filechooser.selection)
Button:
text: "Cancel"
size_hint: (0.5, 1)
on_press: root.manager.current = '_first_screen_'
""")
class FirstScreen(Screen):
pass
class SecondScreen(Screen):
def callback_image_and_other_stuff(self, new_image_address):
# do other stuff here also, then pass new_image_address along
new_image_address = new_image_address[0].replace("\\", "/")
third_screen = ThirdScreen()
third_screen.callback_image(new_image_address)
class ThirdScreen(Screen):
img = ObjectProperty(None)
def __init__(self, **kwargs):
super(Screen, self).__init__(**kwargs)
def callback_image(self, new_image_address):
sm.current = "_third_screen_"
self.img = new_image_address
self.ids.main_image.source = self.img
print(self.img)
# Create the screen manager
sm = ScreenManager() # Problem?
sm.add_widget(FirstScreen(name='_first_screen_'))
sm.add_widget(SecondScreen(name='_second_screen_'))
sm.add_widget(ThirdScreen(name='_third_screen_'))
class MyApp(App):
def build(self):
return sm
if __name__ == '__main__':
MyApp().run()
Every time you use some_obj = SomClass() you are creating a new object, in your case that is what you are doing, you are creating a new ThirdScreen different from the one shown by that you do not observe the image, the solution is that you have to access to the initial object using the ScreenManager and name screen.
from kivy.lang import Builder
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty, StringProperty
Builder.load_string("""
<FirstScreen>:
BoxLayout:
orientation: "horizontal"
Label:
id: first_screen_label
text: "Hi, I'm the home page"
BoxLayout:
orientation: "vertical"
Button:
text: "Okay!"
on_press: root.manager.current = '_second_screen_'
Button:
text: "Cancel!"
on_press: app.stop()
<SecondScreen>:
id: file_chooser
BoxLayout:
id: file_chooser_box_layout
orientation: "horizontal"
Button
text: "Open"
on_press:
root.callback_image_and_other_stuff(file_chooser_list_view.selection)
FileChooserListView:
id: file_chooser_list_view
<ThirdScreen>:
BoxLayout:
orientation: "vertical"
id: third_screen
Label:
id: main_title
text: "Upload"
size_hint: (1, 0.1)
Image:
id: main_image
source: root.img
size_hint: (1, 0.75)
BoxLayout:
orientation: "horizontal"
padding: 10
size_hint: (1, 0.15)
Button:
text: "Okay"
size_hint: (0.5, 1)
on_press: image_viewer.image_accepted_by_user(filechooser.selection)
Button:
text: "Cancel"
size_hint: (0.5, 1)
on_press: root.manager.current = '_first_screen_'
""")
class FirstScreen(Screen):
pass
class SecondScreen(Screen):
def callback_image_and_other_stuff(self, new_image_address):
if new_image_address:
third_screen = self.manager.get_screen("_third_screen_")
# do other stuff here also, then pass new_image_address along
new_image_address = new_image_address[0].replace("\\", "/")
third_screen.callback_image(new_image_address)
class ThirdScreen(Screen):
img = ObjectProperty(None)
def __init__(self, **kwargs):
super(Screen, self).__init__(**kwargs)
def callback_image(self, new_image_address):
sm.current = "_third_screen_"
self.img = new_image_address
self.ids.main_image.source = self.img
print(self.img)
# Create the screen manager
sm = ScreenManager() # Problem?
sm.add_widget(FirstScreen(name='_first_screen_'))
sm.add_widget(SecondScreen(name='_second_screen_'))
sm.add_widget(ThirdScreen(name='_third_screen_'))
class MyApp(App):
def build(self):
return sm
if __name__ == '__main__':
MyApp().run()

How do you reset the position of an Animation in Kivy

I'm trying to get a handle on Animations. The problem that I'm having is that my Animation plays once but does not repeat.
What I want to do: I want the image to slide up, and then off the screen. Then appear at the bottom of the screen and again slide up and off.
What actually happens: The Image slides "up" the screen, disappears off of the screen and that's it. It doesn't reset back to its original location, and it doesn't repeat.
My question is: How can I reset the position of the image so that it continues in a never-ending cycle (until the "Stop Animation" button is clicked)?
The animated object is the Image that's setup in .kv language it's directly under MyScreen
If you want to see how the animation plays just change the name of the image "binary_rain.png" in kv lang to w/e you have :)
import kivy
from kivy.uix.textinput import TextInput
from kivy.uix.screenmanager import ScreenManager, Screen, FallOutTransition
from kivy.app import App
from kivy.lang import Builder
from kivy.clock import Clock
from kivy.uix.actionbar import ActionBar
from kivy.factory import Factory
from kivy.animation import Animation
class MyScreen(Screen):
def __init__(self, **kwargs):
super(MyScreen, self).__init__(**kwargs)
Clock.schedule_interval(self.example_func, 20.0)
self._test_bool = False
self.water = Animation(pos=(0, 800)) # It's setup in __init__ ; here
self.water &= Animation(size=(800, 800), duration=2, t='in_back') # and then here
def example_func(self, dt):
if self._test_bool == True:
self.ids.text_input_test_id.foreground_color = 255,0,0,1
self.ids.text_input_test_id.text = "The color has been changed"
self._test_bool = False
elif self._test_bool != True:
self.ids.text_input_test_id.foreground_color = 0, 255, 0, 1
self.ids.text_input_test_id.text = "The color has changed"
self._test_bool = True
def test_func(self):
if self._test_bool == True:
self.ids.text_input_2.foreground_color = 255,0,0,1
self.ids.text_input_2.text = "The color has been changed"
self._test_bool = False
elif self._test_bool != True:
self.ids.text_input_2.foreground_color = 0, 255, 0, 1
self.ids.text_input_2.text = "The color has changed"
self._test_bool = True
def test_func_two(self):
if self._test_bool == True:
self.ids.text_input_3.foreground_color = 255,0,0,1
self.ids.text_input_3.text = "The color has been changed"
self._test_bool = False
elif self._test_bool != True:
self.ids.text_input_3.foreground_color = 0, 255, 0, 1
self.ids.text_input_3.text = "The color has changed"
self._test_bool = True
def start_my_animation(self): # this is what starts the animation
self.water.repeat = True
self.water.start(self.ids.animated_bacground)
def stop_my_animation(self): # this is what should end the animation
self.water.stop(self.ids.animated_bacground)
class MyScreenManager(ScreenManager):
pass
root_widget = Builder.load_string('''
#:import FallOutTransition kivy.uix.screenmanager.FallOutTransition
#:import Config kivy.config
#:import Window kivy.core.window
#:import Clock kivy.clock
#:import ActionBar kivy.uix.actionbar
#:import Animation kivy.animation.Animation
MyScreenManager:
transition: FallOutTransition()
MyScreen:
<MyScreen>:
name: 'example_screen'
Image:
id: animated_bacground
size: self.size
pos: self.pos
source: 'binary_rain.png'
TextInput:
id: text_input_test_id
size_hint: .3, .05
pos_hint: {'x': .35, 'y': .85}
text: 'Hello'
font: '12sp'
TextInput:
id: text_input_2
size_hint: .3, .05
pos_hint: {'x': .35, 'y': .70}
text: 'Hello'
font: '12sp'
TextInput:
id: text_input_3
size_hint: .3, .05
pos_hint: {'x': .35, 'y': .65}
text: 'Button 3'
Button:
id: test_button_id
size_hint: .3, .05
pos_hint: {'x': .5, 'y': .5}
text: 'Click me'
on_press: root.test_func()
ActionBar:
pos_hint: {'top':1}
ActionView:
use_separator: True
ActionPrevious:
title: 'Menu'
with_previous: False
ActionOverflow:
ActionButton:
text: 'click me'
on_press: root.test_func_two()
ActionButton:
text: 'Start Animation'
on_press: root.start_my_animation()
ActionButton:
text: 'Stop Animation'
on_press: root.stop_my_animation()
ActionButton:
text: 'Button 2'
ActionButton:
text: 'Button 3'
ActionGroup:
text: 'Group1'
ActionButton:
text: 'Button 5'
ActionButton:
text: 'Btn6'
ActionButton:
text: 'Btn7'
''')
Factory.unregister('ActionPrevious')
class TestApp(App):
def build(self):
self.title = 'Example App'
return root_widget
TestApp().run()
Your animation is setting the size, not the pos...
also you are doing both animations in the same time using &=, you need +=
self.water = Animation(pos=(0, 800))
# notice the changes * pos * and * += *
self.water += Animation(pos=(800, 800), duration=2, t='in_back') # and then here

Categories

Resources