I want to initialise the value of a CheckBox in kivy from the python code
I have tried (see example) but it doesn't work. Can anyone please help?
import kivy
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import BooleanProperty
from kivy.properties import StringProperty
class MainScreen(BoxLayout):
BlueText = StringProperty()
Blue = BooleanProperty()
Red = BooleanProperty()
UseColours = BooleanProperty()
def __init__(self, **kwargs):
super(MainScreen, self).__init__(**kwargs)
self.BlueText='Blue'
self.UseColours=True
self.Blue=False
self.Red=True
def doBlue(self,*args):
pass
def doRed(self,*args):
pass
def doUseColours(self,*args):
pass
class BasicApp(App):
def build(self):
return MainScreen()
if __name__ == '__main__':
BasicApp().run()
My kv file tries to pick up whether or not the boxes are checked by setting 'value'. Is this right?
MainScreen:
<MainScreen>:
orientation: "vertical"
GridLayout:
cols: 2
Label:
text: root.BlueText
CheckBox:
group: 'colours'
value: root.Blue
on_active: root.doBlue(*args)
Label:
text: "Red"
CheckBox:
group: 'colours'
value: root.Red
on_active: root.doRed(*args)
Label:
text: "Use colours"
CheckBox:
value: root.UseColours
on_active: root.doUseColours(*args)
Use active property:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
Builder.load_string('''
<MyWidget>:
CheckBox:
active: False
CheckBox:
active: True
''')
class MyWidget(BoxLayout):
pass
class MyApp(App):
def build(self):
return MyWidget()
if __name__ == '__main__':
MyApp().run()
From Python code:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import BooleanProperty
from kivy.lang import Builder
Builder.load_string('''
<MyWidget>:
CheckBox:
active: root.is_active
CheckBox:
active: not root.is_active
Button:
text: 'toggle'
on_press: root.toggle()
''')
class MyWidget(BoxLayout):
is_active = BooleanProperty(False)
def toggle(self):
self.is_active = not self.is_active
class MyApp(App):
def build(self):
return MyWidget()
if __name__ == '__main__':
MyApp().run()
Related
imports:
from kivy.app import App
from kivy.lang import Builder
from kivy.properties import StringProperty
from kivy.uix.textinput import TextInput
kv = '''
BoxLayout:
orientation: 'vertical'
TextInput:
id: t1
TextInput:
id: t2
TextInput:
id: t3
TextInput:
id: t4
'''
MyApp class:
class MyApp(App):
text = StringProperty('-.text')
def build(self):
return Builder.load_string(kv)
def on_pre_enter(self):
self.ids['t1'].text = "textinput1"
def on_enter(self):
self.ids['t2'].text = "textinput2"
def on_pre_enter(self):
self.ids['t3'].text = "textinput3"
def on_enter(self):
self.ids['t4'].text = "textinput4"
if __name__ == '__main__':
MyApp().run()
This is nothing to do with Kivy, it's simply how Python works that writing a second method with the same name replaces the previous definition.
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:
I have 2 file test.py and test.kv. When I run test.py and pass numeric value in self.abc.text=10 then it gives error
File "/usr/lib/python2.7/dist-packages/kivy/uix/textinput.py", line 2930, in _set_text
text = text.replace(u'\r\n', u'\n')
AttributeError: 'int' object has no attribute 'replace'
If I pass string value then it's working. I think text for string value but I don't what is for numeric value?
test.py
import kivy
kivy.require('1.9.0') # replace with your current kivy version !
import sqlite3 as lite
from kivy.app import App
from kivy.uix.screenmanager import Screen
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import BooleanProperty, ListProperty, StringProperty, ObjectProperty, NumericProperty
from kivy.lang import Builder
from kivy.uix.popup import Popup
from kivy.core.window import Window
from kivy.uix.label import Label
#Window.maximize()
from kivy.clock import Clock
from kivy.uix.treeview import TreeView, TreeViewLabel, TreeViewNode
Window.size = (500, 530)
class GroupScreen(Screen):
groupName = ObjectProperty(None)
popup = ObjectProperty(None)
abc = ObjectProperty(None)
def display_groups(self, instance):
self.abc.text=10
class Group(App):
def build(self):
self.root = Builder.load_file('test.kv')
return self.root
if __name__ == '__main__':
Group().run()
test.kv
#:kivy 1.10.0
<CustomLabel#Label>:
text_size: self.size
valign: "middle"
padding_x: 5
<SingleLineTextInput#TextInput>:
multiline: False
<GreenButton#Button>:
background_color: 1, 1, 1, 1
size_hint_y: None
height: self.parent.height * 0.150
GroupScreen:
groupName: groupName
abc:abc
GridLayout:
cols: 2
padding : 30,30
spacing: 10, 10
row_default_height: '40dp'
CustomLabel:
text: 'Number'
SingleLineTextInput:
id: abc
CustomLabel:
text: 'Test'
SingleLineTextInput:
id: groupName
on_text: root.display_groups(self)
GreenButton:
text: 'Ok'
GreenButton:
text: 'Cancel'
Use NumericProperty and then str(root.abc) in kv.
Try this example:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import NumericProperty
class MyBoxLayout(BoxLayout):
abc = NumericProperty(0)
def set_text(self):
self.abc = 42
KV = """
MyBoxLayout:
Button:
text: str(root.abc)
on_release:
root.set_text()
"""
class Testapp(App):
def build(self):
root = Builder.load_string(KV)
return root
Testapp().run()
You need to type self.abc.text = str(rows[1]) in order for it to be passed as the correct type.
Hope this helps!
I want to get the random values generated in 'randgen' displayed as text in the button (right now the button displays string). How can I get rand_val into the .kv file?
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.clock import Clock
import random
root = Builder.load_string('''
<Demo>:
cols: 1
BoxLayout:
orientation: 'vertical'
Button:
text: 'rand_val_here'
size_hint: .2, .2
pos_hint: {'x':0, 'center_y': .1}
''')
class Demo(BoxLayout):
pass
class MainApp(App):
def build(self):
Clock.schedule_interval(self.randgen, 0.01)
return Demo()
def randgen(dt, self):
rand_val = random.randint(0, 10)
print(rand_val)
if __name__ == '__main__':
MainApp().run()
The arguments and names of some functions are not correct, I think they are caused because you have tried to copy and remove the secondary part but remember that the order is interesting in python.
If you want to assign a property to a Widget you must first obtain it and for them an id must be placed, this id will be the name of the variable that will be created and assigned, we can access it through ids as I show below:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.clock import Clock
import random
root = Builder.load_string('''
<Demo>:
cols: 1
BoxLayout:
orientation: 'vertical'
Button:
id: btn
size_hint: .2, .2
pos_hint: {'x':0, 'center_y': .1}
''')
class Demo(BoxLayout):
def __init__(self, *args, **kwargs):
BoxLayout.__init__(self, *args, **kwargs)
Clock.schedule_interval(self.randgen, 0.01)
def randgen(self, dt):
rand_val = random.randint(0, 10)
self.ids.btn.text = str(rand_val)
print(rand_val)
class MainApp(App):
def build(self):
return Demo()
if __name__ == '__main__':
MainApp().run()
There are two methods of solving this. The method 1 is using ObjectProperty, and the method 2 is using StringProperty.
Method 1 - Using ObjectProperty
In this example, an ObjectProperty is used to hook up to the button because an id is a weakref to the widget. Using ObjectProperty creates a direct reference, provides faster access and is more explicit.
main.py
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty
from kivy.lang import Builder
from kivy.clock import Clock
import random
root = Builder.load_string('''
<Demo>:
btn: btn
orientation: 'vertical'
Button:
id: btn
text: 'rand_val_here'
size_hint: .2, .2
pos_hint: {'x':0, 'center_y': .1}
''')
class Demo(BoxLayout):
btn = ObjectProperty(None)
def __init__(self, **kwargs):
super(Demo, self).__init__(**kwargs)
Clock.schedule_interval(self.randgen, 0.01)
def randgen(self, dt):
self.btn.text = str(random.randint(0, 10))
class MainApp(App):
title = "Updating Button's Text - Using ObjectProperty"
def build(self):
return Demo()
if __name__ == '__main__':
MainApp().run()
Output
Method 2 - Using StringProperty
Without changing much of your original app, the solution is as follow:
Since your root widget class, Demo is a BoxLayout, therefore the attribute cols: 1 which is only applicable to GridLayout is not required in the kv file
Declare rand_val of type StringProperty
Populate the button's text using app.rand_val
Note:
Your app has nested BoxLayout.
main.py
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty
from kivy.lang import Builder
from kivy.clock import Clock
import random
root = Builder.load_string('''
<Demo>:
BoxLayout:
orientation: 'vertical'
Button:
text: app.rand_val
size_hint: .2, .2
pos_hint: {'x':0, 'center_y': .1}
''')
class Demo(BoxLayout):
pass
class MainApp(App):
rand_val = StringProperty("")
def build(self):
Clock.schedule_interval(self.randgen, 0.01)
return Demo()
def randgen(self, dt):
self.rand_val = str(random.randint(0, 10))
print(self.rand_val)
if __name__ == '__main__':
MainApp().run()
Output
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: