I read this question and tried to implement a close event for my app.
I wrote the following code in Kivy in Python.
#-*- coding: utf-8 -*-
from kivy.lang import Builder
Builder.load_string("""
<TextWidget>:
BoxLayout:
size: root.size
Button:
text: "Test App"
""")
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.core.window import Window
from kivy.properties import StringProperty
class TextWidget(Widget):
def __init__(self, **kwargs):
super(TextWidget, self).__init__(**kwargs)
self.text = 'test'
def on_request_close(self, *args):
print(self.text)
class TestApp(App):
def __init__(self, **kwargs):
super(TestApp, self).__init__(**kwargs)
def build(self):
scn = TextWidget
Window.bind(on_request_close=scn.on_request_close)
return TextWidget()
if __name__ == '__main__':
TestApp().run()
When I quit the app,"on_request_close" function is executed, but for some reason the print(self.text) fails, resulting in an error.
The errors are as follows:
AttributeError: 'WindowSDL' object has no attribute 'text'
How can I fix this problem?
You're trying to access the class itself instead of the TextWidget instance that has the text attribute.
You can do the binding within TextWidget's __init__ method to fix it (below) or you can access the instance by assigning it an id.
class TextWidget(Widget):
def __init__(self, **kwargs):
super(TextWidget, self).__init__(**kwargs)
Window.bind(on_request_close=self.on_request_close)
self.text = 'test'
def on_request_close(self,*args):
app=self.text
print(app)
class TestApp(App):
def build(self):
return TextWidget()
Related
I don't know why, but every time I try to run my code it doesn't work, here's the code.
If you can help me it'd be really wholesome. Thank you in advance.
Here's the code of the 3 files.
main.py
from kivy.app import App
from App.Constructor.constructor import Constructor
class MyApp(App):
def build(self):
return Constructor().constr()
if __name__ == '__main__':
MyApp().run()
constructor.py
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager
kv = Builder.load_file('Constructor\\constructor.kv')
class WindowManager(ScreenManager):
pass
class Constructor():
def constr(self):
return kv
constructor.kv
#:import Login App.Login
#:import SignUp App.SignUp
WindowManager:
Login:
SignUp:
<Login>:
name: "login"
<SignUp>:
name: "signup"
This because of you used the WindowManager in kv file before you define it in the python file
The solution will be to load the kv file after creating the WindowManager class
like this
1)
class WindowManager(ScreenManager):
pass
kv = Builder.load_file('Constructor\\constructor.kv')
or
2)
loading directly when you need it
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager
class WindowManager(ScreenManager):
pass
class Constructor():
def constr(self):
return Builder.load_file('Constructor\\constructor.kv')
I want to make a custom set of widgets and in some of them I would like to access specific widgets' properties inside of the add_widget(widget, index, canvas)method.
The problem is that the properties are always empty. This could be because I access them early but how do I fix it?
My Code:
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivymd.uix.label import MDLabel
from kivymd.app import MDApp
class CustomWidget(BoxLayout):
def add_widget(self, widget, index=0, canvas=None):
if isinstance(widget, MDLabel):
# Why is the text empty?
# Also how can I get the text value?
print("{}'s text is: {}".format(widget, widget.text))
else:
super(CustomWidget, self).add_widget(widget, index, canvas)
class MainApp(MDApp):
def __init__(self, **kwargs):
super(MainApp, self).__init__(**kwargs)
self.kv = Builder.load_string('''
#:kivy 2.0.0
CustomWidget:
MDLabel:
text: "Some text"
''')
def build(self):
return self.kv
if __name__ == '__main__':
MainApp().run()
The text is empty because it hasn't been set yet at the time it's added to the parent.
If you care about what its value changes to, you can bind to the new child widget's text property in add_widget so that you are notified when it changes and can act accordingly.
I'm new to kivy so I don't really know how to display a progress bar in my NaviWindow. I cant seem to put progress bar inside the kv file so anyone knows how to display the bar in the NaviWindow?
.pyfile
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.progressbar import ProgressBar
from kivy.uix.screenmanager import ScreenManager, Screen
KV = """
WindowManager:
NaviWindow:
<NaviWindow>:
"""
class WindowManager(ScreenManager):
pass
class NaviWindow(Screen):
def build(self):
Progress = ProgressBar(max=1000)
Progress.value = 100
return Progress
class MyMainApp(App):
def build(self):
return Builder.load_string(KV)
if __name__ == "__main__":
MyMainApp().run()
Only the App class (and obviously the classes that inherit from App) has the build method, but you seem to think that the Screen method also has it and is clearly incorrect. The solution is to add the ProgressBar using the add_widget() method:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.progressbar import ProgressBar
from kivy.uix.screenmanager import ScreenManager, Screen
KV = """
WindowManager:
NaviWindow:
<NaviWindow>:
"""
class WindowManager(ScreenManager):
pass
class NaviWindow(Screen):
def __init__(self, **kwargs):
super(NaviWindow, self).__init__(**kwargs)
self.progress = ProgressBar(max=1000)
self.progress.value = 100
self.add_widget(self.progress)
class MyMainApp(App):
def build(self):
return Builder.load_string(KV)
if __name__ == "__main__":
MyMainApp().run()
I am new to kivy and using some tutorials but i only get black screen while on the videos developpers get their widget on the screen. i've tried multiple solutions but i dont really understand what the problem is. I am trying to build a login screen here is the code i wrote :
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.textinput import TextInput
class LoginScreen(BoxLayout):
def __int__(self, **kwargs):
super(LoginScreen,self).__int__(**kwargs)
sm=ScreenManager
Screen=Screen(name="screen")
layout=BoxLayout(orientation='vertical')
self.Username = TextInput(multiline=False)
self.Password = TextInput(multiline=False, password=True)
layout.add_widget(Label(text="username"))
layout.add_widget(self.Username)
layout.add_widget(Label(text="password"))
layout.add_widget(self.Password)
Screen.add_widget(layout)
sm.add_widget(Screen)
return sm
class simplekivy(App):
def build(self):
return LoginScreen()
if __name__ == "__main__":
simplekivy().run()
Thank you for your help !
Your code has the following errors:
The constructor method is called __init__, it is not called __int__.
The constructor method should not return anything
The variables should not be called the same as the classes or functions, I mean the following code: Screen=Screen(name="screen").
It is best to segment is to separate your code, with the name of the class LoginScreen I think you want to make a Screen, so create another class that is the ScreenManager.
Another error is that you have not imported Label.
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.textinput import TextInput
from kivy.uix.label import Label
class LoginScreen(Screen):
def __init__(self, *args, **kwargs):
super(LoginScreen,self).__init__(*args, **kwargs)
layout=BoxLayout(orientation='vertical')
self.Username = TextInput(multiline=False)
self.Password = TextInput(multiline=False, password=True)
layout.add_widget(Label(text="username"))
layout.add_widget(self.Username)
layout.add_widget(Label(text="password"))
layout.add_widget(self.Password)
self.add_widget(layout)
class Manager(ScreenManager):
def __init__(self, *args, **kwargs):
super(ScreenManager,self).__init__(*args, **kwargs)
self.add_widget(LoginScreen())
class simplekivy(App):
def build(self):
return Manager()
if __name__ == "__main__":
simplekivy().run()
I am using a screen manager and would like to add widgets to the screen subclass without using the .kv file.
class MainMenu(Screen):
def __init__(self, **kwargs):
gLayout = GridLayout()
gLayout.add_widget(Button(text = 'test'))
class Sis(App):
def build(self):
root = ScreenManager()
root.add_widget(MainMenu(name = 'mainMenu'))
root.current = 'mainMenu'
return root
Sis().run()
When I try to run the above code I get (pygame parachute) Segmentation Fault.
If I create the layout in the .kv file it works fine.
I've tried fiddling around with on_pre_enter and on_enter but I'm pretty sure I was using them wrong.
Any help is appreciated.
You forgot calling parent constructor of MainMenu class:
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
class MainMenu(Screen):
def __init__(self, **kwargs):
super(MainMenu, self).__init__(**kwargs)
self.add_widget(Button(text = 'test'))
class Sis(App):
def build(self):
root = ScreenManager()
root.add_widget(MainMenu(name = 'mainMenu'))
root.current = 'mainMenu'
return root
Sis().run()