Auto dismiss a popup in kivy - python

I need to dismiss the pop up after finishing a function in another class, or at least after specific time like (3 second)
the pop up displaying loading gif image
to notify the user to wait for operating the functions
loading image
*******python******
from kivy.app import App
from kivy.uix.popup import Popup
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
class ScreenManagement(ScreenManager):
pass
class progress(Popup):
pass
class Func_(Screen):
# function
pass
presentation = Builder.load_file("Try_.kv")
class MainApp(App):
def build(self):
return presentation
if __name__ == "__main__":
MainApp().run()
********KV File*********
#:import Factory kivy.factory.Factory
<Popup>:
separator_color: 1, 1, 1, 1
background: "White.png"
Button:
id: btn
disabled: True
background_disabled_normal: "White.png"
text: "Hello"
Image:
source: "Loading.gif"
size: root.size
ScreenManagement:
PopupBox:
<PopupBox>:
BoxLayout:
Button:
text: "Click"
on_release:
Factory.Popup().open()

You have to add a function to dismiss the Popup message and use Clock.schedule_once to call that function. Please refer to the example below for details.
main.py
from kivy.app import App
from kivy.uix.popup import Popup
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.clock import Clock
class ScreenManagement(ScreenManager):
pass
class Progress(Popup):
def __init__(self, **kwargs):
super(Progress, self).__init__(**kwargs)
# call dismiss_popup in 2 seconds
Clock.schedule_once(self.dismiss_popup, 2)
def dismiss_popup(self, dt):
self.dismiss()
class Func(Screen):
# function
pass
class MainApp(App):
def build(self):
return ScreenManagement()
if __name__ == "__main__":
MainApp().run()
main.kv
#:import Factory kivy.factory.Factory
#:import FadeTransition kivy.uix.screenmanager.FadeTransition
<Progress>:
separator_color: 1, 1, 1, 1
background: "White.png"
Button:
id: btn
disabled: True
background_disabled_normal: "White.png"
text: "Hello"
Image:
source: "Loading.gif"
size: root.size
<ScreenManagement>:
transition: FadeTransition()
Func:
<Func>:
BoxLayout:
Button:
text: "Click"
on_release:
Factory.Progress().open()
Output

Related

(Kivy) How do I display new content on my canvas in Kivy?

This should be a pretty easy fix. I'm new to Kivy. I'm trying to have the canvas cleared on a button press, and then display a new widget to essentially move to another page. When I run it and press the button, the canvas is cleared, but I get nothing from IntroPage.
Python Script:
import kivy
kivy.require('2.0.0')
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
from kivy.uix.image import Image
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty
class ABT(App):
def build(self):
return WelcomePage()
class WelcomePage(Widget):
def btn(self):
self.canvas.clear()
print('pressed')
return IntroPage()
class IntroPage(Widget):
def __init__(self):
pass
if __name__ == '__main__':
ABT().run()
KV File:
<WelcomePage>
canvas.before:
Color:
rgba: (.43,.51,.92,.26)
Rectangle:
pos: self.pos
size: self.size
GridLayout:
cols:1
size: root.width, root.height
Image:
source: 'abt1t.png'
size_hint: (1,.8)
Button:
text:"begin"
background_color: (.43,.51,.92,.26)
size_hint: (1,.2)
on_press: root.btn()
<IntroPage>
GridLayout:
cols:1
Label:
text:"This won't show up!"
Returning IntroPage from btn won't work, as btn isn't a build method.
The best way to implement multiple pages is probably to use ScreenManager:
from kivy.uix.screenmanager import ScreenManager, Screen
class ABT(App):
def build(self):
sm = ScreenManager()
sm.add_widget(WelcomePage(name="welcome"))
sm.add_widget(IntroPage(name="intro"))
return sm
class WelcomePage(Screen):
def btn(self):
print('pressed')
self.manager.current = "intro"
class IntroPage(Screen):
def __init__(self):
pass

Error Code : "KivyMD: App object must be initialized before loading "

I am receiving the Error : "KivyMD: App object must be initialized before loading " when I am trying to add a kivymd button (MDRaisedButton).
I tried debugging, the issue is when I add the BoxLayout under the DateScreen, I just don't find any information on how to fix it.
How should one initialized app object before loading ?
import kivy
kivy.require("1.11.1")
from kivy.app import App
from kivy.lang import Builder
from kivy.clock import Clock
from kivy.uix.screenmanager import Screen
from kivymd.theming import ThemeManager
class WelcomeScreen(Screen): # Defines WelcomeScreen instance as a screen widget.
pass
class DateScreen(Screen): # Defines DateScreen instance as a screen widget.
pass
class ResultScreen(Screen): # Defines ResultScreen instance as a screen widget.
pass
root_widget = Builder.load_string("""
ScreenManager:
WelcomeScreen:
DateScreen:
ResultScreen:
<WelcomeScreen>:
_welcome_screen_text_: welcome_screen
name: 'my_welcome_screen'
Label:
id: welcome_screen
Image:
source: 'Cheers.jpg'
size: 200, 200
center: self.parent.center
<DateScreen>:
_date_screen_text_: date_screen
name: 'my_date_screen'
Label:
id: date_screen
text: "This is the date selection screen"
BoxLayout:
size_hint: 0.1, 0.5
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
MDRaisedButton:
text: 'MDButton1'
<ResultScreen>:
_result_screen_text_: result_screen
name: 'my_result_screen'
Label:
id: result_screen
text: "This is where the result will be displayed"
""")
class MainApp(App):
theme_cls = ThemeManager()
def build(self):
self.theme_cls.theme_style = "Dark"
Clock.schedule_once(self.screen_switch_one, 36) # clock callback for the first screen
Clock.schedule_once(self.screen_switch_two, 4) # clock callback for the second screen
return root_widget
def screen_switch_one(a, b):
root_widget.current = 'my_welcome_screen'
def screen_switch_two(a, b):
root_widget.current = 'my_date_screen'
if __name__ == '__main__':
MainApp().run()
Please help!
I believe you need to call Builder after the App is initialized (as mentioned in your error). To do that you can save your kv in a string, then call Builder inside the build() method. Like this:
import kivy
from kivymd.app import MDApp
kivy.require("1.11.1")
from kivy.lang import Builder
from kivy.clock import Clock
from kivy.uix.screenmanager import Screen
class WelcomeScreen(Screen): # Defines WelcomeScreen instance as a screen widget.
pass
class DateScreen(Screen): # Defines DateScreen instance as a screen widget.
pass
class ResultScreen(Screen): # Defines ResultScreen instance as a screen widget.
pass
kv = """
ScreenManager:
WelcomeScreen:
DateScreen:
ResultScreen:
<WelcomeScreen>:
_welcome_screen_text_: welcome_screen
name: 'my_welcome_screen'
Label:
id: welcome_screen
Image:
source: 'Cheers.jpg'
size: 200, 200
center: self.parent.center
<DateScreen>:
_date_screen_text_: date_screen
name: 'my_date_screen'
Label:
id: date_screen
text: "This is the date selection screen"
BoxLayout:
size_hint: 0.1, 0.5
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
MDRaisedButton:
text: 'MDButton1'
<ResultScreen>:
_result_screen_text_: result_screen
name: 'my_result_screen'
Label:
id: result_screen
text: "This is where the result will be displayed"
"""
class MainApp(MDApp):
def build(self):
self.theme_cls.theme_style = "Dark"
self.root_widget = Builder.load_string(kv)
Clock.schedule_once(self.screen_switch_one, 36) # clock callback for the first screen
Clock.schedule_once(self.screen_switch_two, 4) # clock callback for the second screen
return self.root_widget
def screen_switch_one(self, dt):
self.root_widget.current = 'my_welcome_screen'
def screen_switch_two(self, dt):
self.root_widget.current = 'my_date_screen'
if __name__ == '__main__':
MainApp().run()

Python/Kivy crashes instantly

Overall question is: Why does my Kivy application crashes instantly?
My Python code is:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.widget import Widget
from kivy.graphics import Line
class MainScreen(Screen):
pass
class AnotherScreen(Screen):
pass
class ScreenManagement(ScreenManager):
pass
class TouchInput(Widget):
def on_touch_down(self, touch):
with self.canvas:
touch.ud["line"] = Line(points=(touch.x, touch.y))
def on_touch_move(self, touch):
touch.ud["line"].points += (touch.x, touch.y)
presentation = Builder.load_file("simplekivy.kv")
class SimpleKivy(App):
def build(self):
return presentation
if __name__ == "__main__":
SimpleKivy().run()
My Kv. code is:
#: import FadeTransition kivy.uix.screenmanager.FadeTransition
ScreenManagement:
transition: FadeTransition()
MainScreen:
AnotherScreen:
<MainScreen>:
name: "Main"
Button:
on_release: app.root.current = "Other"
text: "Next screen!"
font_size: 50
<AnotherScreen>:
name: "Other"
FloatLayout:
TouchInput:
id: touch
Button:
on_release: app.root.current = "Main"
text: "Going back!"
font_size: 40
color: 0,1,0,1
size_hint: 0.3, 0.2
pos_hint: {'right': 1, 'top': 1}
Button:
on_release: touch.canvas.clear()
text: "Clear window"
font_size: 40
color: 0,1,0,1
size_hint: 0.3, 0.2
pos_hint: {'right': 1, 'top': 0}
When I would remove the 'Clear window'-Button, the application works as expected. However, the moment I add the button, it crashes instantly with the error message:
Python has stopped working
when you make a code in python and use kv the library itself will look for the .kv file in the same directory where the .py file is, so you do not have to start through 'presentation = Builder.load_file (" simplekivy. kv ")'
this can be solved changing the python code to:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.widget import Widget
from kivy.graphics import Line
class MainScreen(Screen):
pass
class AnotherScreen(Screen):
pass
class ScreenManagement(ScreenManager):
pass
class TouchInput(Widget):
def on_touch_down(self, touch):
with self.canvas:
touch.ud["line"] = Line(points=(touch.x, touch.y))
def on_touch_move(self, touch):
touch.ud["line"].points += (touch.x, touch.y)
#don't need this
#presentation = Builder.load_file("simplekivy.kv")
class SimpleKivy(App):
pass
#I commented on that part of your code and added a 'pass' above
#def build(self):
# return presentation
if __name__ == "__main__":
SimpleKivy().run()

Kivy content sizes adjustment

I have been started to work in kivy recently. The thing what I am doing now is, i have a blank page with a button, when I click that button it navigates to an user input screen. It works fine, but the content comes in a very small input boxes and text as in the picture.
My question is that I want it bigger and centred.
Here is my code:
In python:
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
from kivy.uix.widget import Widget
from kivy.lang import Builder
class LoginScreen(GridLayout):
def __init__(self, **kwargs):
super(LoginScreen, self).__init__(**kwargs)
self.cols = 2
self.add_widget(Label(text="Username:"))
self.username = TextInput(multiline=False)
self.add_widget(self.username)
self.add_widget(Label(text="Password:"))
self.password = TextInput(multiline=False, password=True)
self.add_widget(self.password)
self.add_widget(Label(text="Two Factor Auth:"))
self.tfa = TextInput(multiline=False)
self.add_widget(self.tfa)
class MainScreen(Screen):
pass
class AnotherScreen(Screen):
pass
class ScreenManagement(ScreenManager):
pass
presentation = Builder.load_file("screen.kv")
class SimpleKivy(App):
def build(self):
return presentation
if __name__ == "__main__":
SimpleKivy().run()
In kv:
#: import FadeTransition kivy.uix.screenmanager.FadeTransition
ScreenManagement:
transition: FadeTransition()
MainScreen:
AnotherScreen:
<MainScreen>:
name: "main"
Button:
color: 0,1,0,1
font_size: 25
size_hint: 0.3,0.2
text: "Click"
on_release: app.root.current = "other"
pos_hint: {"right":1, "top":1}
<AnotherScreen>:
name: "other"
GridLayout:
LoginScreen
In your screen.kv, you have the LoginScreen inside a GridLayout. Since the LoginSCreen is a GridLayout, you do not need that extra GridLayout.
Just change:
<AnotherScreen>:
name: "other"
GridLayout:
LoginScreen
to:
<AnotherScreen>:
name: "other"
LoginScreen:

AsyncImage refresh in kivy/python

In python2.7 + kivy1.9, I use AsyncImage like:
class Foo(BoxLayout):
..def bar(self):
....file_name=StringProperty()
..
..
....self.file_name="/../../image.png"
..
and in kivy,
BoxLayout:
..AsyncImage:
....source: root.file_name
Before the second call of function bar I change the content of image.png.
But the image displayed doesn't change.
I tried "nocache: True" after source command in kivy but it doesn't work.
How can I get the correct display everytime I call the func bar.
The problem is that you declare file_name property in each bar call. The file_name property must be a class attribute:
main.py:
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty
class RootWidget(BoxLayout):
image_path = StringProperty('image1.png') # <<<<<<<<
def __init__(self, **kwargs):
super(RootWidget, self).__init__(**kwargs)
def change_image(self, path):
self.image_path = path
class TestApp(App):
def build(self):
return RootWidget()
if __name__ == '__main__':
TestApp().run()
test.kv:
<RootWidget>:
orientation: "vertical"
AsyncImage:
id: image
source: root.image_path
BoxLayout:
size_hint_y: 0.1
Button:
text: 'Image 1'
on_press: root.change_image("image1.png")
Button:
text: 'Image 2'
on_press: root.change_image("image2.png")
EDIT
If you would like to use only one file name and change the content of the image, you need call reload method (with nocache property True):
main.py:
import os
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty
class AsyncTest(BoxLayout):
img = ObjectProperty()
def show_icon(self):
self.img.source = "/sdcard/archive/icon_0.png"
def switch(self):
os.system("mv /sdcard/archive/icon_1.png /sdcard/archive/icon_0.png")
self.img.reload()
class TestApp(App):
def build(self):
return AsyncTest()
if __name__ == '__main__':
TestApp().run()
test.ḱv:
<AsyncTest>:
orientation: "vertical"
img: asyn_image
AsyncImage:
id: asyn_image
nocache: True
BoxLayout:
size_hint_y: 0.1
Button:
text: 'Show'
on_press: root.show_icon()
Button:
text: 'Switch'
on_press: root.switch()
Output:

Categories