Kivy add widgets to predefined layout - layout

Assuming I have a layout written in kv and I define a BoxLayout with an id value, how would I later add more widgets into this layout without Kv language? I could do this in python, but I feel like it would be more efficient to do this in Kv language.
Here is some example code (Note: Widgets is a BoxLayout):
<Content#BoxLayout>:
orientation: 'vertical'
Button:
text: 'Test'
BoxLayout:
id: to_change
orientation: 'horizontal'
Button:
text: 'Button 1'
<Widgets>:
orientation: 'vertical'
Content:
# How would I add this button to the layout called "to_change"?
to_change:
Button:
text: 'Button 2'

Related

Edit a Widget in Kv

I have a widget that I defined in Kv language, which exists within a layout that I also defined in Kv language. I would like to change the text of the widget in the layout in Kv. How would I go about is?
Python code:
import kivy
kivy.require('1.11.1')
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
class Test(BoxLayout):
pass
class KivyTestApp(App):
def build(self):
return Test()
app = KivyTestApp()
app.run()
Kv code:
<Header#BoxLayout>:
orientation: 'horizontal'
size_hint_y: 0.2
Button:
text: 'Button 1'
Button:
id: edit_but
<Test>:
orientation: 'vertical'
Header:
edit_but.text: 'Button 2'
# How do I do this ^ ?
Label:
text: 'Filler'
In your kv, you can add a Property to your Header rule (I named it edit_text). That property can be used to set the text of the Button by using text: root.edit_text. That Property can be set whenever you use the Header in kv as edit_text: 'Button 2':
<Header#BoxLayout>:
orientation: 'horizontal'
size_hint_y: 0.2
edit_text: ''
Button:
text: 'Button 1'
Button:
id: edit_but
text: root.edit_text
<Test>:
orientation: 'vertical'
Header:
edit_text: 'Button 2'
# How do I do this ^ ?
Label:
text: 'Filler'

python kivy : How to make switch Button work with carousel

I get:
AttributeError: 'Carousel' object has no attribute 'switch_on'
error whenever I try to click on the button
-------main.py----------
class main(App):
def build(self):
class SampBoxLayout(BoxLayout):
# For Switch
def switch_on(self, instance, value):
if value is True:
print("Switch On")
else:
print("Switch Off")
return Carousel()
sample_app = kv_main()
sample_app.run()
----------main.kv--------------
:
Label:
text: "Page 1"
size_hint: 1, .1
width :100
SampBoxLayout:
# ----------Switch ----------
BoxLayout:
BoxLayout:
orientation: "horizontal"
size_hint_x: .25
CustLabel:
text: "On / Off"
Switch:
id: switch_id
on_active: root.switch_on(self, self.active)# <--need help on this
Label:
text: "Page 2"
size_hint: 1, .1
width :100
Button:
text: "Button 2.1"
size_hint: None, None
width :100
Label:
text: "Page 3"
size_hint: 1, .1
width :100
Button:
text: "Button 3.1"
size_hint: None, None
width :100
You are using root.switch_on. As the error indicates, your root class is the carousel. Since SampBoxLayout is not root, you should give SampBoxLayout an id, and call it with it´s id.
Edited from your example:
SampBoxLayout:
id: samp
BoxLayout:
BoxLayout:
orientation: "horizontal"
size_hint_x: .25
CustLabel:
text: "On / Off"
Switch:
id: switch_id
on_active: samp.switch_on(self, self.active)
I don't know if you did something wrong when posting this, or if your code really looks like this. But you should not define classes inside your app class. Keep the classes on top level to access them in kv.
And your kv code is unusual. You have your widgets in a label.

Add custom widgets at runtime to screens

I want to add Buttons (Basicly custom Buttons with Image) as a custom Widgets to "Screen1" but I always end up with "_event.pyx not found" Error.
I've tried with "super().init(**kwargs)" and without.
Python code:
sm = ScreenManager()
class DrinkWidget(Widget):
pass
class HomeScreen(BoxLayout):
def switch(self, to):
#Swithing funktion
#This is the Part, that causes the Problem I think:
class Screen1(Screen):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.add_widget(DrinkWidget(
lable_text_optn = 'test'
))
class Screen2(Screen):
pass
class ZapfanlageApp(App):
icon = 'GUI_Elemente/app_icon.png'
title = 'Zapfanlage'
def build(self):
pass
if __name__ == "__main__":
ZapfanlageApp().run()
Kivy code (separate .kv File. The part "HomeScreen" works so far):
HomeScreen:
sm: sm
name: 'ScreenManager'
BoxLayout:
orientation: 'vertical'
rows: 2
ActionBar:
pos_hint: {'top': 1}
size_hint_y: .065
ActionView:
ActionButton:
text: 'Cocktails'
on_press:
root.switch(1)
ActionButton:
text: 'Drinks'
on_press:
root.switch(2)
ActionButton:
text: 'Einstellungen'
on_press:
root.switch(3)
ScreenManager:
id: sm
size_hint_y: .935
Screen1:
name: "screen1"
id: screen1
Screen2:
name: "screen2"
id: screen2
<Screen1#Screen>:
name: "screen_1"
id: screen1
#Here should the Buttons in GridLayout appear
<Screen2#Screen>:
name: "screen_2"
id: screen2
#This is the Custom Button I want to be inserted above
<Drink_Widget#Button>:
image_path_optn: image_path
lable_text_optn: lable_text
Button:
size_hint_x: None
size_hint_y: None
height: (root.height) -10
width: 250
on_press:
BoxLayout:
orientation: "vertical"
width: root.width
height: root.height
pos_hint: root.pos
pos: root.pos
padding: 5
Image:
source: image_path
Label:
text: label_text
I want to show a various number of DrinkWidgets on screen1 vertically and add them in runtime. But I always end up with nothing showing up or with _event.pyx not found error. Passing the code under <Screen1#Screen>: directly works.
I hope someone can help me. Thanks a lot!
Okay, it looks like you want to add a number of your DrinkWidgets to your screen when your app loads. First things first, in your .py file you have defined a class named Drink_widget but in .kv you call it DrinkWidget
Next, since you have your DrinkWidget defined as inheriting the Button class from kivy, you can easily change the text in the DrinkWidget using the text: field. Similarly, you can change the image that the button displays to be whatever you like using the background_normal: field. To change the image displayed when you click the button, use the background_down: field. Example:
<DrinkWidget#Button>:
text: "some text"
background_normal: "image1.png"
background_down: "image2.png"
So you don't need your lable_text_optn or image_path_optn fields.
Also, you are trying to add a number of widgets to a Screen widget, when really you should be adding a number of widgets to a Layout widget (FloatLayout, BoxLayout, or GridLayout). Your Screen widget should only have the Layout widget as its direct child.
Another issue I see is you have two root widgets inside your .kv file -- HomeScreen and BoxLayout unless your indentation is correct in the question.
Here is a minimal example of what I believe you are trying to get working:
main.py
from kivy.app import App
from kivy.uix.button import Button
class DrinkWidget(Button):
pass
class MainApp(App):
def on_start(self):
# This command is automatically called when your app loads up
the_screen_grid = self.root.ids.some_descriptive_id
# self.root refers to the root widget, which is the GridLayout
# self.root.ids gets me a DictProperty of all children widgets that have an id associated with them
# self.root.ids.some_descriptive_id gets me the GridLayout widget I defined with the id: some_descriptive_id
for i in range(3):
the_screen_grid.add_widget(DrinkWidget(text="drink " + str(i)))
MainApp().run()
main.kv
GridLayout:
cols: 1
Screen:
# Widgets that aren't Layouts normally only have 1 child widget
# To "add multiple widgets" to a screen, give the screen a Layout, then add widgets to the layout
GridLayout:
id: some_descriptive_id
rows: 1
Your code is a bit too long to give you an exact solution for your case, but I hope this example gives you the knowledge to fix it up for yourself!

How to manage screens from a different layout

I am trying to have a set of buttons that controls what screen is displayed while still having the buttons displayed.
bobo.py
import kivy
kivy.require("1.9.0")
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.boxlayout import BoxLayout
class ButtSection(BoxLayout):
pass
class Welcome(Screen):
pass
class AccountOne(Screen):
pass
class AccountTwo(Screen):
pass
class ScreenManagement(ScreenManager):
pass
presentation = Builder.load_file("Bobo.kv")
class BoboApp(App):
def build(self):
return presentation
main = BoboApp()
main.run()
Bobo.kv
BoxLayout:
orientation: "horizontal"
BoxLayout:
ButtSection:
orientation: "vertical"
Button:
text: "Account One"
on_press: app.root.current = "a1"
Button:
text: "Account Two"
on_press: app.root.current = "a2"
Button:
text: "Account Three"
on_press: app.root.current = "a3"
ScreenManagement:
Welcome:
name: "wel"
Label:
text: "Welcome To Bobot"
AccountOne:
name: "a1"
Label:
text: "Page: Account One"
AccountTwo:
name: "a2"
Label:
text: "Page: Account One"
When I run the script, the welcome screen is the current screen. When I click a button, is does nothing even thought i included 'on_press: app.root.current = ''.
You have to analyze what app.root means and see if it is the ScreenManager.
app refers to the application that is the BoboApp instance, that is, main. root refers to the object that returns the build method of the application, that is, presentation. And presentation is the root object of the .kv, that is, the BoxLayout. With what we conclude that app.root is not the ScreenManager for which the error is valid.
Instead of using the root as a way to get to the ScreenManager it can be accessed through an id since the id is accessible within the whole tree.
On the other hand I have changed the names of the Screen to match the ones you want to set.
BoxLayout:
orientation: "horizontal"
BoxLayout:
ButtSection:
orientation: "vertical"
Button:
text: "Account One"
on_press: manager.current = "a1" # <---
Button:
text: "Account Two"
on_press: manager.current = "a2" # <---
Button:
text: "Account Three"
on_press: manager.current = "a3" # <---
ScreenManagement:
id: manager # <---
Welcome:
name: "a1" # <---
Label:
text: "Welcome To Bobot"
AccountOne:
name: "a2" # <---
Label:
text: "Page: Account One"
AccountTwo:
name: "a3" # <---
Label:
text: "Page: Account One"

Adding text to texture - Kivy

I want to add a few text fields defined by a user to an image and export is as one .png file.
I thought of just making screenshot of whole widget but that's low quality and it's not what I'm realling looking into.
For now I have code:
kv = '''
PageLayout:
orientation: 'vertical'
RelativeLayout:
Image:
pos:10,10
id: template
source: 'template.png'
Label:
pos: 50,50
markup: True
text: 'Test'
BoxLayout:
Button:
text: 'Configure'
on_release: app.open_settings()
Button:
id: savebtn
text: 'Save'
on_release: app.sc()
'''
And is it better to write it in kv language or python?
Thanks for any input!

Resources