I want to create something that changes its general layout when the orientation, or size, of the window is changed. In the below example, I was trying to do this with 3 buttons. But it fails, and complains that the buttons already have a parent when I try to add them to a layout. Why do they already have a parent? I never added them to the AdaptWidget...
More importantly, how should I achieve what I want to achieve?
Code below:
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
class AdaptWidget(BoxLayoutWrite failed: Broken pipe
def __init__(self, **kw):
super(AdaptWidget, self).__init__(**kw)
self.but1 = Button(text='but1')
self.but2 = Button(text='but2')
self.but3 = Button(text='but3')
self.layout = None
def on_size(self, *args):
self.clear_widgets()
if self.size[0] > self.size[1]:
self.layout = BoxLayout(orientation='horizontal')
self.but1.size_hint = 0.7, 1
self.layout.add_widget(self.but1)
vert = BoxLayout(orientation='vertical')
self.layout.add_widget(vert)
self.but2.size_hint = (1,0.5)
self.but3.size_hint = (1,0.5)
vert.add_widget(self.but2)
vert.add_widget(self.but3)
else:
self.layout = BoxLayout(orientation='vertical')
self.but1.size_hint = 1, 0.7
self.layout.add_widget(self.but1)
horiz = BoxLayout(oreintation='horizontal')
self.layout.add_widget(horiz)
self.but2.size_hint = 0.5, 1
self.but3.size_hint = 0.5, 1
horiz.add_widget(self.but2)
horiz.add_widget(self.but3)
self.add_widget(self.layout)
class TestLayoutApp(App):
def build(self):
return AdaptWidget()
if __name__ == '__main__':
TestLayoutApp().run()
Every time the size of your AdaptWidget changes, your on_size callback runs - but the callback doesn't remove any widgets from their parents, so on_size will always crash the second time it is called. You can always ensure a widget is removed from its parent:
if widget.parent is not None:
widget.parent.remove_widget(widget)
EDIT:
3 days ago I wrote this "answer", although I could not make the above suggestions work.
But now someone here: https://groups.google.com/forum/#!topic/kivy-users/Z5fjt5tNys8
Showed me how to do it.
So here comes the solution:
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
class AdaptWidget(BoxLayout):
def __init__(self, **kw):
super(AdaptWidget, self).__init__(**kw)
# but1 = Button(id='but1', text='button1')
# but1 = ObjectProperty(None)
# self.but1 = ObjectProperty(None)
self.add_widget(Button(id='but1', text='button1'))
self.add_widget(Button(id='but2', text='button2'))
self.add_widget(Button(id='but3', text='button3'))
def on_size(self, *args):
if self.width > self.height:
self.orientation = 'horizontal'
# self.child.but1.size_hint = (0.7, 1)
# but1.size_hint = (0.7, 1)
# self.ids.but1.size_hint = (0.7, 1)
self.children[2].size_hint = (0.7, 1)
self.children[1].size_hint = (0.5, 1)
self.children[0].size_hint = (0.5, 1)
else:
self.orientation = 'vertical'
self.children[2].size_hint = (1, 0.7)
self.children[1].size_hint = (1, 0.5)
self.children[0].size_hint = (1, 0.5)
class TestLayoutApp(App):
def build(self):
return AdaptWidget()
if __name__ == '__main__':
TestLayoutApp().run()
Note that the solution above is much cleaner than the original code. No need to remove or clear any widgets. You just change their attributes.
EDIT:
Part of the problem was that the 'buildozer.spec'-file contained this:
# (str) Supported orientation (one of landscape, sensorLandscape, portrait or all)
orientation = portrait
Instead of this:
# (str) Supported orientation (one of landscape, sensorLandscape, portrait or all)
orientation = all
Related
I have a screen with a StackLayout. The first row of the stack includes a textinput and a "+" button which is meant to add another identical row below the actual one in a loop (i.e. another textinput with another "add" button). Then there is a "Save" button, which is supposed to be always at the end of the stack.
The dictionary is supposed to later grab the input from the text field, when pressing the save button, but this should not be relevant to my problem.
There are two problems with my code:
First, when I press the "+" button in a row, the button that gets highlighted is not this button itself, but the one in the row below (e.g. if there are three rows and I press the button in the second row, the button in the third row is highlighted)
Second and most importantly, starting from the second row onwards, each press of the "+" button adds a new row above the actual one, rather than below it.
I am aware that kivy assigns reverse order to the widgets (i.e. the one added last will be drawn first) and that is why I am manually assigning indexes to the new rows. However, I cannot achieve the desired behavior.
Here is a minimal working version:
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
from kivy.uix.stacklayout import StackLayout
from kivy.uix.screenmanager import ScreenManager, Screen
class AddWindow(Screen):
def __init__(self, **kwargs):
super(AddWindow, self).__init__(**kwargs)
self.grid = StackLayout()
self.grid.pos_hint = {"x":0.05,"top":0.8}
self.grid.size_hint = (0.9,None)
self.add_widget(self.grid)
self.i = 1
self.n = 1
self.inputs = {}
self.ing1 = TextInput(size_hint=(0.9,'0.3sp'))
self.grid.add_widget(self.ing1)
self.inputs['0'] = 'ing1'
self.addIng = Button(text="+", size_hint=(0.1,'0.3sp'))
self.addIng.bind(on_press=self.addIngredient)
self.grid.add_widget(self.addIng)
self.doneButton = Button(text="Save")
self.grid.add_widget(self.doneButton, index=0)
def addIngredient (self, instance):
self.ing = TextInput(size_hint=(0.9,'0.3sp'))
self.inputs[self.i] = 'ing{}'.format(self.i+1)
self.grid.add_widget(self.ing, index=self.n+1)
self.addNext = Button(text="+", size_hint=(0.1,'0.3sp'))
self.addNext.bind(on_press=self.addIngredient)
self.grid.add_widget(self.addNext, index=self.n+2)
self.i += 1
self.n += 2
print(self.inputs)
WMan = ScreenManager()
WMan.add_widget(AddWindow(name='add'))
class RecipApp(App):
def build(self):
return WMan
if __name__ == "__main__":
RecipApp().run()
What am I missing? Here is a screenshot for better clarity:
Screenshot
Here is a brute force method to do what you want by rebuilding the StackLayout each time a + `Button is pressed:
def addIngredient(self, instance):
tmp_children_list = self.grid.children[:]
self.grid.clear_widgets()
for index in range(len(tmp_children_list)-1, -1, -1):
child = tmp_children_list[index]
self.grid.add_widget(child)
if child == instance:
# this is the pressed Button, so add new row after it
self.n += 1
self.ing = TextInput(size_hint=(0.9,'0.3sp'))
self.ing.text = str(self.n) # add text just for identification
self.grid.add_widget(self.ing)
self.addNext = Button(text="+", size_hint=(0.1,'0.3sp'))
self.addNext.bind(on_press=self.addIngredient)
self.grid.add_widget(self.addNext)
Here is a quick and dirty approach , where your problems should be fixed due to a remove and add of the save button. Between those to actions you add a new row before you finally add the save button again. Hope it helps you to adjust your code. The key part is the custom on_press method of the AddButton.
from kivy.app import App
from kivy.uix.stacklayout import StackLayout
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.core.window import Window
class AddButton(Button):
def __init__(self, **kwargs):
super(AddButton, self).__init__(**kwargs)
def on_press(self):
self.parent.remove_widget(self.parent.save_btn)
self.parent.add_widget(TextInput(size_hint=(None, None), size=(Window.width * 0.8 - self.parent.padding[1], Window.height * 0.1)))
self.parent.add_widget(AddButton(text="+", size_hint=(None, None), size=(Window.width * 0.2, Window.height * 0.1)))
self.parent.add_widget(self.parent.save_btn)
class MyApp(App):
def build(self):
Window.size = (400, 600)
layout = StackLayout(orientation="lr-tb", padding=(20, 40))
layout.save_btn = Button(text="Save", size_hint=(None, None),
size=(Window.width - layout.padding[1], Window.height * 0.1))
layout.add_widget(TextInput(size_hint=(None, None), size=(Window.width * 0.8 - layout.padding[1], Window.height * 0.1)))
layout.add_widget(AddButton(text="+", size_hint=(None, None), size=(Window.width * 0.2, Window.height * 0.1)))
layout.add_widget(layout.save_btn)
return layout
MyApp().run()
The Goal
I want to create a small script that adds buttons dynamically, but still lets me perform functions on specific ones via root.
My Methods
I made this script.
It is capable of dynamically adding large buttons along the top. Each of these buttons slightly changes its own color when pressed.
It has two smalls buttons at the bottom. The first button dynamically adds new large buttons along the top.
The second button resets the color of the first large button on the top.
My Code
#!/usr/bin/env python3
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
Builder.load_string('''
<RootWidget>:
Button:
text: 'Add'
size_hint: (None, None)
size: (40, 40)
pos: (40, 40)
group: 'action'
on_press: root.createNextTarget()
Button:
text: 'res'
size_hint: (None, None)
size: (40, 40)
pos: (100, 40)
group: 'action'
on_press: root.resetTarget()
''')
class RootWidget(FloatLayout):
def __init__(self, **kwargs):
super(RootWidget, self).__init__(**kwargs)
#note: self.ids isn't populated yet. I guess we can't use it yet.
self.createNextTarget()
def resetTarget(self):
f_target = self.ids['targetbutton0']
f_target.background_color = (1.0, 1.0, 1.0, 1.0)
return True
def countTargets(self):
return [str(x.__class__.__name__) for x in self.children if x != None].count('TargetButton')
def createNextTarget(self):
f_nextButton = TargetButton(id="targetbutton"+str(self.countTargets()),
size_hint=(None, None),
pos=(80 + (10 + 60) * self.countTargets(), 100),
size=(60, 60),
background_normal = '',
background_color = (1, 1, 1, 1),
group = 'target')
self.add_widget(f_nextButton)
f_nextButton.bind(on_press=TargetButton.lowerAllRGB)
class TargetButton(Button):
def __init__(self, **kwargs):
super(TargetButton, self).__init__(**kwargs)
def lowerAllRGB(self):
f_r, f_g, f_b, f_a = self.background_color
if f_r >= 0.1: f_r = f_r - 0.1
if f_g >= 0.1: f_g = f_g - 0.1
if f_b >= 0.1: f_b = f_b - 0.1
self.background_color = (f_r, f_g, f_b, f_a)
return True
class TestApp(App):
def build(self):
return RootWidget()
def on_stop(self):
print("TestApp.on_stop: finishing", self.root.ids)
if __name__ == '__main__':
TestApp().run()
The Problem
If I try to hit the reset button (that accesses the widget via root.ids), I get the error: KeyError: 'targetbutton0'
After finding a post about a similar problem, I thought root.ids just wouldn't work during RootWidget.__init__.
But when I use the button to add buttons after RootWidget.__init__ is finished, TestApp.on_stop() still prints:
TestApp.on_stop: finishing {}
So root.ids is still empty, and doesn't seem to include any dynamically added widgets despite me assigning an id attribute to each of them.
My questions to you
Given the way I am dynamically adding widgets, is using root.ids just worthless for my purposes?
Is there a decent way for me to access my widgets via id? I saw another question here asking something similar. But it didn't answer my question about dynamically added widgets.
Question 1 - root.ids / self.ids
Given the way I am dynamically adding widgets, is using root.ids just
worthless for my purposes?
Answer
id assigned to dynamically added widgets are not store in self.ids or root.ids. Therefore, you cannot access dynamically added widgets using self.ids['targetbutton0'] or self.ids.targetbutton0. If you do that, you will get a KeyError because it is not found in self.ids which is a dictionary type property.
When your kv file is parsed, Kivy collects all the widgets tagged with id’s and places them in this self.ids dictionary type property.
Note:
These type of id (i.e. id assigned to dynamically created widget) is deprecated and will be removed in a future Kivy version.
[WARNING] Deprecated property "<StringProperty name=id>" of object "<kivy.uix.button.Button object at 0x7feeec0968d0>" has been set, it will be removed in a future version
Question 2
Is there a decent way for me to access my widgets via id?
Solution
You could create your own list of ids of dictionary type property.
Snippets
from kivy.properties import DictProperty
class RootWidget(FloatLayout):
dynamic_ids = DictProperty({}) # declare class attribute, dynamic_ids
def __init__(self, **kwargs):
super(RootWidget, self).__init__(**kwargs)
self.createNextTarget()
def resetTarget(self):
f_target = self.dynamic_ids['targetbutton0']
f_target.background_color = (0.0, 1.0, 1.0, 1.0) # cyan colour
return True
...
def createNextTarget(self):
id = "targetbutton" + str(self.countTargets())
f_nextButton = TargetButton(id=id,
size_hint=(None, None),
pos=(80 + (10 + 60) * self.countTargets(), 100),
size=(60, 60),
background_normal = '',
background_color = (1, 1, 1, 1), # white colour
group = 'target')
self.add_widget(f_nextButton)
self.dynamic_ids[id] = f_nextButton
f_nextButton.bind(on_press=TargetButton.lowerAllRGB)
Output
Kivy 2.0 throws an error when you use id='value' when dynamically creating kivy widgets from python main file. But by using weak references you achieve the following success.
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty
from kivy.lang import Builder
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
import weakref
class MyLayout(Widget):
def use_weakref_id_to_replace_text(self, *args):
self.ids.AddUserTextBox.text = "shotta"
print("released and renamed the text to shotta")
def add_textinpt_with_weak_ref_dyn_id(self, *args):
print('Pressed and added text input box')
textinput = TextInput(pos=(380,380),text='123')
self.add_widget(textinput)
# We'll use a weak ref to add our dynamic id
self.ids['AddUserTextBox'] = weakref.ref(textinput)
class MdApp(App):
def build(self):
root = MyLayout()
Btn = Button(size=(250,250), pos=(100,100),text="Dynamic id assign n use id to rename")
Btn.bind(on_release=root.use_weakref_id_to_replace_text,on_press=root.add_textinpt_with_weak_ref_dyn_id)
root.add_widget(Btn)
return root
if __name__ == '__main__':
MdApp().run()
I am trying to create a menu using box layout in kivy. I wanted to use "root.top-self.height" so that it sticks the vertical layout from the top of screen but its still sticking from bottom. Also when I print(root.top) its strangely giving 100 which is not my screen resolution. Please let me know how can I place it accurately.
Furthermore I read somewhere that I need to use root=BoxLayout(), now after using this the button's are not clickable after adding that, before adding this I could use the buttons. Please do let me know how to deal with "root" ie screen or App size functionality.
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.label import Widget
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.layout import Layout
from kivy.uix.button import Button
from kivy.lang import Builder
## CREATING A CLASS WHICH HAS SCREEN CONTENT:
class firstScreen(BoxLayout):
def __init__(self,**kwargs):
super(firstScreen, self).__init__(**kwargs)
self.orientation = 'vertical'
root = BoxLayout()
self.pos = (0 ,root.top-self.height)
print(root.top)
self.myButton1 = Button(text='Home',
color = (1,0,0,1),
size_hint = (0.1,None),
## pos_hint = {'x':.8, 'y':'.7'},
## pos_hint = {'x':0, 'top':'0'},
pos = (0,0)
)
self.myButton2 = Button(text='Buy Now',
color = (1,0,0,1),
size_hint = (0.1,None))
self.myButton3 = Button(text='Blog',
color = (1,0,0,1),
size_hint = (0.1,None))
self.myButton4 = Button(text='Contant Us',
color = (1,0,0,1),
size_hint = (0.1,None))
self.add_widget(self.myButton1)
self.add_widget(self.myButton2)
self.add_widget(self.myButton3)
self.add_widget(self.myButton4)
def on_touch_down(self,touch):
print(touch)
def on_touch_move(self,touch):
print(touch)
def on_touch_up(self,touch):
print(touch)
## CREATING A CLASS WHICH RETURNS SOME SCREEN:
class myKivyApp(App):
def build(self):
return firstScreen()
## THIS CODE RUNS THE CLASS WHICH HAS SOME SCREEN
if __name__ == "__main__":
myKivyApp().run()
Eliminating the unused BoxLayout and setting the y component of size_hint to 1.0 means that each button will share equally in the vertical space available for the firstScreen.
class firstScreen(BoxLayout):
def __init__(self,**kwargs):
super(firstScreen, self).__init__(**kwargs)
self.orientation = 'vertical'
self.myButton1 = Button(text='Home',
color = (1,0,0,1),
size_hint = (0.1,1.0))
self.myButton2 = Button(text='Buy Now',
color = (1,0,0,1),
size_hint = (0.1,1.0))
self.myButton3 = Button(text='Blog',
color = (1,0,0,1),
size_hint = (0.1,1.0))
self.myButton4 = Button(text='Contant Us',
color = (1,0,0,1),
size_hint = (0.1,1.0))
self.add_widget(self.myButton1)
self.add_widget(self.myButton2)
self.add_widget(self.myButton3)
self.add_widget(self.myButton4)
By the way, the root.top will always be 100 in the __init__() method. The 100 is the default value and is not updated until the app is actually displayed.
This is my first post here, but I will try to be as detailled as I can.
So my application is in python, and involves a grid in kivy, where each element in the grid is supposed to contain 4 additional widgets and possibility for a fifth. The four additional widgets are supposed to be in a cross shape at the edges and the fifth in the middle.
Problem is, whenever I add a sub widget it lands in the bottom left corner on position 0,0 of the main window
So far so good. Right now I am just trying to get even one widget inside another widget to display correctly.
Heres what I attempted:
<GridCell#Label>
BoxLayout:
orientation:'horizontal'
Button:
text:'One'
size:10,10
size_hint:None,None
Building a .kv file for my app, where I would put a box layout inside of it and then a button.
Also I tried the following class configuration:
class GridCell(Label):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.root = FloatLayout()
self.button = Button(text="test")
self.button.x = self.root.x
self.button.center_y = self.root.center_y
self.root.add_widget(self.button)
self.add_widget(self.root)
Also did not work.
I am adding the grid cells by just calling .add on the grid with a newly created widget for each iteration of a for loop.
All the child widgets are apparently created, but they all land in the bottom left corner!
This is the whole code of the gui right now:
import kivy
import World
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.graphics import Color, Rectangle
kivy.require('1.10.0')
class GridCell(Label):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.root = FloatLayout()
self.button = Button(text="blargh")
self.button.x = self.root.x
self.button.center_y = self.root.center_y
self.root.add_widget(self.button)
self.add_widget(self.root)
def on_size(self, *args):
self.canvas.before.clear()
if self.id is "cliff":
with self.canvas.before:
Color(249 / 255, 6 / 255, 6 / 255, 0.3)
Rectangle(pos=self.pos, size=self.size)
if self.id is "goal":
with self.canvas.before:
Color(6 / 255, 6 / 255, 249 / 255, 0.3)
Rectangle(pos=self.pos, size=self.size)
if self.id is "start":
with self.canvas.before:
Color(11 / 255, 174 / 255, 6 / 255, 0.3)
Rectangle(pos=self.pos, size=self.size)
if self.id is "normal":
with self.canvas.before:
Color(119 / 255, 115 / 255, 115 / 255, 0.3)
Rectangle(pos=self.pos, size=self.size)
class GameGridApp(App):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.grid = GridLayout(cols=8, rows=5)
self.load_into()
def load_into(self):
world = World.World(8, 5)
world.build_gamegrid()
for cell in world.gamegrid:
name = str(cell.name)
grid_cell = GridCell()
grid_cell.text = name
if cell.start:
grid_cell.id = "start"
if cell.goal:
grid_cell.id = "goal"
if cell.cliff:
grid_cell.id = "cliff"
if cell.field:
grid_cell.id = "normal"
self.grid.add_widget(grid_cell)
def build(self):
return self.grid
customLabel = GameGridApp()
customLabel.run()
I may give an idea , that create a 'subgrids' object and a 'main grid' object that contain the 'subgrids'. These two objects would be GridLayout objects.
Here is a simple example in python2.7 :
import kivy
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
class SubGrids(GridLayout):
def __init__(self):
GridLayout.__init__(self, cols=3, rows=3);
self.add_widget(Label(text='1st'));
self.add_widget(Label(text=''));
self.add_widget(Label(text='2nd'));
self.add_widget(Label(text=''));
self.add_widget(Label(text='3rd'));
self.add_widget(Label(text=''));
self.add_widget(Label(text='4th'));
self.add_widget(Label(text=''));
self.add_widget(Label(text='5th'));
class Grids(GridLayout):
def __init__(self):
GridLayout.__init__(self, cols=2, rows = 2);
self.add_widget(SubGrids());
self.add_widget(SubGrids());
self.add_widget(SubGrids());
self.add_widget(SubGrids());
class Example(App):
def build(self):
return Grids()
if __name__ == '__main__':
x = Example();
x.run();
Hope this gives an idea.
I am writing my first Kivy app in python only (I'm avoiding kv for now). I have created a custom widget called WorldviewWidget, and I'm trying to use it as a place to draw. With the button widgets, I just give a size_hint and a pos_hint, and they show up where I want them. But with my widget, I don't know how to use the size_hint and position_hint to size the rectangle I am drawing in my WorldviewWidget. Here is the code. Thanks in advance!
#! /usr/bin/python
from kivy.app import App
from kivy.graphics import *
from kivy.core.window import Window
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.widget import Widget
from kivy.uix.button import Button
class WorldviewWidget(Widget):
def __init__(self, **kwargs):
super(WorldviewWidget, self).__init__(**kwargs)
self.canvas.clear()
print self.size, self.pos
with self.canvas:
Color(1, 0, 0, 1, mode='rgba')
# HELP! I want the rectangle to be resized when the window changes size so that it always takes up the same proportion of the screen.
self.rect = Rectangle(size=???, pos=???)
class JFROCS_App(App):
def build(self):
Window.clearcolor = [1,1,1,1]
parent = FloatLayout(size=Window.size)
worldview = WorldviewWidget(size_hint=(0.4, 0.4), pos_hint = {'x':0.2, 'y':0.2})
parent.add_widget(worldview)
start_btn = Button(text='Start', size_hint=(0.1, 0.1), pos_hint={'x':.02, 'y':.7}, background_color=[0,1,0,1])
start_btn.bind(on_release=self.start_simulation)
parent.add_widget(start_btn)
pause_btn = Button(text='Pause', size_hint=(0.1,0.1), pos_hint={'x':.02, 'y':.6}, background_color=[1,1,0,1])
pause_btn.bind(on_release=self.pause_simulation)
parent.add_widget(pause_btn)
stop_btn = Button(text='Stop', size_hint=(0.1,0.1), pos_hint={'x':.02, 'y':.5}, background_color=[1,0,0,1])
stop_btn.bind(on_release=self.stop_simulation)
parent.add_widget(stop_btn)
return parent
def start_simulation(self, obj):
print "You pushed the start button!"
def pause_simulation(self, obj):
print "You pushed the pause button!"
def stop_simulation(self, obj):
print "You pushed the stop button!"
if __name__ == '__main__':
JFROCS_App().run()
I think that this sort of task is predestined for the kivy-language but here is a solution in Python. Basically, I have used the bind-method to make your widget listen for changes in its parent's size. Have a look at this for more information on this mechanism.
from kivy.app import App
from kivy.graphics import *
from kivy.core.window import Window
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.widget import Widget
from kivy.uix.button import Button
class WorldviewWidget(Widget):
def __init__(self, **kwargs):
super(WorldviewWidget, self).__init__(**kwargs)
self.canvas.clear()
print self.size, self.pos
with self.canvas:
Color(1, 0, 0, 1, mode='rgba')
# *changed* ##############################################
self.rect = Rectangle(size=self.size, pos=self.pos)
# *new* ##########################################################
def update_size(self, instance, new_size):
print "UPDATING SIZE", instance, new_size
self.size[0] = new_size[0] * 0.4
self.size[1] = new_size[1] * 0.4
self.rect.size = self.size
self.pos[0] = self.parent.size[0] * 0.2
self.pos[1] = self.parent.size[1] * 0.2
self.rect.pos = self.pos
class JFROCS_App(App):
def build(self):
Window.clearcolor = [1,1,1,1]
parent = FloatLayout(size=Window.size)
# *changed* ##################################################
worldview = WorldviewWidget(size=(0.4*parent.size[0], 0.4*parent.size[1]),
pos=(0.2*parent.size[0], 0.2*parent.size[1]))
# makes sure that the widget gets updated when parent's size changes:
parent.bind(size=worldview.update_size)
parent.add_widget(worldview)
start_btn = Button(text='Start', size_hint=(0.1, 0.1), pos_hint={'x':.02, 'y':.7}, background_color=[0,1,0,1])
start_btn.bind(on_release=self.start_simulation)
parent.add_widget(start_btn)
pause_btn = Button(text='Pause', size_hint=(0.1,0.1), pos_hint={'x':.02, 'y':.6}, background_color=[1,1,0,1])
pause_btn.bind(on_release=self.pause_simulation)
parent.add_widget(pause_btn)
stop_btn = Button(text='Stop', size_hint=(0.1,0.1), pos_hint={'x':.02, 'y':.5}, background_color=[1,0,0,1])
stop_btn.bind(on_release=self.stop_simulation)
parent.add_widget(stop_btn)
return parent
def start_simulation(self, obj):
print "You pushed the start button!"
def pause_simulation(self, obj):
print "You pushed the pause button!"
def stop_simulation(self, obj):
print "You pushed the stop button!"
if __name__ == '__main__':
JFROCS_App().run()
And have a look at the kivy-language -- it takes care of all the binding for you :)