我正在尝试在kivy中创建一个界面,我认为有些基本的东西我不了解自定义小部件以及如何对它们进行分层,即使在完成教程之后也是如此。我认为我有更多的盒子模型html心态,所以窗口小部件嵌套在原生GUI中的方式对我来说仍然是一种陌生的。
一些背景知识:
我咨询this entry如何添加背景(它回答了问题:“如何将背景图像/颜色/视频/ ...添加到布局中”,我相信我是用_update_rect方法复制。)
This one有on_touch_down事件。
K,我正试图让MyApp看起来像这样......
据我了解,以下是我需要的东西:
这是我的代码,它不会再崩溃,但不会显示任何颜色或任何类型的对象。
#!/usr/bin/kivy
import kivy
kivy.require('1.7.2')
from random import random
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.floatlayout import FloatLayout
from kivy.graphics import Color, Ellipse, Rectangle
class MyApp(App):
title = 'My App'
def build(self):
root = RootWidget()
root.bind(
size=self._update_rect,
pos=self._update_rect)
def _update_rect(self, instance, value):
self.rect.pos = instance.pos
self.rect.size = instance.size
class RootWidget(FloatLayout):
def __init__(self, **kwargs):
super(RootWidget, self).__init__(**kwargs)
with self.canvas.before:
Color(1, 0, 0, 1) # This RED does not display.
self.rect = Rectangle(
size=self.size,
pos=self.pos,
text="some junk!") # This label does not display.
mybackground = Background()
self.add_widget(mybackground)
def _update_rect(self, instance, value):
self.rect.pos = instance.pos
self.rect.size = instance.size
class Background(Widget):
def __init__(self, **kwargs):
super(Background, self).__init__(**kwargs)
with self.canvas.before:
Color(1, 1, 1, 1) # This WHITE does not display
self.rect = Rectangle(
size=self.size,
pos=self.pos,
text="More stuff!") # This label does not display.
myholder = Holder()
self.add_widget(myholder)
def _update_rect(self, instance, value):
self.rect.pos = instance.pos
self.rect.size = instance.size
class Holder(Widget):
def __init__(self, **kwargs):
super(Holder, self).__init__(**kwargs)
with self.canvas.before:
Color(0.25, 0.25, 0.25, 1) # This GRAY does not display
self.rect = Rectangle(
size=self.size,
pos=self.pos,
text="More stuff!") # This does not display.
c1 = Circley(label="Label 1") # I see I'd need to do some size/pos math here to center
c2 = Circley(label="Label 2") # but since everything isn't working, I've tabled this.
self.add_widget(c1)
self.add_widget(c2)
def _update_rect(self, instance, value):
self.rect.pos = instance.pos
self.rect.size = instance.size
def on_touch_down(self, touch):
rcolor = Color(random(), random(), random(), 1)
with self.canvas:
self.color = rcolor
class Circley(Widget):
def __init__(self, label='label', **kwargs):
super(Circley, self).__init__(**kwargs)
with self.canvas.before:
Color(0, 1, 0, 1) # This GREEN does not display
self.circ = Ellipse(
size=self.size,
pos=self.pos,
text=label
)
def _update_circ(self, instance, value):
self.circ.pos = instance.pos
self.circ.size = instance.size
def on_touch_down(self, touch):
rcolor = Color(random(), random(), random(), 1)
with self.canvas:
self.color = rcolor
if __name__ == '__main__':
MyApp().run()
关于我做错了什么以及如何正确嵌套这些小部件的任何指示?
答案 0 :(得分:2)
您获得空白屏幕的原因是您的应用的build()
方法不会返回任何内容。无论它返回什么都是根小部件,但即使你制作了一些小部件,也不会返回一个小部件,因此不会显示任何内容。
如果你解决了这个问题,你可以再次运行该应用,但是你会立即收到MyApp has no attribute rect
之类的错误。这是因为您的根窗口小部件会立即调整大小并定位以填充窗口,该窗口(根据您的root.bind
行)触发MyApp._update_rect
。但是,此方法尝试修改MyApp.rect.pos ...但该应用程序没有self.rect!您可能打算绑定到root._update_rect
,而不是应用程序的方法。 (编辑:我绑定到root._update_rect
,现在至少出现红色背景和绿色圆圈。)
编辑:作为旁注,使用kv语言会更容易,这可以自动处理很多小部件创建,矩形绑定等。
我现在没时间修复它,但也许这两个问题可以帮助您修复整体流程。如果没有其他人的话,我会稍后发布一个更完整的答案。
根据评论,这是一个更新的MyApp。
class MyApp(App):
title = 'My App'
def build(self):
root = RootWidget()
root.bind(
size=root._update_rect,
pos=root._update_rect)
答案 1 :(得分:0)
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.widget import Widget
from kivy.graphics import Color, Rectangle, Ellipse
class MyApp(App):
title = 'My App'
def build(self):
root = RootWidget()
root.bind(
size=root._update_rect,
pos=root._update_rect)
return root
class RootWidget(FloatLayout):
def __init__(self, **kwargs):
super(RootWidget, self).__init__(**kwargs)
with self.canvas.before:
Color(1, 0, 0, 1) # This RED does not display.
self.rect = Rectangle(
size=self.size,
pos=self.pos,
text="some junk!") # This label does not display.
mybackground = Background()
self.add_widget(mybackground)
def _update_rect(self, instance, value):
self.rect.pos = instance.pos
self.rect.size = instance.size
class Background(Widget):
def __init__(self, **kwargs):
super(Background, self).__init__(**kwargs)
with self.canvas.before:
Color(1, 1, 1, 1) # This WHITE does not display
self.rect = Rectangle(
size=self.size,
pos=self.pos,
text="More stuff!") # This label does not display.
myholder = Holder()
self.add_widget(myholder)
def _update_rect(self, instance, value):
self.rect.pos = instance.pos
self.rect.size = instance.size
class Holder(Widget):
def __init__(self, **kwargs):
super(Holder, self).__init__(**kwargs)
with self.canvas.before:
Color(0.25, 0.25, 0.25, 1) # This GRAY does not display
self.rect = Rectangle(
size=self.size,
pos=self.pos,
text="More stuff!") # This does not display.
c1 = Circley(label="Label 1") # I see I'd need to do some size/pos math here to center
c2 = Circley(label="Label 2") # but since everything isn't working, I've tabled this.
self.add_widget(c1)
self.add_widget(c2)
def _update_rect(self, instance, value):
self.rect.pos = instance.pos
self.rect.size = instance.size
def on_touch_down(self, touch):
rcolor = Color(random(), random(), random(), 1)
with self.canvas:
self.color = rcolor
class Circley(Widget):
def __init__(self, label='label', **kwargs):
super(Circley, self).__init__(**kwargs)
with self.canvas.before:
Color(0, 1, 0, 1) # This GREEN does not display
self.circ = Ellipse(
size=self.size,
pos=self.pos,
text=label
)
def _update_circ(self, instance, value):
self.circ.pos = instance.pos
self.circ.size = instance.size
def on_touch_down(self, touch):
rcolor = Color(random(), random(), random(), 1)
with self.canvas:
self.color = rcolor
if __name__ == '__main__':
MyApp().run()