How can I update screen values when I change the screen - python

I have a script in python and a kivy file with different screens. In screen 1 i introduce some information in a TextInput and when I change to the following screen (screen 2) I want to recover the values of the variable I introduce in TextInput of screen 1. I have problem to update value in function __init__ of screen 2.
I don't know which is the best way to update values automatically.
class PantallaDos(Screen):
def __init__(self, *args):
super(PantallaDos, self).__init__(**kwargs)
softinput_mode = 'below_target'
Window.softinput_mode = softinput_mode
self.ids['pol'].text = 'verdadero'
Kivy kv.file
<PantallaDos>:
BoxLayout:
orientation: 'vertical'
padding: 10
spacing: 3
canvas:
Color:
rgb: 0.15,0.14,0.14
Rectangle:
pos: self.pos
size: self.size
....
SLabel:
id: pol
size_hint: None, None
size: root.width, 30

You can save the shared data in the ScreenManager class, or App class forexample.
Or just access it directly in kv.
Here is an example, where you just use the id of the textinput, in kv, to set the label text in the other screen.
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
Builder.load_string("""
<Manager>:
Screen:
name: 'first'
BoxLayout:
TextInput:
id: ti
text: 'type something'
Button:
text:'go to other'
on_press: app.sm.current = 'other'
Screen:
name: 'other'
BoxLayout:
Label:
text: ti.text
Button:
text:'go to first'
on_press: app.sm.current = 'first'
""")
class Manager(ScreenManager):
pass
class ClassApp(App):
def build(self):
self.sm = Manager()
return self.sm
if __name__ == '__main__':
ClassApp().run()

Related

AttributeError: 'super' object has no attribute '__getattr__' in Kivy

I am facing an error when trying to add buttons to a specific GridLayout using ids. Ideally the code below should generate 10 buttons in the GridLayout with an id of grids, but instead the error that shows up is
AttributeError: 'super' object has no attribute 'getattr'
The code in my main.py file is -->
import kivy
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
from kivy.uix.scrollview import ScrollView
from kivy.core.window import Window
from kivy.uix.widget import Widget
from kivy.clock import mainthread
Builder.load_file("design.kv")
class RoundedButton(Button):
pass
class RootWidget(ScreenManager):
pass
class MainScreen(Screen):
def on_enter(self):
for i in range(10):
button = RoundedButton()
self.ids.grids.add_widget(button)
class MainApp(App):
def build(self):
return RootWidget()
class RootWidget(ScreenManager):
pass
if __name__ == "__main__":
MainApp().run()
and the code in my design.kv file is -->
<MainScreen>:
canvas.before:
Color:
rgba: (245/255,245/255,245/255,245/255)
Rectangle:
pos: self.pos
size: self.size
GridLayout:
id: box1
cols:1
spacing:5
GridLayout:
id: box
cols:1
size_hint_y: 0.10
TextInput:
id: ti
hint_text: 'Search'
size_hint: 1, 0.05
text_size: self.width, self.height
background_normal: ''
ScrollView:
id: scrolls
do_scroll_x:False
spacing: 10, 5
GridLayout:
id: grids
cols:1
RoundedButton:
text: "hi"
size_hint: .98, .25
<RoundedButton#Button>
background_color: (0,0,0,0)
background_normal: ''
canvas.before:
Color:
rgba: (1,0,0,1)
RoundedRectangle:
size: self.size
pos: self.pos
radius: [10]
<RootWidget>:
MainScreen:
name: "main_screen"
I was wondering what the issue is
You need to call another function with Clock.schedule_once in on_enter function and try to load your widgets in it. It happens because kivy doesn't let you add widgets before first frame so we can give order kivy to add widgets soon as possible with that.
Example code below:
def on_enter(self):
Clock.schedule_once(self.load_buttons)
def load_buttons(self,*args):
for i in range(10):
button = RoundedButton()
self.ids.grids.add_widget(button)

Kivy: How to add buttons to StackLayout from a list

I want to use a list of values like ['btn1', 'btn2','btn3'] to create buttons dynamically on my layout.
After that I want capture the name of the button when pressed
but I'm stuck at adding buttons step please help
This is my main.py
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.button import Button
Builder.load_file('design.kv')
class MyLayout(Widget):
btns = ['btn1', 'btn2','btn3']
for i in btns:
self.add_widget(Button(text = i))
class MyApp(App):
def build(self):
return MyLayout()
if __name__ == "__main__":
MyApp().run()
and this is my design.kv file
<MyButton#Button>:
font_size: 24
size_hint: [.50, None]
height: 60
<MyLayout>
GridLayout:
rows: 2
size: root.width, root.height
Label:
size_hint: 1, None
size: 120 , 120
text: "Welcome"
font_size: 42
rgb: utils.get_color_from_hex('#5ee2e5')
ScrollView:
do_scroll_x: False
do_scroll_y: True
StackLayout:
canvas:
Color:
rgb: utils.get_color_from_hex('#5ee2e5')
Rectangle:
pos: self.pos
size: self.size
cols:1
pos_hint: {'center_x':.5}
size_hint_y: None
spacing: 5
padding: 10
height: self.minimum_height
top: self.height
MyButton:
text: "Btn1"
You can do that by adding an id for the StackLayout in kv:
StackLayout:
id: stack
Then add a method in the MyLayout class to add the Buttons, along with a call to that method in the MyApp class:
class MyLayout(Widget):
def add_butts(self, dt):
btns = ['btn1', 'btn2', 'btn3']
for i in btns:
self.ids.stack.add_widget(Button(text=i, size_hint=(None, None), size=(100, 60)))
class MyApp(App):
def build(self):
ml = MyLayout()
Clock.schedule_once(ml.add_butts)
return ml

How Can I Remove BoxLayout?

I want to remove a Boxlayout in my widget, but I cant.
There is a Boxlayout at the begining of the app called "Speca". After my sellections it must be removed.
When you run the app, sellect something in "Home" Spinner and click any of the new Toggle buttons.
Wtih the press of any of the Toggle buttons "Speca" must disappear.
Please help.
Here is main.py:
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.widget import Widget
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.scrollview import ScrollView
from kivy.uix.spinner import Spinner
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.properties import ObjectProperty, StringProperty, BooleanProperty
from kivy.properties import ListProperty
from collections import OrderedDict
from kivy.uix.togglebutton import ToggleButton
data1=["mother","father","son"]
data2=["uncle","aunt","grandfather"]
data3=["jack","mike","simon"]
data4=["1898","1975","1985","1885"]
amd="0dp"
class MainWidget(Widget):
def remove_layout(self, *ignore):
self.remove_widget(self.layout)
global amd
an0=tuple(list(OrderedDict.fromkeys(data1)))
cal5= ObjectProperty()
cal6= ObjectProperty()
def btn10(self,text):
if self.cal5:
self.cal5.parent.remove_widget(self.cal5)
self.cal5 =ModelSpecifications()
a=data2
b=data3
c=data4
mi=[]
n=0
while n < len(a):
aba=n
mi.append(aba)
n+=1
for i in mi:
self.b1=MyTButton(text=str(i),size_hint=(1,None),height="100dp",group="selections")
self.cal5.add_widget(self.b1)
self.ids.scd.add_widget(self.cal5, index=3)
def on_state(self, togglebutton): #<----THIS IS THE TUGGLEBUTTON I WANT USE
global amd
tb = togglebutton
text1=tb.text
if text1=="0":
amd="50dp"
elif text1=="1":
amd="100dp"
else:
amd="200dp"
if self.cal6:
self.cal6.parent.remove_widget(self.cal6)
self.cal6 =Spec()
self.ids.scd.add_widget(self.cal6, index=2)
class SecondPage(ScrollView):
pass
class Speca(BoxLayout): #<------ THIS IS THE BOXLAYOUT I WANT TO REMOVE
pass
class Spec(BoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.size_hint=(1,None)
self.height=amd
class MyTButton(ToggleButton):
def __init__(self, **kwargs):
super().__init__(**kwargs)
class ModelSpecifications(BoxLayout): #this is the class I want add after my spinner selection
pass
class Calculation(GridLayout):
pass
class MyApp(App):
pass
MyApp().run()
here is my.kv :
MainWidget:
<MainWidget>:
hideable: hideable
ScreenManager:
id: scmanager
size: root.width, root.height
Screen:
id: scndpage
name: "second"
SecondPage:
Calculation:
id:scd
cols:1
height: self.minimum_height
row_default_height: "70dp"
size_hint_y: None
spacing:"10dp"
canvas.before:
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
size_hint: 1, None
height: "50dp"
pading:"10dp"
spacing:"10dp"
orientation: "vertical"
BoxLayout:
orientation: "horizontal"
Label:
text:"Name:"
color: 0,0,0,1
TextInput:
text:"---"
color: 0,0,0,1
Label:
text:"Surname:"
color: 0,0,0,1
TextInput:
text:"-----"
color: 0,0,0,1
BoxLayout:
id:scdd
size_hint: 1, 1
height: "100dp"
orientation: "vertical"
BoxLayout:
size_hint: 1, None
height: "50dp"
orientation: "horizontal"
Label:
text: " Sellection:"
color: 0,0,0,1
Spinner:
text: 'Home'
values: root.an0
on_text: app.root.btn10(self.text)
Speca: #<------ THIS IS THE BOXLAYOUT I WANT TO REMOVE
Button:
text:" Calculate"
Button:
text:"Sellect"
Button:
text:"Back"
<ModelSpecifications>:
id:anss
pading:"10dp"
spacing:"10dp"
size_hint: 1, None
height: "100dp"
orientation: "horizontal"
<MyTButton#ToggleButton>: #<----THIS IS THE TUGGLEBUTTON I WANT USE
on_state:
app.root.on_state(self)
<Speca>: #<------ THIS IS THE BOXLAYOUT I WANT TO REMOVE
orientation:"vertical"
Label:
color: (1,1,0,1)
text:"I WANT TO REMOVE THIS PART WHEN I PRESS ANY OF TOGGLE BUTTONS"
Please run the app and see it.
Looks to me like speca is a child of the calculation widget with ID scd. So give speca an ID and then Remove speca via ids in on_srate python function.
Kv
SecondPage:
Calculation:
id:scd
speca:
id: speca
py
def on_state():
self.root.ids.scd.remove_widget(self.root.ids.speca)
YES.
When I make those changes;
Kv
SecondPage:
Calculation:
id:scd
speca:
id: speca
py
def on_state():
self.ids.scd.remove_widget(self.ids.speca)
It works.

Overlapping of custom Widget in ScrollView GridLayout in Kivy

this is a trial code that I want to implement in my final project.
Python Code:
import kivy
kivy.require('1.0.6')
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
class Wid(BoxLayout):
def settxt(self,i):
lab = self.ids['lab']
but = self.ids['but']
lab.text = "Label Number {}".format(i)
but.text = "Button Number {}".format(i)
class Win1(Screen):
i=0
def addw(self):
box1 = self.ids['box1']
self.i = self.i +1
w = Wid()
w.settxt(self.i)
box1.add_widget(w)
def switch(self):
sm.current="win2"
class Win2(Screen):
def switch(self):
sm.current="win1"
class WindowManager(ScreenManager):
pass
kv = Builder.load_file("test.kv")
sm = WindowManager()
screens = [Win1(name="win1"), Win2(name="win2")]
for screen in screens:
sm.add_widget(screen)
sm.current = "win1"
class Test(App):
def build(self):
return sm
if __name__ == '__main__':
Test().run()
Kivy Code:
<Wid>:
lab:lab
but:but
BoxLayout:
height: self.minimum_height
size: root.size
Label:
id: lab
Button:
id: but
<Win1>
name:"win1"
box1:box1
BoxLayout:
height: self.minimum_height
orientation: "vertical"
BoxLayout:
size_hint: 1,0.2
Button:
text:"window 2"
on_release:
root.switch()
Button:
text:"add wid"
on_release:
root.addw()
ScrollView:
GridLayout:
id:box1
orientation: "vertical"
spacing: 2
size_hint_y: None
height: self.minimum_height
row_default_height: 60
cols:1
<Win2>
name: "win2"
BoxLayout:
id: bl
height: bl.minimum_height
size_hint_y: None
Button:
text:"window 2"
on_release:
root.switch()
With the press of the switch, I expect that my custom widget to get in the gridlayout in the scrollview, one below the other. But instead, each new widget appears in the last cell of the layout and overlaps on the previous one and empty cells keep on forming above them.
Don't know where it's going wrong.
Here I have moved the kv to a separate file, and dynamically created the screens.
Key points: I add the screens dynamically in on_start, this is after the build has completed. I create the ScreenManager in kv, and use the id to add the screens. In the kv code I put the ScreenManger in a BoxLayout. This is a personal preference. I do this so when accessing objects the root widget is not the screen manager. Therefore in the switch() methods, the addressing uses the assigned id, rather than relying on the root widget being a screenmanager.
FWIW: If the switch code is only going to change screens I would move those single lines into KV.
import kivy
kivy.require('1.0.6')
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import Screen
class Wid(BoxLayout): # Change to layout
def settxt(self, i):
lab = self.ids['lab']
but = self.ids['but']
lab.text = "Label Number {}".format(i)
but.text = "Button Number {}".format(i)
class Win1(Screen):
i = 0
def addw(self):
box1 = self.ids['box1']
self.i = self.i + 1
w = Wid()
w.settxt(self.i)
box1.add_widget(w)
#staticmethod
def switch():
app = App.get_running_app()
app.root.ids.sm.current = "win2"
class Win2(Screen):
#staticmethod
def switch():
app = App.get_running_app()
app.root.ids.sm.current = "win1"
class WidgetQ1App(App):
def build(self):
return Builder.load_file('widgetq.kv')
def on_start(self):
screens = [Win1(name="win1"), Win2(name="win2")]
sm = self.root.ids.sm
for screen in screens:
sm.add_widget(screen)
WidgetQ1App().run()
And the KV code:
<Wid>: # Put widgets in a layout, not a widget.
lab:lab
but:but
BoxLayout:
size: root.size
Label:
id: lab
Button:
id: but
<Win1>
# name:"win1"
box1:box1
BoxLayout:
orientation: "vertical"
BoxLayout:
size_hint: 1,0.2
Button:
text:"window 2"
on_release:
root.switch()
Button:
text:"add wid"
on_release:
root.addw()
ScrollView:
GridLayout:
id:box1
orientation: "vertical"
spacing: 2
size_hint_y: None
height: self.minimum_height
row_default_height: 60
cols:1
<Win2>:
# name: "win2"
BoxLayout:
Button:
text:"window 2"
on_release:
root.switch()
BoxLayout:
ScreenManager:
id: sm
<win2>
name: "win2"
size_hint_y: None
height: bl.minimum_height
BoxLayout:
id: bl
Button:
text:"window 2"
on_release:
root.switch()
Your custom widgets don't have a height defined, try changing to something like the above.
Also, start your class names with an upper case letter, kv requires this in some cases. For instance, win2 should be Win2.
A number of issues here, see the comments. The biggest problem I see is putting items in a widget. Put Widgets in a layout, not other widgets.
import kivy
kivy.require('1.0.6')
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import Screen
from kivy.lang import Builder
kv = """
<Wid>: # Put widgets in a layout, not a widget.
lab:lab
but:but
BoxLayout:
size: root.size
Label:
id: lab
Button:
id: but
<Win1>
# name:"win1"
box1:box1
BoxLayout:
orientation: "vertical"
BoxLayout:
size_hint: 1,0.2
Button:
text:"window 2"
on_release:
root.switch()
Button:
text:"add wid"
on_release:
root.addw()
ScrollView:
GridLayout:
id:box1
orientation: "vertical"
spacing: 2
size_hint_y: None
height: self.minimum_height
row_default_height: 60
cols:1
<Win2>:
# name: "win2"
BoxLayout:
Button:
text:"window 2"
on_release:
root.switch()
ScreenManager:
id: sm
Win1:
name: 'win1'
Win2:
name: 'win2'
"""
class Wid(BoxLayout): # Change to layout
def settxt(self,i):
lab = self.ids['lab']
but = self.ids['but']
lab.text = "Label Number {}".format(i)
but.text = "Button Number {}".format(i)
class Win1(Screen):
i = 0
def addw(self):
box1 = self.ids['box1']
self.i = self.i + 1
w = Wid()
w.settxt(self.i)
box1.add_widget(w)
#staticmethod
def switch():
app = App.get_running_app()
app.root.current = "win2"
class Win2(Screen):
#staticmethod
def switch():
app = App.get_running_app()
app.root.current = "win1"
# class WindowManager(ScreenManager):
# pass
# kv = Builder.load_file("test.kv")
# sm = WindowManager()
#
# screens = [win1(name="win1"), win2(name="win2")]
# for screen in screens:
# sm.add_widget(screen)
#
# sm.current = "win1"
class WidgetQApp(App):
def build(self):
return Builder.load_string(kv)
WidgetQApp().run()

Use On_Press Event to Change Screen without KV Language for Dynamically Created Buttons

Question:
How do you use an On-Press event to change screen for dynamically created buttons in python, and without using KV language?
Goal:
Be able to navigate to new screen from clicking on dynamically created button,
[without needing to create button in Kivy, and still getting to use Screenmanager in both Python and Kivy (not sure if you have to stick with either Python or Kivy throughout entire program?]
Things I've already tried:
Using button_share.bind(on_press = self.changer), then this:
def changer(self,*args):
ScreenManager()
screenmanager.current = 'MainScreen'
But I get the error ScreenManagerException: No Screen with name "MainScreen".
Suspicion:
I think this is because I'm creating a new instance of ScreenManager, instead of referencing the existing one. To combat this issue, I considered instantiating Screenmanager() in the App class, then referencing that instantiation in the my button def changer(self, *args) method, but that's useless if it's not the same ScreenManager I'm actually using for all my screens. And those are all defined in KV language. I wouldn't be able to switch them all over without a substantial amount of effort.
Using:
button_share.bind(on_press=partial(app.sm.setter('current'), (app.sm, "MainScreen")))`
But the error I get here is ValueError: ScreenManager.current accept only str
Below is a fully runnable example:
Note: In this example, I want to click 'Continue Editing' button, then click on 'Test 1', 'Test 2' or 'Test 3' button and have it take me to another screen.
Python Code:
from kivy.app import App
# kivy.require("1.10.0")
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.clock import Clock
from kivy.uix.widget import Widget
#from kivy.base import runTouchApp
from kivy.properties import StringProperty, ObjectProperty, NumericProperty
from functools import partial
class ScrollableLabelDataEntryInstructions(BoxLayout):
pass
class NewGarageScreen(Screen):
pass
class ContinueEditingScreen(Screen):
pass
class GarageNameBoxLayout(BoxLayout):
box_share2 = ObjectProperty()
sm = ScreenManager()
def __init__(self, **kwargs):
super(GarageNameBoxLayout, self).__init__(**kwargs)
self.orientation = "vertical"
Clock.schedule_interval(self.create_button, 5)
def create_button(self, *args):
self.box_share2.clear_widgets()
app = App.get_running_app()
#put GarageNameStartList data into app class, then pull from it in this class
top_button_share = 1.1
color = (.4, .4, .4, 1)
for i in range(len(app.GarageNameStartList)):
top_button_share -= .4
id_ = app.GarageNameStartList[i]
button_share = Button(background_normal='',
background_color = color,
id = id_,
pos_hint = {"x": 0, "top": top_button_share},
size_hint_y = None,
height = 60,
font_size = 30,
text = app.GarageNameStartList[i])
button_share.bind(on_press = self.changer)
#button_share.bind(on_press=partial(app.sm.setter('current'), (app.sm, "MainScreen")))
self.box_share2.add_widget(button_share)
def changer(self,*args):
ScreenManager()
#app = App.get_running_app()
screenmanager.current = 'MainScreen'
class BackHomeWidget(Widget):
pass
class MainScreen(Screen):
pass
class AnotherScreen(Screen):
pass
class ScreenManagement(ScreenManager):
pass
presentation = Builder.load_file("example_on_press.kv")
class MainApp(App):
GarageNameStartList = ["Test1", "Test2", "Test3"]
def Update_GarageNameStartList(self, *args):
self.GarageNameStartList = ["Test1", "Test2", "Test3"]
def build(self):
return presentation
if __name__ == "__main__":
MainApp().run()
KV Code:
#: import FadeTransition kivy.uix.screenmanager.FadeTransition
ScreenManagement:
transition: FadeTransition()
MainScreen:
AnotherScreen:
NewGarageScreen:
ContinueEditingScreen:
<SmallNavButton#Button>:
font_size: 32
size: 125, 50
color: 0,1,0,1
<MedButton#Button>:
font_size: 30
size_hint: 0.25, 0.1
color: 0,1,0,1
<BackHomeWidget>:
SmallNavButton:
on_release: app.root.current = "main"
text: "Home"
pos: root.x, root.top - self.height
<MainScreen>:
name: "main"
FloatLayout:
MedButton:
on_release: app.root.current = "edit"
text: "Edit"
pos_hint: {"x":0.3728, "top": 0.4}
<AnotherScreen>:
name: "edit"
BackHomeWidget:
SmallNavButton:
on_release: app.root.current = "main"
text: "Back"
pos: root.x, root.top - (2.25*(self.height))
FloatLayout:
MedButton:
on_release: app.root.current = "continueediting"
text: "Continue Editing"
pos_hint: {"x":0.25, "top": 0.6}
MedButton:
on_release: app.root.current = "newgarage"
text: "Create New"
pos_hint: {"x":0.3728, "top": 0.4}
<NewGarageScreen>:
name: "newgarage"
BackHomeWidget:
SmallNavButton:
on_release: app.root.current = "edit"
text: "Back"
pos: root.x, root.top - (2.25*(self.height))
FloatLayout:
MedButton:
text: "1. Groundfloor"
pos_hint: {"x":0, "top": 0.6}
<GarageNameBoxLayout>:
box_share2: box_share2
ScrollView:
GridLayout:
id: box_share2
cols: 1
size_hint_y: None
size_hint_x: 0.5
spacing: 5
padding: 130
height: self.minimum_height
canvas:
Color:
rgb: 0, 0, 0
Rectangle:
pos: self.pos
size: self.size
<ContinueEditingScreen>:
name: "continueediting"
GarageNameBoxLayout:
BackHomeWidget:
SmallNavButton:
on_release: app.root.current = "edit"
text: "Back"
pos: root.x, root.top - (2.25*(self.height))
Your code can be improved in the following things:
You do not have to create box_share2 in the .py since you're creating it in the .kv
When you use sm = ScreenManager() you are creating another ScreenManager different from the original, that is not necessary.
It is not necessary to use range and len, make your code less readable, you just have to iterate.
If we look at the structure of the .kv we see that the presentation object is the ScreenManager so you can get it via app.root.
Using the above your code the solution is:
[...]
class GarageNameBoxLayout(BoxLayout):
def __init__(self, **kwargs):
super(GarageNameBoxLayout, self).__init__(**kwargs)
self.orientation = "vertical"
Clock.schedule_interval(self.create_button, 5)
def create_button(self, *args):
self.box_share2.clear_widgets()
app = App.get_running_app()
sm = app.root
#put GarageNameStartList data into app class, then pull from it in this class
top_button_share = 1.1
color = (.4, .4, .4, 1)
for text in app.GarageNameStartList:
top_button_share -= .4
id_ = text
button_share = Button(background_normal='',
background_color = color,
id = id_,
pos_hint = {"x": 0, "top": top_button_share},
size_hint_y = None,
height = 60,
font_size = 30,
text = text)
button_share.bind(on_press=lambda *args: setattr(sm, 'current', "main"))
self.box_share2.add_widget(button_share)
[...]

Categories