python - 在 kivy 中嵌套小部件

标签 python user-interface widget kivy

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

一些背景:

  1. 我咨询了this entry关于如何添加背景(它回答了问题:“如何将背景图像/颜色/视频/...添加到布局”,我相信我正在使用 _update_rect 方法进行复制)。

    <
  2. This one有一个 on_touch_down 事件。

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

enter image description here

据我了解,这是我需要的东西:

  1. 你有一个应用程序。
  2. 该应用程序有根。
  3. 根有背景,比如说背景是白色的。
  4. 背景包含一个持有人,假设持有人与背景有一点边距并且是灰色的。我确实希望它成为一个小部件而不仅仅是一个非小部件 Canvas ,因为我希望持有者也对点击事件使用react。单击时它会变成随机颜色。 (只是为了表明它正在做某事。)
  5. 持有人包含两个自定义小部件。这些是带有标签的圆圈,每个都是绿色的。单击时它们会变成随机颜色(只是为了表明它们正在做某事)。

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

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

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

最佳答案

出现空白屏幕的原因是您应用的 build() 方法未返回任何内容。无论它返回什么,都将是根小部件,但即使您制作了一些小部件,您也不会返回一个小部件,因此不会显示任何内容。

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

编辑:附带说明一下,使用 kv 语言会容易得多,它可以自动处理很多小部件创建、矩形绑定(bind)等。

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


这是根据评论更新的 MyApp。

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

关于python - 在 kivy 中嵌套小部件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20366779/

相关文章:

Python 和 lxml.html get_element_by_id 输出问题

python WatchedFileHandler 旋转后仍在写入旧文件

jquery - 在网页中快速加载图像

java - 能否从片段类内部调用PlaceAutocompleteFragment(覆盖模式)

qt - 隐藏的QWidget对象接收信号

python |喀拉斯 |多变量预测

python - 计算其中一个引用的三个项目的最快方法(使用 python)?

java - Eclipse Windowbuilder 缺少设计

delphi - DUnit GUI 测试 : Can I force 'Application' to a different "form"?

java - Android 闪光灯小部件代码崩溃