I have my code set up to initially add a few button widgets.
The first button will spawn a rectangular box. This is written as addfunction()
.
the second button is bound to perform hookupfull()
, which does two things - gethooks()
and hookfunc()
:
First it grabs the pos
, width
, and height
of the children of my MainWindowWidget
, and puts it in a list for each of those, then deletes extra entries from the buttons (I have my buttons as children of the MainWindowWidget
currently, but I only want the properties of the boxes). This is written as gethooks()
Secondly it calculates fancy coordinates from the list and draws a line. This is written as hookfunc()
So, if I press the first button twice and the second button once, it will create two boxes and then draw a line connecting them together. This works fine. Next on my agenda is to schedule stuff like canvas.clear()
and redraw the line, etc. every 1/60th of a second. I then create a third button widget to set a flag to start update
loop run.
However if I try to schedule hookupfull()
with Clock.schedule_interval()
it doesn't work as I think it should - not sure how to explain it or what is going on, but the scheduled code doesn't seem to "go" to the MainWindowWidget
I want. It seems to be spawning a whole bunch of other MainWindowWidget
s.
I figured it's the way I'm referring to the widgets or something with the arguments (which is what I assume to be the (self, *args)
portion of the code) or the way I'm declaring the method/function (I'm not sure of the difference between methods and functions still, sorry)
So, I tried to debug it by adding stuff like print self
in several places to see what self
was.
My code:
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.scatter import Scatter
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.button import Button
from kivy.graphics import Color, Line
from kivy.clock import Clock
boxscale = 1
global startenable
global debug_1
startenable = False
debug_1 = True
class Scatterer(Scatter):
pass
class Drawer(FloatLayout):
pass
class MainWindowWidget(FloatLayout):
def addfunction(self, *args):
s = Scatterer()
d = Drawer()
s.size = 60 * boxscale , 111 * boxscale
# default size * scale
d.size = s.size
self.add_widget(s)
s.add_widget(d)
print "button is pressed"
def startfunc(obj):
global startenable
if startenable == False:
startenable = True
else:
startenable = False
print'startenable set to',startenable
def gethooks(self, *args):
# get hook locations
self.p = []
for child in self.children:
self.p.append(child.pos)
del self.p[(len(self.p)-3):(len(self.p))]
self.w = []
for child in self.children:
self.w.append(child.width)
del self.w[(len(self.w)-3):(len(self.w))]
self.h = []
for child in self.children:
self.h.append(child.height)
del self.h[(len(self.h)-3):(len(self.h))]
if debug_1 == True:
print 'getting hook location........'
print 'self.p:',self.p # list of positions
print 'length of self.p:',len(self.p)
print 'widths:',self.w # list of widths
print 'heights:',self.h# list of heights
print self
def hookfunc(self, *args):
# draw line based on hooks' position
self.h_01_x = \
self.p[0][0]
self.h_01_y = \
self.p[0][1] + (self.h[0]/2)
self.h_02_x = \
self.p[1][0] + self.w[1]
self.h_02_y = \
self.p[1][1] + (self.h[1]/2)
with self.canvas:
Line(bezier=(
self.h_01_x, self.h_01_y,
self.h_01_x - 20, self.h_01_y,
self.h_02_x + 20, self.h_02_y,
self.h_02_x, self.h_02_y,
), width=2)
print self
def hookupfull(self, *args):
self.gethooks()
self.hookfunc()
def update(self, *args):
global debug_1
if startenable == True:
mww= MainWindowWidget()
print mww
mww.hookupfull()
else: # if startenable is false
pass
class Test2App(App):
def build(self):
Clock.schedule_interval(MainWindowWidget.update, \
5.0/60.0)
return MainWindowWidget()
if __name__ == '__main__':
Test2App().run()
kv file:
#:kivy 1.0.9
<MainWindowWidget>
NewButton:
text: 'add'
pos: 100, 0
on_release: root.addfunction()
NewButton:
text: 'start'
pos: 200, 0
on_release: root.startfunc()
NewButton:
text: 'hook up full'
pos: 400, 0
on_release: root.hookupfull()
<NewButton@Button>:
font_size: 15
size_hint: None, None
size: 100, 100
<Scatterer>:
do_rotation: False
size_hint: None, None
size: self.size
<Drawer>:
size: self.size
canvas:
Color:
rgba: 0, 1, 0, 0.3
Rectangle:
pos: self.pos
size: self.size
What I found out was, when I clicked the button that does hookupfull()
, which print self
, they always return the same thing such as <__main__.MainWindowWidget object at 0x7f110fcef530>
no matter how many times hookupfull()
is called.
However when the same function is scheduled, self
always returns different widgets.
Some other questions I'm wondering about:
Is there a way to assign id's or references to dynamically created widgets? For example, in my code, pressing the first button will create a new
Scatter
object. Is there a way to point to that specificScatter
object?How do I refer to widget grandchildren? For example, in my code, I have a
FloatLayout
object set up as a child of aScatter
object, which is a child of theMainWindowWidget
. TheFloatLayout
object changes in size due to theScatter
, which acts like a controller (and to my knowledge, doesn't actually change in size). I would like to access the properties such aspos
andwidth
of theFloatLayout
.arguments for the method/function declarations such as
(self, *args)
- what do they do?