如果可能 kivy/python,如何将小部件添加到列表?
How to add widgets to a list if it's possible in kivy/python?
所以我想做的是将一堆小部件添加到列表中,然后能够在 canvas 上绘制每个小部件。我正在考虑使用循环(例如,for widget in widgets: )然后调用它们的绘制函数。我希望每个小部件都是它自己的实体,因为它们不相互依赖(如果我选择删除一个小部件,其他小部件也不会被删除)。到目前为止,我有最低限度的代码(它只画了 1 个黄点):
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.graphics import Color, Ellipse, Line
class YellowDot(Widget):
def draw(self):
with self.canvas:
Color(1,1,0)
Ellipse(pos=(500, 500), size=(50,50))
class TestApp(App):
def build(self):
game=YellowDot()
game.draw()
return game
if __name__ == '__main__':
TestApp().run()
我知道这在对象的常规 python 中是可能的,因为您可以将对象添加到列表并调用它们各自的函数。是否可以在列表或类似的东西中添加小部件?
有两种方法,选择哪种取决于您是否希望小部件能够被垃圾收集(从内存中释放出来):
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.weakproxy import WeakProxy
from kivy.uix.boxlayout import BoxLayout
from kivy.graphics import Color, Ellipse, Line
from random import randint as r
class Dot(Widget):
def __init__(self, dot_color=None, **kwargs):
super(Dot, self).__init__(**kwargs)
if not dot_color:
raise Exception('No color available!')
self.dot_color = dot_color
# call draw automatically
self.draw()
def draw(self):
with self.canvas:
Color(*self.dot_color)
Ellipse(pos=self.pos, size=self.size)
class TestApp(App):
def build(self):
colors = ((1, 0, 0),
(0, 1, 0),
(0, 0, 1))
do_weak_referencing = False # change to True for weakrefs
if do_weak_referencing:
# get the class for weak referencing
# variant 1
wp = WeakProxy
self.dots = [
WeakProxy(
Dot(dot_color=dc,
pos=(r(100, 500), r(100, 500)))
) for dc in colors]
else:
# variant 2
self.dots = [
Dot(dot_color=dc,
pos=(r(100, 500), r(100, 500))
) for dc in colors]
box = BoxLayout()
for dot in self.dots:
# where will our dot be?
print(dot.pos)
box.add_widget(dot)
# what the list look like?
print(self.dots)
return box
if __name__ == '__main__':
TestApp().run()
请注意,如果对象作为 WeakProxy
在列表中并且没有添加到任何地方(作为子项),它将被收集,如果您稍后尝试访问它,它会引发一个错误,它不可用(显然)- 变体 1.
但是,如果您选择直接获取强引用,则该对象将不会被收集,除非从 self.dots
列表中弹出。
我直接把self.draw()
放在__init__
里,这样你就可以看到点在哪里,但是你可以把它去掉,直接从App.dots
调用它,例如:
app = App.get_running_app()
app.dots[0].draw()
# tada!
所以我想做的是将一堆小部件添加到列表中,然后能够在 canvas 上绘制每个小部件。我正在考虑使用循环(例如,for widget in widgets: )然后调用它们的绘制函数。我希望每个小部件都是它自己的实体,因为它们不相互依赖(如果我选择删除一个小部件,其他小部件也不会被删除)。到目前为止,我有最低限度的代码(它只画了 1 个黄点):
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.graphics import Color, Ellipse, Line
class YellowDot(Widget):
def draw(self):
with self.canvas:
Color(1,1,0)
Ellipse(pos=(500, 500), size=(50,50))
class TestApp(App):
def build(self):
game=YellowDot()
game.draw()
return game
if __name__ == '__main__':
TestApp().run()
我知道这在对象的常规 python 中是可能的,因为您可以将对象添加到列表并调用它们各自的函数。是否可以在列表或类似的东西中添加小部件?
有两种方法,选择哪种取决于您是否希望小部件能够被垃圾收集(从内存中释放出来):
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.weakproxy import WeakProxy
from kivy.uix.boxlayout import BoxLayout
from kivy.graphics import Color, Ellipse, Line
from random import randint as r
class Dot(Widget):
def __init__(self, dot_color=None, **kwargs):
super(Dot, self).__init__(**kwargs)
if not dot_color:
raise Exception('No color available!')
self.dot_color = dot_color
# call draw automatically
self.draw()
def draw(self):
with self.canvas:
Color(*self.dot_color)
Ellipse(pos=self.pos, size=self.size)
class TestApp(App):
def build(self):
colors = ((1, 0, 0),
(0, 1, 0),
(0, 0, 1))
do_weak_referencing = False # change to True for weakrefs
if do_weak_referencing:
# get the class for weak referencing
# variant 1
wp = WeakProxy
self.dots = [
WeakProxy(
Dot(dot_color=dc,
pos=(r(100, 500), r(100, 500)))
) for dc in colors]
else:
# variant 2
self.dots = [
Dot(dot_color=dc,
pos=(r(100, 500), r(100, 500))
) for dc in colors]
box = BoxLayout()
for dot in self.dots:
# where will our dot be?
print(dot.pos)
box.add_widget(dot)
# what the list look like?
print(self.dots)
return box
if __name__ == '__main__':
TestApp().run()
请注意,如果对象作为 WeakProxy
在列表中并且没有添加到任何地方(作为子项),它将被收集,如果您稍后尝试访问它,它会引发一个错误,它不可用(显然)- 变体 1.
但是,如果您选择直接获取强引用,则该对象将不会被收集,除非从 self.dots
列表中弹出。
我直接把self.draw()
放在__init__
里,这样你就可以看到点在哪里,但是你可以把它去掉,直接从App.dots
调用它,例如:
app = App.get_running_app()
app.dots[0].draw()
# tada!