I'm new to Kivy and I would have to think this is possible, but I can't figure it out - How can I update a Kivy label when a button is pressed, but only by referencing that Kivy id within Python? (The reason I'm trying to do it this way is because in my actual application, I would like several labels to update at once, which I was hoping I could do all within the button_pressed equivalent button I have in my app).
In the simple example below, I'm just trying to have the button pressed and then have the label update to 'Updated!'
Thanks very much!
My Python code:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.widget import Widget
from kivy.properties import StringProperty
import random
class TestingWidget(BoxLayout):
# This is the kv id of the Label I would like to update
label_to_update = StringProperty('')
# This is the action I would like to happen when the button is pressed
def button_pressed(self):
label_to_update.text = 'Updated!'
class TestButtonApp(App):
def build(self):
return TestingWidget()
if __name__ == '__main__':
TestButtonApp().run()
My kv file:
<TestingWidget>:
BoxLayout:
orientation: 'horizontal'
Button:
text: 'test'
on_press: root.button_pressed()
Label:
id: label_to_update
text: 'Trying to get this to update'
You definitely update all label when you press the button. Just crate a StringProperty for each and do what you are doing now.
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.widget import Widget
from kivy.properties import StringProperty
from kivy.lang import Builder #used because I didn't want to create two files
import random
Builder.load_string('''
<TestingWidget>:
BoxLayout:
orientation: 'horizontal'
Button:
text: 'test'
on_press: root.button_pressed()
Label:
id: label_to_update
text: root.label_to_update
''')
class TestingWidget(BoxLayout):
# This is the kv id of the Label I would like to update
label_to_update = StringProperty('Trying to get this to update')
#default text set
# This is the action I would like to happen when the button is pressed
def button_pressed(self):
self.label_to_update = 'Updated!'
class TestButtonApp(App):
def build(self):
return TestingWidget()
if __name__ == '__main__':
TestButtonApp().run()
Related
I want to be able to scroll within the buttons numbered 10-1 but it wont let me scroll. Any solutions? I was finally able to put the buttons in a scrollview but after all my effort I am not able to move it. It just crams into the space provided and doesn't move at all.
orientation: "vertical"
SongText:
size_hint: 1,0.35
PausePlay:
size_hint: 1,0.1
ScrollView:
orientation: "vertical"
PlayList:
orientation: "vertical"
AddDeleteShuffle:
size_hint: 1,0.2
<SongText>:
Label:
id: songtitle
text: "Song Title"
<PausePlay>:
Button:
id: play
text: "Play"
Button:
id: pause
text: "Pause"
This is the main area of focus I think nothing is needed here but who knows.
<PlayList>: #Main area of conceren
<AddDeleteShuffle>:
BoxLayout:
Button:
text: "Shuffle"
Button:
text: "Delete"
Button:
text: "Shuffle"
kv file ^
py file
import kivy
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.scrollview import ScrollView
from kivy.uix.stacklayout import StackLayout
from kivy.uix.gridlayout import GridLayout
from kivy.metrics import dp
from kivy.core.audio import SoundLoader
from kivy.properties import ObjectProperty, StringProperty
from kivy.uix.screenmanager import ScreenManager, Screen
class AddDeleteShuffle(BoxLayout):
pass
class PlayList(BoxLayout):
def __init__(self,**kwargs):
super().__init__(**kwargs)
for i in range(0,10):
size = dp(100)
b = Button(text=str(i+1), size_hint=(1,None), size=(size,size))
self.add_widget(b)
Class for the playlist it is inside a scroll view, but I can't move it. Maybe I have to add a layout in the kv file. I have no idea.
class PausePlay(BoxLayout):
pass
class SongText(BoxLayout):
pass
class AppLayout(BoxLayout):
pass
class Sound5App(App):
def build(self):
return AppLayout()
if __name__ == "__main__":
Sound5App().run()
How do I change the button's color when it's down? As in, when you press the button, replace the blue-ish colour into another one?
I've tried fiddling around with background_color_down, background_color_normal, I tried using canvas and the sort but nothing seems to have the effect I intend it to
Or you could try giving the path to a png file with your design of the pressed button to the background_down attribute. Here my file is called "pressed.png" and is located within the same folder as the python programm. this is a link to something i made within 30 seconds in inkscape.
#!/usr/bin/python3.5
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang.builder import Builder
from kivy.properties import ObjectProperty, ListProperty
from kivy.atlas import Atlas
kv= Builder.load_string('''
<MainScreen>
my_but:my_but
orientation: "vertical"
size_hint:1,1
# size_hint: 0.3,0.3
# pos_hint:{"center_x": 1, "center_y":1}
Label:
size_hint: 0.5,0.4
text: "Look at my Button go:"
Button:
id:my_but
size_hint: 0.5,0.4
text: "klick me"
# background_normal: ""
background_down: "pressed.png"
''')
class MainScreen(BoxLayout):
my_but = ObjectProperty(None)
def __init__(self, **kwargs):
super(MainScreen, self).__init__(**kwargs)
class myApp(App):
def build(self):
return MainScreen()
if __name__ == "__main__":
myApp().run()
it is a simple program but i can not find a way to make it work. i just want to add a widget in boxlayout2 when the user presses the button (and has not writed anything in textinput) which is located in boxlayout1 .The widget do not display in screen.What should i do?
main.py
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
class BoxLayout1(BoxLayout):
def Search(self):
if self.ids.textinput.text!='':
BoxLayout2()
class BoxLayout2(BoxLayout):
def Print(self):
self.add_widget(Button(text='hello'))
class TestApp(App):
pass
TestApp().run()
and here is my kivy code
test.kv
<BoxLayout1>:
BoxLayout:
Label:
text:'Hello'
TextInput:
id: textinput
Button:
text: 'write'
on_press: root.Search()
BoxLayout:
orientation: 'vertical'
BoxLayout1:
BoxLayout2:
I see the presentation layout i want but the button is nowhere to be found.
To make it clear let's follow the stream of the app you've written.
it creates a BoxLayout and puts BoxLayout1 and BoxLayout2 in it, the second one doesn't have any content. When you click on write, the app checks the content of the text box and if valid, calls the constructor of BoxLayout2! Now at this point it creates an instance of this class, but does not keep it's reference so it will be discarded immediately. Now what you want is to call a function of a currently existing instance, not to create another one. Here's the code:
python:
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
class BoxLayout1(BoxLayout):
def Search(self):
if self.ids.textinput.text!='':
self.parent.ids.bxl2.addButton()
# BoxLayout2()
class BoxLayout2(BoxLayout):
def addButton(self):
button=Button(text='hello')
self.add_widget(button)
kivy language:
<BoxLayout1>:
BoxLayout:
Label:
text:'Hello'
TextInput:
id: textinput
Button:
text: 'write'
on_press: root.Search()
BoxLayout:
orientation: 'vertical'
BoxLayout1:
BoxLayout2:
id:bxl2
Simple problem I'm having:
When I click a button in my Kivy/Python app, I want to gain access to the ID of that button.
# Kivy code
Button:
id: position_1
on_press: app.access_button_id()
I have had various trial and error attempts but I cannot figure it out. The button is nested as follows (as part of a bigger app), if this is a factor in my problem:
FloatLayout:
AnchorLayout:
ScreenManager:
Screen:
BoxLayout:
FloatLayout:
Button:
id: position_1
on_press: app.access_button_id()
Here is my Python code, which returns all of the id's. That's as close as I have got:
# Python code
def access_button_id(name):
print(self.root.ids)
The problem I've got is that I don't even know what I should be looking at in the documentation as I do not fully understand the terminology yet, so I can't find the right information to learn from.
EDIT:
The (name) passed into the function is for some other functionality, not related to this problem.
You already know the id - you set it yourself. These are mostly used as a hard-coded values in your code:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
Builder.load_string('''
<MyWidget>:
Button:
id: id_value_1
text: 'Print my id'
on_press: print({'id_value_1': self.proxy_ref})
Button:
id: id_value_2
text: 'Print all ids'
on_press: print(root.ids)
''')
class MyWidget(BoxLayout):
pass
class MyApp(App):
def build(self):
widget = MyWidget()
print({'id_value_1': widget.ids['id_value_1']})
return widget
if __name__ == '__main__':
MyApp().run()
Why do you need id of a Button if you already have an access to it? What are you trying to accomplish?
EDIT
An example solution to problem mentioned in the comment:
import random
import functools
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.popup import Popup
from kivy.uix.button import Button
from kivy.lang import Builder
Builder.load_string('''
<MyWidget>:
Button:
text: 'B1'
on_press: root.open_popup(self)
Button:
text: 'B2'
on_press: root.open_popup(self)
''')
class MyWidget(BoxLayout):
def open_popup(self, caller):
fun = functools.partial(self.rename, caller)
popup = Popup(
title='Test popup',
content=Button(
text='rename',
on_press=fun
),
size_hint=(None, None), size=(400, 400)
)
popup.open()
def rename(self, caller, *args):
caller.text = ''.join(chr(random.randint(48, 90)) for i in range(5))
class MyApp(App):
def build(self):
return MyWidget()
if __name__ == '__main__':
MyApp().run()
I'm making an app to rename files that come from a scanner in a specific format.
The idea is to scan the directory and load a list of files, which are renamed according to the text in the textinput box. I've stripped down the app to come directly to the problem
import csv, os, datetime, string, shutil
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen, ScreenManager, FadeTransition
from kivy.properties import ObjectProperty, ListProperty, StringProperty, DictProperty
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from functools import partial
from kivy.uix.scrollview import ScrollView
class TestScreen(Screen):
def update_text(self, text):
print(text)
class ScreenManagement(ScreenManager):
pass
class TestApp(App):
default_font_size = 15
def build(self):
compiled_kv_file = Builder.load_file("TestApp.kv")
return compiled_kv_file
if __name__ == "__main__":
print("Main loop")
TestApp().run()
and the kv file is
#: import FadeTransition kivy.uix.screenmanager.FadeTransition
ScreenManagement:
transition:FadeTransition()
TestScreen:
<TestScreen>:
name: "TestScreen"
Button:
text:"Test Screen"
size_hint: 0.2,0.1
pos_hint: {"x":0.2,"y":0.8}
font_size: 20
TextInput:
id: my_textinputa
text:"File Screen"
size_hint: 0.2,0.1
pos_hint: {"x":0.4,"y":0.8}
font_size: 20
on_text:
root.update_text(self.text)
Label:
size_hint: 1,0.5
pos_hint: {"x":0,"y":0}
text: my_textinputa.text
font_size: 20
I'm using windows 10 and eclipse with pydev, if thats relevant. The textinput returns the entered text to the .py file. But the textinput does not update the entered text. Furthermore, There seem to be two labels rather than 1.
My gut says that I'm somehow adding two sets of widgets on top of each other. Since only the top one is changed, the text does not change on the bottom one. The output in the console is correct. Yet the textinput box doesnt update itself.
Can someone suggest how to get the textinput to update correctly?
Having multiple .kv files defining the root widget can produce this issue. One solution would be to drop the Builder.load_file("TestApp.kv")
class TestApp(App):
default_font_size = 15
def build(self):
pass
and rename the .kv file to the name of the App instance (test.kv in this case). In this way, kivy will only load one .kv file as the root widget.