switching screen after 3 seconds staying in the screen - python

Problem is with screenmanager where i have 2 screens say loadingscreen and menuscreen .
In starting I load loading screen first and after 3 seconds i switch it to menuscreen which help of clock schedule .
On menu screen I have a button which when pressed takes us back to loading screen .
Now i want to move back to menu screen after 3 seconds of loading screen is active .. Can someone suggest best way to do it . Below is a code which explains what i have and what i need :
I know changing below code to have Clock.schedule_interval(self.callNext, 3) in LoadingScreen Class will do the job but i am looking for a better option which is much more efficient
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen,FallOutTransition
from kivy.properties import ObjectProperty,NumericProperty
from kivy.uix.image import Image
from kivy.graphics import Color
from kivy.clock import Clock
gui_v3 = '''
<PlayScreen>:
play_Button: playButton
canvas.before:
Color:
rgb: (0, 0, 1)
GridLayout:
rows:1
size_hint: .1,.1
pos_hint: {'center_x': .5, 'center_y': .5}
Button:
id: playButton
size_hint_x: None
width: 100
text: 'Play !'
font_size: 12
bold: True
italic: False
border: 10,10,10,10
color: (0.5, 1, 0.5, 1)
on_press: root.playButton_press()
<LoadingScreen>:
canvas:
Color:
rgba: 0.4, 0.4, 0.4, 1
Rectangle:
pos: root.center
size: (32, 32)
BoxLayout:
Label:
text: 'JB'
font_size: 100
Label:
text: 'Loading...'
font_size: 10
'''
class PlayScreen(Screen):
play_Button = ObjectProperty(None)
def __init__(self, **kwargs):
super(PlayScreen, self).__init__(**kwargs)
Clock.schedule_interval(self.update, 1.0/2)
def update(self,dt):
print "Current screen is ",self.manager.current
def playButton_press(self):
print "Hi Play button is pressed"
sm.current = 'loading'
class LoadingScreen(Screen):
def __init__(self, **kwargs):
super(LoadingScreen, self).__init__(**kwargs)
Clock.schedule_once(self.callNext, 3)
def callNext(self,dt):
self.manager.current = 'play'
print "Hi this is call Next Function of loading 1"
# Create the screen manager
Builder.load_string(gui_v3)
sm = ScreenManager(transition= FallOutTransition())
sm.add_widget(LoadingScreen(name='loading'))
sm.add_widget(PlayScreen(name='play'))
class MyJB(App):
def build(self):
print sm.screen_names
return sm
if __name__ == '__main__':
MyJB().run()

You should use the screen's on_enter event. Simply do this in the kv file:
<LoadingScreen>:
on_enter: Clock.schedule_once(self.callNext, 3)
Also a the top of the kv you need to import Clock, #:import Clock kivy.clock.Clock. Now every time the screen is opened it'll schedule the callback.

Related

ProgressBar in Kivy (automatically loading)

I want a ProgressBar to start loading automatically when opening the application (similar to a loading screen). I have already created the bar. However, I've been trying to get the automatic loading process for two days. Does one of you have an idea?
Thanks in advance!
py-file:
from kivy.uix.screenmanager import ScreenManager
from kivy.lang import Builder
from kivymd.app import MDApp
from kivy.clock import Clock
#Window.size = (1366, 768)
#Window.fullscreen = True
class GATR(MDApp):
def build(self):
global sm
sm = ScreenManager()
sm.add_widget(Builder.load_file("splash.kv"))
sm.add_widget(Builder.load_file("login.kv"))
return sm
def on_start(self):
Clock.schedule_once(self.login, 5)
def login(*args):
sm.current = "login"
if __name__=="__main__":
GATR().run()
kv-file (The file with the progress bar):
MDScreen:
name: "splash"
MDFloatLayout:
md_bg_color: 110/255, 123/255, 139/255, 1
Image:
source: "logo.png"
size: 50, 50
pos_hint: {"center_x":.5, "center_y":.6}
MDLabel:
text: "Text"
text_color: 255, 255, 255, 0
font_size: "60sp"
pos_hint: {"center_x":.51, "center_y":.25}
halign: "center"
font_name: "3.ttf"
ProgressBar:
id: pb
min: 0
max: 100
pos_hint: {"center_x": .5, "center_y": .1}
size_hint_x: .8
I think something like this should do the work.
def foo(self):
current = self.ids.pb.value #get current value of the progress bar
if current >= 100: #check when it hits 100%, stop it
return False
current += 1 #increment current value
self.ids.pb.value = current #update progress bar value
def on_start(self):
Clock.schedule_interval(self.foo, 1/25) #kivy clock object to time it
It is just an idea, you should play around with it and implement it correctly with your codebase.

I can't get Kivy screen manager to work in this specific app, I've made it work in other programs I literally cant get it to work in this app

so i'm learning kivy and I want to have a button bring me to a different screen to be able to set a alarm. I've made another file to learn how to transition between screens and its worked and all morning I've been trying to get it to work in my other app and I cant figure out why it wont work in this app. The app works and runs but when I click the button nothing happens. For anyone reading and helping me I appreciate it.
python file
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.lang import Builder
from kivy.clock import Clock
from kivy.uix.screenmanager import ScreenManager, Screen
import time
class AlarmWindow(Screen):
pass
class ClockScreen(Screen):
def addAlarm(self):
print("add alarm")
class WindowManager(ScreenManager):
pass
Builder.load_file('myApp.kv')
class ClockApp(App):
def build(self):
return ClockScreen()
def on_start(self):
Clock.schedule_interval(self.updateClock, 1)
def updateClock(self, *args):
print(args)
#create time variable, if var doesnt work here create it in the ClockScreen class and call it here
hour = time.strftime("%H")
minute = time.strftime("%M")
clockTime = f'{hour}:{minute}'
#update label
self.root.ids.clock.text = clockTime
ca = ClockApp()
ca.run()
kv file
WindowManager:
ClockScreen:
AlarmWindow:
<ClockScreen>:
name: "main"
FloatLayout:
size: root.width, root.height
Label:
id: clock
text: "12:00"
font_size: 32
Button:
text: "Add Alarm"
size_hint: None, None
size: 150, 100
pos_hint: {'center_x': .5, 'center_y': 0.3}
on_release: app.root.current = 'second'
<AlarmWindow>:
name: "second"
FloatLayout:
size: root.width, root.height
Label:
text: "Create alarm here"
Button:
text: "Go Back"
on_release: app.root.current = 'main'

How to ensure proper functionality when adding widgets to Kivy

I am attempting to create a Kivy/Python application which gets the user to push a button on one screen, and in turn adds several widgets to the next screen. However, when I run the script, the button appears and can be clicked on the first page, and the widgets are visible on the second page, but they can not be interacted with.
Here is an example of my code, any help is appreciated:
py:
import kivy
kivy.require('1.11.1')
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.properties import ListProperty, StringProperty, ObjectProperty
from kivy.core.window import Window
from kivy.uix.label import Label
from kivy.uix.scrollview import ScrollView
from kivy.uix.button import Button
from kivy.uix.spinner import Spinner
sm = None
class RcGUITestApp(App):
def build(self):
global sm
Window.clearcolor = (0, 0, 0.35, 1)
sm = ScreenManager()
sm.add_widget(NewJobPage(name="new_job_page"))
sm.add_widget(IPMConfirmPage(name = "ipm_confirm_page"))
return sm
class NewJobPage(Screen):
def retrieve(self):
global rc
global sm
sm.get_screen("ipm_confirm_page").displayIPM()
class IPMConfirmPage(Screen):
grid = ObjectProperty(None)
def displayIPM(self):
for ipm in range(50):
self.grid.add_widget(Label(text="A"))
self.grid.add_widget(Spinner(text="B"))
self.grid.add_widget(Spinner(text="C"))
def main():
rc_gui = RcGUITestApp()
rc_gui.run()
if __name__ == "__main__":
main()
kv:
<NewJobPage>:
BoxLayout:
orientation: "horizontal"
size_hint: (1, .35)
Button:
text: "RETRIEVE"
pos_hint: {"center_x": .5, "center_y": .5}
size_hint: (.33, .33)
color: (1,1,1,1)
on_press:
root.retrieve()
root.manager.transition.direction = "left"
root.manager.transition.duration = .8
root.manager.current = "ipm_confirm_page"
<IPMConfirmPage>:
grid: Grid
GridLayout:
cols: 1
size_hint_x: 1
padding: 10
spacing: 10
BoxLayout:
size_hint: (1, 0.1)
Label:
text: "IPM"
Label:
text: "CD#"
Label:
text: "CONDUCTOR"
ScrollView:
GridLayout:
id: Grid
cols: 3
height: self.minimum_height
size_hint: 1, None
spacing: 50
padding: 30
First Page output
Second Page output
You need to provide the height of each widget added to grid. There are two solutions to the problem.
Method 1 - kv file
This method involves changing only the kv file by adding row_force_default: True and row_default_height: 40.
Snippets - kv file
ScrollView:
GridLayout:
row_force_default: True
row_default_height: 40
...
Method 2 - py file
This method involves changing only the py file by adding size_hint_y=None and height=40.
Snippets
def displayIPM(self):
for ipm in range(50):
self.grid.add_widget(Label(text="A", size_hint_y=None, height=40))
self.grid.add_widget(Spinner(text="B", size_hint_y=None, height=40))
self.grid.add_widget(Spinner(text="C", size_hint_y=None, height=40))

Kivy:I want window-sized buttons to be stacked on top of the screen

I want window-sized opaque black button to be stacked on top of the screen
and the button will be disappear and the screen below will be visible when I press the opaque black button.
I tried but failed all the time.
Below this is my code (.py)
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.image import Image
from kivy.animation import Animation
from kivy.clock import Clock
class First_Screen(Screen, BoxLayout):
pass
class ScreenManagement(ScreenManager):
pass
presentation = Builder.load_file("main.kv")
class TubucApp(App):
def build(self):
return presentation
TubucApp().run()
and this is my .kv file:
ScreenManagement:
transition:
First_Screen:
<First_Screen>: #<-i want fullscreen-sized opaque black button covers
#up this screen and will be disappear when i press the button
name: 'First_Screen'
BoxLayout:
orientation: 'horizontal'
spacing: 50
padding: [50, 50, 50, 50]
canvas:
Rectangle:
pos: self.pos
size: self.size
source: 'image/background.jpg'
Button:
id: campustown
width: 40
pos_hint: {'x' : 0, 'y':.45}
size_hint: [.6,.1]
background_normal:'image/test.png'
background_down:'image/test2.png'
border: (0,0,0,0)
font_size: 15
text: 'campus-town'
These two images show what I want to accomplish:
How can I do this?
Python code
Remove BoxLayout from class First_Screen()
Snippet - Py
class First_Screen(Screen):
pass
kv file
Add a on_release event for button
Set background_normal to background_down
Snippet - kv
<First_Screen>:
name: 'First_Screen'
Button:
id: campustown
background_normal: 'image/test.png'
background_down: 'image/test2.png'
border: (0,0,0,0)
font_size: 15
text: 'campus-town'
on_release:
self.background_normal = self.background_down
Output

Kivy: Modifying a child widget of another separate class

im currently looking into kivy to start with crossplatform development. i have a bit of python experience (but basic) and now wanted to code a little game in kivy to get into. i probably wont finish this but i like learning stuff while doing it with something im intrested in.
Anyway my "App" is supposed to be seperated in two seperate "screens" the top one is only used for displaying stuff and the all interactive stuff is controlled from the bottom "screen".
Now i want to display some text in old school way by getting it written letter by letter to the screen.
This is working fine but for some reason the Label widget is only updated on screen if i call the "print_something" function from the top screen, if i call it from the bottom screen the function is indeed called but the Label widget wont change on screen.
Am i doing something wrong?
Here is a stripped version of the code:
from kivy.app import App
from kivy.lang import Builder
from kivy.properties import ObjectProperty
from kivy.core.window import Window
from kivy.uix.widget import Widget
from kivy.clock import Clock
Builder.load_string('''
<MainUI>:
orientation: 'vertical'
# both these variables can be the same name and this doesn't lead to
# an issue with uniqueness as the id is only accessible in kv.
<Screen1>:
print_txt: print_txt
layout: layout
RelativeLayout:
id: layout
pos: 0, 400
size: 480, 400
Button:
pos: 0, 200
size_hint: (1, 0.2)
text: "Test Print"
on_press: root.print_something('TEST PRINT FROM SCREEN1')
AnchorLayout:
anchor_x: 'center'
anchor_y: 'bottom'
Label:
id: print_txt
padding_x: 10
markup: True
text_size: self.size
halign: 'left'
valign: 'top'
size_hint: (1, 0.2)
text: ""
<Screen2>:
btn1: btn1
RelativeLayout:
pos: 0, 0
size: 480, 400
Button:
id: btn1
pos_hint: {'x': .15, 'center_y': .5}
size_hint: (0.7, 0.5)
text: "Test Print"
on_press: root.print_text()
''')
class Screen1(Widget):
print_txt = ObjectProperty(None)
layout = ObjectProperty(None)
def print_something(self, string):
print 'Function called...'
self.print_txt.text = ''
counter = [0]
string_len = len(string)
def print_step(dt):
if counter[0] == string_len:
return False
else:
self.print_txt.text += string[counter[0]]
counter[0] = counter[0] + 1
Clock.schedule_interval(print_step, 2.0/60.0)
print 'Function End..'
class Screen2(Widget):
btn1 = ObjectProperty(None)
def __init__(self):
super(Screen2, self).__init__()
def print_text(self):
print 'Trying to print Text from Screen2 to Screen1'
target = Screen1()
target.print_something('TEST PRINT FROM SCREEN2')
class MainUI(Widget):
def __init__(self):
super(MainUI, self).__init__()
self.screen1 = Screen1()
self.add_widget(self.screen1)
self.add_widget(Screen2())
class MainApp(App):
def build(self):
Window.size = (480, 800)
return MainUI()
if __name__ == '__main__':
MainApp().run()
Your Screen2 print_text method creates a new Screen1 instance, which is modified but not displayed anywhere so you don't see anything change.
You could change the call to instead something like
on_press: root.parent.screen1.print_text()
...to access the print_text function of the Screen1 instance that you actually want to update.

Categories

Resources