在Kivy中嵌套小部件 [英] Nesting widgets in kivy

查看:101
本文介绍了在Kivy中嵌套小部件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试用kivy制作一个界面,我认为关于自定义小部件以及如何对它们进行分层的一些基本知识,即使在学习了本教程之后,我也不了解.我认为我有更多的盒式html思维方式,所以小部件在本机GUI中嵌套的方式对我来说仍然很陌生.

I'm trying to make an interface in kivy and I think there are some fundamental things I don't understand about custom widgets and how to hierarchy them, even after going through the tutorial. I think I have more of a box-model html mindset, so the way widgets are nested in native GUIs are still kind of foreign to me.

一些背景:

  1. 我咨询了此条目有关如何添加背景的信息(回答了一个问题:如何在布局中添加背景图像/颜色/视频/...",我相信我正在使用_update_rect方法进行复制.)

  1. I consulted this entry on how to add a background (It answers the question: "How to add a background image/color/video/... to a Layout", which I believe I was replicating with the _update_rect methods).

具有on_touch_down事件的那个.

K,我正在尝试让MyApp看起来像这样...

K, I'm trying to get MyApp to look like this...

据我了解,这是我需要做的事情:

As I understand it, here are the things I'd need for that:

  1. 您有一个应用.
  2. 该应用程序具有根目录.
  3. 根有背景,例如背景是白色.
  4. 背景包含一个持有人,说该持有人与背景之间有一点空白,并且是灰色的.我确实希望它是一个小部件,而不只是一个非小部件的画布,因为我也希望所有者对单击事件做出反应.单击时变为随机颜色. (只是为了证明它在做某事.)
  5. 持有人包含两个自定义窗口小部件.这些是带有标签的圆圈,每个圆圈都标记为绿色.单击时它们会变成随机的颜色(只是表明它们在做某事).

这是我的代码,它不再崩溃,但不显示任何颜色或任何种类的对象.

Here's my code, which doesn't crash anymore, but doesn't display any colors or objects of any kind.

#!/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()

关于我做错了什么以及如何正确嵌套这些小部件的任何指针?

Any pointers on what I'm doing wrong and how to nest these widgets correctly?

推荐答案

出现空白屏幕的原因是应用程序的build()方法不返回任何内容.它返回的内容都是根窗口小部件,但是即使您创建了一些窗口小部件,也不会返回任何一个,因此不会显示任何内容.

The reason you get a blank screen is that your app's build() method does not return anything. Whatever it returns would be the root widget, but even though you make some widgets you don't return one so nothing is displayed.

如果您解决了此问题,则可以再次运行该应用程序,但会立即收到类似MyApp has no attribute rect之类的错误.这是因为根窗口小部件会立即调整大小和位置以填充窗口,这会(根据您的root.bind行)触发MyApp._update_rect.但是,此方法尝试修改MyApp.rect.pos ...但该应用程序没有self.rect!您大概打算绑定到root._update_rect,而不是应用程序的方法. (我绑定到root._update_rect,现在至少出现了红色背景和绿色圆圈.)

If you fix this, you can run the app again but you'll immediately get an error something like MyApp has no attribute rect. This is because your root widget is immediately sized and positioned to fill the window, which (as per your root.bind line) triggers MyApp._update_rect. However, this method try to modify MyApp.rect.pos...but the app doesn't have a self.rect! You presumably intended to bind to root._update_rect, not the app's method. ( I bound to root._update_rect instead and now at least the red background and green circle do appear.)

另外,使用kv语言会容易得多,它可以自动处理很多小部件的创建,矩形绑定等.

And as a side note, this would be a lot easier using the kv language, which could automatically take care of a lot of the widget creation, rectangle binding etc.

我现在没有时间修复所有问题,但是也许这两个问题可以帮助您修复整个流程.如果没有其他人,我将在稍后尝试发布更完整的答案.

I don't have time to fix it all right now, but perhaps these two problems can help you fix the overall flow. I'll try to post a more complete answer later if nobody else has.

根据评论,这是更新的MyApp.

Here's an updated MyApp, as per the comments.

class MyApp(App):
    title = 'My App'
    def build(self):
        root = RootWidget()
        root.bind(
            size=root._update_rect,
            pos=root._update_rect)

这篇关于在Kivy中嵌套小部件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆