I tried adding a slider to a treeview like this:
myTreeView = TreeView()
myTreeView.add_node(Slider(min=0, max = 20, value = 0))
But this generates and error 'The node must be a subclass of TreeViewNode'
How can i add a slider to a treeview in kivy?
You need to create a TreeViewSlider by extending Slider and TreeViewNode.
from kivy.app import App
from kivy.uix.slider import Slider
from kivy.uix.treeview import TreeView, TreeViewNode
from kivy.uix.button import Button
from kivy.uix.slider import Slider
from kivy.uix.label import Label
from kivy.lang import Builder
class TreeViewButton(Button, TreeViewNode):
pass
class TreeViewLabel(Label, TreeViewNode):
pass
class TreeViewSlider(Slider, TreeViewNode):
pass
class TestApp(App):
def build(self):
tv = TreeView()
tv.add_node(TreeViewLabel(text='My first item'))
tv.add_node(TreeViewLabel(text='My second item'))
tv.add_node(TreeViewButton(text='My third item'))
tv.add_node(TreeViewSlider())
return tv
if __name__ == '__main__':
TestApp().run()
Related
Hello i'm relatively new to python and kivy and I've been looking around but i cant quite find the answer, i'm trying to make a hub where I can display live data from my rasberry-pi. I made a clock widget using a Label, and it updates time, but when i try to add my CPU usage only one label shows up. I thought the widgets might be covering each other but I used size_hint and it wont help. When i run the code below, only the timex will show up and only if i delete the Clock.schedule_interval(display32.timex, (1)) will the *updatex * display.
Thanks alot for the help
from kivy.app import App
from kivy.uix.label import Label
from kivy.clock import Clock
from kivy.uix.floatlayout import FloatLayout
import psutil
from kivy.lang import Builder
import time
class Display(Label, FloatLayout):
def __init__(self):
super(Display, self).__init__()
def updatex(self, *args):
self.cpu2 = psutil.cpu_percent()
self.text=str(self.cpu2)
self.size_hint=(.5, .25)
self.pos=(500, 500)
self.texture_size=(0.1,0.1)
def timex(self, *args):
self.time2 = time.asctime()
self.text = str(self.time2)
self.size_hint = (.5, .25)
self.pos = (30, 500)
self.size_hint=(0.1,0.1)
class TimeApp(App):
def build(self):
display32 = Display()
Clock.schedule_interval(display32.updatex, (1))
Clock.schedule_interval(display32.timex, (1))
return display32
if __name__ == "__main__":
TimeApp().run()
Instead of passing both labels to the clock, you can define a widget, add both labels and start the clock on the widget.
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.label import Label
from kivy.clock import Clock
import psutil
import time
class Display(Widget):
def draw(self, *args):
self.clear_widgets()
self.add_widget(Label(text=str(psutil.cpu_percent()), pos=(500, 500)))
self.add_widget(Label(text=str(time.asctime()), pos=(30, 500)))
class TimeApp(App):
def build(self):
display32 = Display()
Clock.schedule_interval(display32.draw, 1)
return display32
if __name__ == '__main__':
TimeApp().run()
How to get access to different widgets in python kivy?
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
from kivy.uix.label import Label
class kxApp(App):
def build(self):
gl_main = GridLayout(rows=2,padding=5, spacing=5)
gl_left = GridLayout(padding=5, spacing=5)
gl_middle = GridLayout(padding=5, spacing=5)
gl_right = GridLayout(padding=5, spacing=5)
gl_main.add_widget(gl_left)
gl_main.add_widget(gl_middle)
gl_main.add_widget(gl_right)
gl_left.add_widget(TextInput(text='Input Here'))
gl_middle.add_widget(Label(text='Just Label'))
gl_right.add_widget(Button(text='Remove Input Field', on_press killFunc))
def killFunc(self,obj):
#how to get access to TextInput() and remove it?
kxApp().run()
What is the natural way to 'get' widget to manipulate it?
By saving a reference to the TextInput, you can simply use remove_widget:
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
from kivy.uix.label import Label
class kxApp(App):
def build(self):
gl_main = GridLayout(rows=2,padding=5, spacing=5)
gl_left = GridLayout(cols=1, padding=5, spacing=5)
gl_middle = GridLayout(cols=1, padding=5, spacing=5)
gl_right = GridLayout(cols=1, padding=5, spacing=5)
gl_main.add_widget(gl_left)
gl_main.add_widget(gl_middle)
gl_main.add_widget(gl_right)
self.text_input = TextInput(text='Input Here')
gl_left.add_widget(self.text_input)
gl_middle.add_widget(Label(text='Just Label'))
gl_right.add_widget(Button(text='Remove Input Field', on_press=self.killFunc))
return gl_main
def killFunc(self,obj):
self.text_input.parent.remove_widget(self.text_input)
kxApp().run()
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.core.window import Window
from kivy.uix.scrollview import ScrollView
from kivy.effects.scroll import ScrollEffect
from kivy.uix.widget import Widget
from kivy.uix.button import Button
class BSGameMain:
def sas(self):
# blmain.remove_widget(scrlFBtns)
self.scrlFBtns.remove_widget(blbtns)
blmain = BoxLayout(orientation = 'vertical') # MainBoxLayout init
scrlFBtns = ScrollView(effect_cls = 'ScrollEffect')
blbtns = BoxLayout(
orientation = 'vertical',
size_hint_y = None
) # BoxLayout for buttons
blbtns.bind(minimum_height = blbtns.setter('height'))
scrlFBtns.add_widget(blbtns)
for i in range (2):
blbtns.add_widget(Button(
text='asd',
size_hint_y = None,
height = 40,
on_press = sas
))
lblmain = Label(text = 'asd')
blmain.add_widget(lblmain)
blmain.add_widget(scrlFBtns)
class BSApp(App):
def build(self):
game = BSGameMain()
return game.blmain
if __name__ == "__main__":
BSApp().run()
AttributeError 'Button' object has no attribute scrlFBtn. What is the problem? I'm trying to make it so that when you clicked, the screen was cleared (Widget was deleted). Рelp me please =)
Your code has several errors and bad programming practices:
if you declare variables that are inside a class and outside any method of the class will be class variables and not attributes of the class, so it is not a good practice to do so if you want to use later self, all that code must be within a method of a class.
on_someproperty wait as parameter a function that receives parameters, in your case sas() does not receive them so the solution is to use a lambda method.
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.scrollview import ScrollView
from kivy.effects.scroll import ScrollEffect
from kivy.uix.button import Button
class BSGameMain:
def __init__(self):
self.blmain = BoxLayout(orientation = 'vertical') # MainBoxLayout init
self.scrlFBtns = ScrollView(effect_cls = 'ScrollEffect')
self.blbtns = BoxLayout(
orientation = 'vertical',
size_hint_y = None )
self.blbtns.bind(minimum_height = self.blbtns.setter('height'))
self.scrlFBtns.add_widget(self.blbtns)
for i in range(2):
self.blbtns.add_widget(Button(
text='asd',
size_hint_y = None,
height = 40,
on_press = lambda *args: self.sas()))
lblmain = Label(text = 'asd')
self.blmain.add_widget(lblmain)
self.blmain.add_widget(self.scrlFBtns)
def sas(self):
self.scrlFBtns.remove_widget(self.blbtns)
class BSApp(App):
def build(self):
game = BSGameMain()
return game.blmain
if __name__ == "__main__":
BSApp().run()
I'm trying to remove an Image widget after its animation is complete.
So far I have managed to animate the widget and then call the animation_complete method after the animation ends. Unfortunately, the widget is not removed.
What am I doing wrong?
class ShootButton(Widget):
def bullet_fly(self):
def animation_complete(animation, widget):
print "removing animation"
self.remove_widget(widget=bullet1)
with self.canvas:
bullet1 = Image(source='bullet.png', pos = (100,200))
animation1 = Animation(pos=(200, 300))
animation1.start(bullet1)
animation1.bind(on_complete=animation_complete)
You do not have to use the canvas to add an animation but add the widget directly using add_widget() and then remove it with remove_widget(). In your initial case bullet1 is not the children of ShootButton.
from kivy.app import App
from kivy.core.window import Window
from kivy.uix.image import Image
from kivy.uix.widget import Widget
from kivy.animation import Animation
Window.size = (360, 640)
class ShootButton(Widget):
def bullet_fly(self):
def animation_complete(animation, widget):
self.remove_widget(widget)
bullet1 = Image(source='bullet.png', pos = (100,200))
self.add_widget(bullet1)
animation1 = Animation(pos=(200, 300))
animation1.start(bullet1)
animation1.bind(on_complete=animation_complete)
class MyApp(App):
def build(self):
button = ShootButton()
button.bullet_fly()
return button
if __name__ == '__main__':
MyApp().run()
My problem is in accessing container property of DropDown, which is a GridLayout by default and contains it's children.
Simple app:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.dropdown import DropDown
from kivy.uix.button import Button
from kivy.uix.label import Label
class TestApp(App):
def build(self):
root = BoxLayout(orientation='vertical')
dropdown = DropDown()
for i in range(3):
dropdown.add_widget(Button(
text=str(i),
size_hint_y=None
)) # add 3 buttons to dropdown
dropdown.container.bind(spacing=8) # this line does not work
dropdown_button = Button(size_hint_y=.2, text='Open DropDown')
dropdown_button.bind(on_release=dropdown.open)
root.add_widget(dropdown_button)
root.add_widget(Label()) # empty space under button
return root
TestApp().run()
I tried using bind method for this, but there is no result. No indentation is set. I also would like to see the solution in kivy language because I want to use dp() function for setting spacing and it's not very convenient to pass the parameter to python file for this. Thanks in advance for any help.
Instead using bind you should just set the value directly:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.dropdown import DropDown
from kivy.uix.button import Button
from kivy.uix.widget import Widget
class TestApp(App):
def build(self):
root = BoxLayout(orientation='vertical')
dropdown = DropDown()
for i in range(3):
dropdown.add_widget(Button(
text=str(i),
size_hint_y=None
)) # add 3 buttons to dropdown
dropdown.container.spacing = 10
dropdown.container.padding = (0, 10, 0, 0)
dropdown_button = Button(size_hint_y=.2, text='Open DropDown')
dropdown_button.bind(on_release=dropdown.open)
root.add_widget(dropdown_button)
root.add_widget(Widget()) # empty space under button
return root
TestApp().run()
Using a custom container class is not supported directly. You can do it like this, but its hacky and ugly:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.dropdown import DropDown
from kivy.uix.button import Button
from kivy.uix.widget import Widget
from kivy.lang import Builder
Builder.load_string('''
<MyContainer>:
# copied from kivy.uix.dropdown._grid_kv
size_hint_y: None
height: self.minimum_size[1]
cols: 1
# custom settings
spacing: 10
padding: (0, 10, 0, 0)
''')
class MyContainer(GridLayout):
pass
class TestApp(App):
def build(self):
root = BoxLayout(orientation='vertical')
container = MyContainer()
dropdown = DropDown(container=container)
super(DropDown, dropdown).add_widget(container)
dropdown.on_container(dropdown, container)
for i in range(3):
dropdown.add_widget(Button(
text=str(i),
size_hint_y=None
)) # add 3 buttons to dropdown
dropdown_button = Button(size_hint_y=.2, text='Open DropDown')
dropdown_button.bind(on_release=dropdown.open)
root.add_widget(dropdown_button)
root.add_widget(Widget()) # empty space under button
return root
TestApp().run()
So I'd say it'd more clean to make custom spacing class as a subclass of Widget to fill space between buttons:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.dropdown import DropDown
from kivy.uix.button import Button
from kivy.uix.widget import Widget
from kivy.lang import Builder
Builder.load_string('''
<DropDownSpacing>:
size_hint_y: None
height: 20
''')
class DropDownSpacing(Widget):
pass
class TestApp(App):
def build(self):
root = BoxLayout(orientation='vertical')
dropdown = DropDown()
for i in range(3):
dropdown.add_widget(DropDownSpacing())
dropdown.add_widget(Button(
text=str(i),
size_hint_y=None
)) # add 3 buttons to dropdown
dropdown_button = Button(size_hint_y=.2, text='Open DropDown')
dropdown_button.bind(on_release=dropdown.open)
root.add_widget(dropdown_button)
root.add_widget(Widget()) # empty space under button
return root
TestApp().run()
This is the same you're doing in your main BoxLayout, except I prefer to use Widget class directly instead of Label with no text.