Reputation: 41
I'm using a loop to create 27 label instances. These labels need to be numbered using their Label.text method - This I've achieved.
I also need to be able to re-colour these labels (canvas rectangle) using a python function (based on other inputs). This is the bit that doesn't work
Basically, the init method of the GridLayout creates 29 instances of the custButton() Label. This loop also re-numbers (label.text) the buttons, but the re-coloring of one label does not work.
I've isolated that self.pos and self.size are both returning (0,0) in the xBackground_Color function - this is why the new rectangle doesn't draw after the old one is cleared (the clear works).
Why doesn't self.pos and self.size work from the python side?
I've tried soooooooo many things! Please help if you can.
Here's kvMain.kv :
#:kivy 1.0.9
FloatLayout:
canvas:
Color:
rgba: (64/255, 64/255, 64/255, 1) #Whole screen background
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
orientation: 'vertical'
padding: 10
FloatLayout: #Dummy widget
myGrid:
<myGrid>:
cols: 9
spacing: 3
padding: 3
canvas.before:
Color:
rgba: (216/255, 216/255, 216/255, 1)
Rectangle:
pos: self.pos
size: self.size
<custButtom>:
canvas.before:
Color:
rgba: (191/255, 191/255, 191/255, 1)
Rectangle:
pos: self.pos
size: self.size
font_size: 14
color: (90/255, 90/255, 90/255, 1)
text: 'Er' #Don't ever want to see this text. Will set each label in loop
size: self.texture_size
Here's main.py:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label
from kivy.graphics.vertex_instructions import Rectangle, Line
from kivy.graphics.context_instructions import Color
IN_Labels = {}
class custButtom(Label):
def __init__(self, **kwargs):
super(custButtom, self).__init__(**kwargs)
def xtext(self, newText):
self.text = newText
self.size = self.texture_size
def xbackground_color(self, newR, newG, newB, newA):
print('IN_Labels[14] pos ('+ str(IN_Labels[14].pos[0]) + ',' + str(IN_Labels[14].pos[1]) + ') size ('+ str(IN_Labels[14].size[0]) + ',' + str(IN_Labels[14].size[1]) + ')')
print('self pos ('+ str(self.pos[0]) + ',' + str(self.pos[1]) + ') size ('+ str(self.size[0]) + ',' + str(self.size[1]) + ')')
self.canvas.before.clear()
with self.canvas.before:
Color(newR, newG, newB, newA)
#Problem is that self.size and self.pos are both (0,0)
Rectangle(size=self.size, pos=self.pos)
class myGrid(GridLayout):
def __init__(self, **kwargs):
super(myGrid, self).__init__(**kwargs)
for i in range(0, 27, 1):
IN_Labels[i] = custButtom()
self.add_widget(IN_Labels[i])
#CAN change text, needs more work to get it right
IN_Labels[i].xtext(str(i))
# I need to be able to change backgroundcolor programatically
IN_Labels[14].xbackground_color(1,0,0,1)
class MainApp(App):
def build(self):
return kvMain
kvMain = Builder.load_file("kvMain.kv")
if __name__ == '__main__':
MainApp().run()
Upvotes: 0
Views: 2326
Reputation: 41
Found it! I think the problem is that the label doesn't really have size and pos at the time at which it's being asked for self.size and self.pos.
Binding a function to resize and reposition it solves the issue.
Thanks to Alexander Taylor for his excellent YouTube videos and his blog where I found the answer: https://blog.kivy.org/2014/10/updating-canvas-instructions-declared-in-python/
kvMain.kv becomes:
#:kivy 1.0.9
FloatLayout:
canvas:
Color:
rgba: (64/255, 64/255, 64/255, 1) #Whole screen background
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
orientation: 'vertical'
padding: 10
FloatLayout: #Dummy widget
myGrid:
<myGrid>:
cols: 9
spacing: 3
padding: 3
canvas.before:
Color:
rgba: (216/255, 216/255, 216/255, 1)
Rectangle:
pos: self.pos
size: self.size
<custButtom>:
#CANVAS INSTRUCTION MOVED TO PYTHON INIT
font_size: 14
color: (90/255, 90/255, 90/255, 1)
text: 'Er' #Don't ever want to see this text. Will set each label in loop
size: self.texture_size
main.py becomes:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label
from kivy.graphics.vertex_instructions import Rectangle, Line
from kivy.graphics.context_instructions import Color
IN_Labels = {}
class custButtom(Label):
def __init__(self, **kwargs):
super(custButtom, self).__init__(**kwargs)
with self.canvas.before:
Color(191/255, 191/255, 191/255, 1)
self.rect = Rectangle(pos=self.pos, size=self.size)
#Ensure that everytime the Rectangle is updated, it's repositioned correctly
self.bind(pos=self.update_rect, size=self.update_rect)
def update_rect(self, *args):
self.rect.pos = self.pos
self.rect.size = self.size
def xtext(self, newText):
self.text = newText
self.size = self.texture_size
def xbackground_color(self, newR, newG, newB, newA):
print('IN_Labels[14] pos ('+ str(IN_Labels[14].pos[0]) + ',' + str(IN_Labels[14].pos[1]) + ') size ('+ str(IN_Labels[14].size[0]) + ',' + str(IN_Labels[14].size[1]) + ')')
print('self pos ('+ str(self.pos[0]) + ',' + str(self.pos[1]) + ') size ('+ str(self.size[0]) + ',' + str(self.size[1]) + ')')
self.canvas.before.clear()
with self.canvas.before:
Color(newR, newG, newB, newA)
self.rect = Rectangle(size=self.size, pos=self.pos)
class myGrid(GridLayout):
def __init__(self, **kwargs):
super(myGrid, self).__init__(**kwargs)
for i in range(0, 27, 1):
IN_Labels[i] = custButtom()
self.add_widget(IN_Labels[i])
#CAN change text, needs more work to get it right
IN_Labels[i].xtext(str(i))
# I need to be able to change backgroundcolor programatically
IN_Labels[14].xbackground_color(1,0,0,1)
class MainApp(App):
def build(self):
return kvMain
kvMain = Builder.load_file("kvMain.kv")
if __name__ == '__main__':
MainApp().run()
Upvotes: 1