Hello fellow programmers, I'm developing a simple interface application in Python that will enable easy and intuitive entry of inventory forms in an access database.
I currently have a function as follows:
def spawnerror(self, errormsg):
self.running = False
content = Button(text=errormsg)
popup = Popup(title='ERROR!', content=content, auto_dismiss=False)
content.bind(on_press=popup.dismiss)
popup.open()
And I have appropriate error handling done, and the application uses this function as intended. For example, if someone doesn't enter in a required field, it calls this function and spawns an error page with an error and informs the user.
My issue that I run into is that, it needs to set the class variable running to False, because at the end of the main function "submit" it checks for that and if self.running == False, then it needs to skip the execution of data entry in the access database.
Why is this function not setting the class variable of running to false?
Solution - using App.get_running_app()
In the example, a class attribute, running is defined as BooleanProperty. In the spawnerror() function, it uses App.get_running_app() function to get an instance of App class and then access variable, running.
Note
If running, spawnerror() function and submit() function are in different classes then work out the relation of the classes and pass a direct reference between them.
Example
main.py
from kivy.app import App
from kivy.uix.popup import Popup
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import BooleanProperty, ObjectProperty
class RootWidget(BoxLayout):
instance = ObjectProperty(None)
def __init__(self, **kwargs):
super(RootWidget, self).__init__(**kwargs)
self.instance = App.get_running_app()
self.spawnerror('Testing')
def spawnerror(self, errormsg):
self.instance.running = False
content = Button(text=errormsg)
popup = Popup(title='ERROR!', content=content, auto_dismiss=False)
content.bind(on_press=popup.dismiss)
popup.open()
class TestApp(App):
running = BooleanProperty(True)
def build(self):
print("\nbuild:")
self.display_attributes()
return RootWidget()
def on_stop(self):
print("\non_stop:")
self.display_attributes()
def display_attributes(self):
print("\tApp.running =", self.running)
if __name__ == "__main__":
TestApp().run()
Output
Related
I want to get instances of the attributes in each class, such as the users password and email, but I also want to be able to get the add_widget to come up with only the name, yet:
Here is my code so far
from kivy.uix import Screen, ScreenManager
class WindowManager(ScreenManager):
pass
sm = WindowManager()
In login window
class LoginWindow(Popups, Screen, FloatLayout, BoxLayout):
def __init__(self, email, password, checkBox, **kwargs):
self.email = email
self.password = password
self.checkBox = checkBox
super(self, **kwargs).__init__()
self.name = "login"
And in main app window
sm.add_widget(LoginWindow(name="login"))
#actual phone app class
class PhoneAssistantApp(App):
def __init__(self):
super(self).__init__()
def build(self):
if LoginWindow.checkBox == True:
sm.current = "main"
else:
sm.current = "login" #user sent to login page whenever program is ran
return sm
if __name__ == "__main__":
PhoneAssistantApp().run()
But it comes up with error:
line 352, in <module>
sm.add_widget(LoginWindow(name="login"))
TypeError: __init__() missing 3 required positional arguments: 'email', 'password', and 'checkBox'
My login window in my kv file is simply:
<LoginWindow>:
name: "login" #name used to know where to send
email: email #links to object property in py file class
password: password #links to object property in py file class
checkBox: checkBox #links to boolean property in py file class
I believe the error is in my main program, as I'm trying to figure out how to fit both the attributes instances in with the kivy.
First I had my sm.add_widget and classes names in the App class, like
class PhoneAssistantApp(App):
def __init__(self, **kwargs):
super(self, **kwargs).__init__()
self.screens = ((LoginWindow(name="login"), CreateAccountWindow(name="Create))
self.sm = ScreenManager()
def build(self):
for screen in self.screens:
self.sm.add_widget(screens)
if LoginWindow.checkBox == True:
self.sm.current = "main"
else:
self.sm.current = "login" #user sent to login page whenever program is ran
return self.sm
if __name__ == "__main__":
PhoneAssistantApp().run()
And
class PhoneAssistantApp(App):
def __init__(self, **kwargs):
super(self, **kwargs).__init__()
self.screens = ((LoginWindow(name="login"), CreateAccountWindow(name="Create))
def build(self):
for screen in self.screens:
sm.add_widget(screens)
if LoginWindow.checkBox == True:
sm.current = "main"
else:
sm.current = "login" #user sent to login page whenever program is ran
return sm
if __name__ == "__main__":
PhoneAssistantApp().run()
Yet taking it away didn't get rid of the problem. In addition, getting rid of the **kwargs likely didn't help much either.
It worked fine until I added the init into the classes.
I'm using visual studio code, where before I added the init hovering over name in above would display 'name=[literal]"login', yet now only displays 'name = "any"'
However, when hovering over name in the login class in my new code, it also returned 'name = [literal]login'.
Rather, I want to be able to use the name without having to indent the other attributes into my sm.add_widget.
While I did try putting the attributes in to see what would work, I tended to put:
sm.add_widget(LoginWindow(name="login", email=LoginWindow.email, password=LoginWindow.password, checkBox=LoginWindow.checkBox))
As I simply wanted the instances of the attributes, but I don't think that's what I should do as it only got me error.
line 352, in <module>
sm.add_widget(LoginWindow(name="login", email=LoginWindow.email, password=LoginWindow.password, checkBox=LoginWindow.checkBox))
AttributeError: type object 'LoginWindow' has no attribute 'email'
Thanks to anyone who'd be able to help out.
When you define a method as you have:
def __init__(self, email, password, checkBox, **kwargs):
all those arguments are required whenever an instance of LoginWindow is created. Your code:
sm.add_widget(LoginWindow(name="login"))
does not provide those required arguments, thus you get that error. You can instead use optional arguments by using keywords. See the documentation.
I've wrote this code but I don't understand a part of it; the line that uses super(check_box, self).__init__(**kwargs) and when I remove check_box, self from it, the code still functions properly
from kivy.uix.widget import Widget
from kivy.uix.label import Label
from kivy.uix.checkbox import CheckBox
from kivy.uix.gridlayout import GridLayout
class check_box(GridLayout):
# for class name don't use keywords like CheckBox or if you use them you should use underscore in the name as well
def __init__(self, **kwargs):
# **kwargs imports keywords related to gridlayout class
super().__init__(**kwargs)
self.cols = 2
# number of columns
self.add_widget(Label(text="Male"))
self.active = CheckBox(active=True)
# making an object
self.add_widget(self.active)
# adding the object to the GUI
self.add_widget(Label(text="Female"))
self.active = CheckBox(active=True)
self.add_widget(self.active)
self.add_widget(Label(text="Other"))
self.active = CheckBox(active=True)
self.add_widget(self.active)
class CheckBoxApp(App):
def build(self):
return check_box()
if __name__ == "__main__":
CheckBoxApp().run()
check_box class inherits the GridLayout class. Calling super() inside check_box class allows us to make a proxy object (temporary object of the superclass) that allows us to access methods of the superclass class.
super().init(param1, param2, ...) simply means that we are calling the constructor method of that temporary superclass object to construct that object by feeding in parameter values.
Arguments inside the super are not used now, but they anyway work without error because they were used in old python versions.
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'm relatively new to Python and OOP, and going through the Kivy documentation and found some syntax I was not used to seeing. I am not really sure how to search for the answer since I don't know what to call this type of syntax, so I'll illustrate with the code itself.
Here is the code from the kivy docs:
import kivy
kivy.require('1.0.5')
from kivy.uix.floatlayout import FloatLayout
from kivy.app import App
from kivy.properties import ObjectProperty, StringProperty
class Controller(FloatLayout):
'''Create a controller that receives a custom widget from the kv lang file.
Add an action to be called from the kv lang file.
'''
label_wid = ObjectProperty()
info = StringProperty()
def do_action(self):
self.label_wid.text = 'My label after button press'
self.info = 'New info text'
class ControllerApp(App):
def build(self):
return Controller(info='Hello world')
if __name__ == '__main__':
ControllerApp().run()
When the above code runs
return Controller(info='Hello world')
I understand that it is setting a value for Controller().info (or controller_object_instance.info within the kivy.app.build() code), but I don't understand how this string assignment to the variable 'info' works, since I would think you would need an init() function at the top of the class to accept this assignment. Since there is no init() within the Controller() class, why doesn't
Controller(info='Hello world')
throw an error? How does the above line of code know to properly assign the value 'Hello world' to its own attribute 'info'? Is there some init() function inherited from App and this can someone be used or does it have something to do with these two lines of code?
label_wid = ObjectProperty()
info = StringProperty()
Any help appreciated. Just looking for a way to search for this more on my own, and I'm stuck on what topic to search for.
When you created the class Controller, you wanted to inherit the class FloatLayout.
This means, whenever you create a Controller object, you create a FloatLayout which you extended. So the __init__ function from FloatLayout at executes.
Look at this example:
class Animal:
def __init__(self,**kwargs):
self.info = kwargs.get("info")
class Dog(Animal):
pass
obj = Dog(info="Hello world")
print(obj.info)
Now you want to create a Dog, but a dog is also an Animal, so you want to inherit all it's methods and attributes.
So if you pass info as an argument when creating an instance of Dog, it will be passed to Animal's __init__ function.
I'm developing kivy app.
While I'm using ScreenManager, I can only add Screen in to it.
But Screen seems that it can add other widgets.
How can I add scatter widget to Screen for interface performance?
class sc(Scatter):
pass
class Screen1(Screen):
pass
class Screen2(Screen):
pass
class manager(ScreenManager):
pass
class MyApp(App):
def build(self):
sm = manager()
s1 = Screen1()
sca = sc()
s1.add_widget(sca)
sm.add_widget(s1)
return sm
MyApp().run()
Your code does add a Scatter (what you call sca) to a Screen (what you call s1).