Próbuję zrobić interfejs w Kivy i myślę, że istnieją pewne fundamentalne rzeczy, których nie rozumiem o niestandardowych widżetach i jak ich hierarchii, nawet po przechodzeniu przez samouczek. Myślę, że mam więcej modułu myślenia w pudełku HTML, więc widżety są zagnieżdżone w natiokiecie Guis są dla mnie wciąż zagraniczne.

Trochę tła:

  1. Konsultowałem się Ten wpis, jak dodać tło (odpowiada na pytanie: "Jak Aby dodać obraz / kolor / wideo / wideo / ... do układu ", co uważam, że replikuję metodami _update_rect).

  2. Ten ma zdarzenie On_Touch_down.

K, staram się zdobyć MyApp, żeby wyglądać tak ...

enter image description here

Jak to rozumiem, oto rzeczy, których potrzebuję do tego:

  1. Masz aplikację.
  2. Aplikacja ma korzeń.
  3. Korzeń ma tło, powiedz, że tło jest białe.
  4. Tło zawiera uchwyt, powiedz, że posiadacz ma mały margines z tła i jest szary. Chcę, żeby to był widżet, a nie tylko na płótnie nie widgetowe, ponieważ chcę, aby posiadacz reagował również na kliknięcie wydarzeń. Po kliknięciu zmienia losowe kolory. (Wystarczy pokazać, że coś robi.)
  5. Uchwyt zawiera dwa niestandardowe widżety. Są to kółka z etykietami, każdy kolorowy zieleń. Obracają losowe kolory po kliknięciu (po prostu pokazać, że robią coś).

Oto mój kod, który już nie uderza, ale nie wyświetla żadnych kolorów ani przedmiotów jakiegokolwiek rodzaju.

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

Jakieś wskazówki na temat tego, co robię źle i jak poprawnie zagnieżdżać te widżety?

4
Mittenchops 4 grudzień 2013, 08:21

2 odpowiedzi

Najlepsza odpowiedź

Powód, dla którego otrzymasz pusty ekran, jest to, że metoda aplikacji {X0}} nie zwraca niczego. Cokolwiek powraca będzie widżet korzeniowy, ale nawet jeśli pojawi się kilka widżetów, których nie zwracasz, więc nic nie jest wyświetlane.

Jeśli to naprawisz, możesz ponownie uruchomić aplikację, ale natychmiast zdobędziesz błąd czegoś takiego jak MyApp has no attribute rect. Dzieje się tak, ponieważ twój widget korzenia jest natychmiastowy i umieszczony, aby wypełnić okno, które (zgodnie z linią root.bind) wyzwalacze MyApp._update_rect. Jednak ta metoda próbuje zmodyfikować myApp.rect.Pos ... ale aplikacja nie ma self.rect! Przypuszczalnie zamierzasz wiązać się z root._update_rect, a nie metody aplikacji. (Edytuj: Zamiast tego zerwałem root._update_rect, a teraz przynajmniej czerwone tło i zielone koło.)

Edytuj: A jako notatka boczna byłaby to dużo łatwiejsze przy użyciu języka KV, który mógłby automatycznie zadbać o wiele tworzenia widżetów, powiązania prostokąta itp.

Nie mam czasu, aby to naprawić teraz, ale być może te dwa problemy mogą pomóc ci naprawić ogólny przepływ. Spróbuję opublikować więcej pełniejszej odpowiedzi później, jeśli nikt inny nie ma.


Oto zaktualizowany MyApp, zgodnie z komentarzami.

class MyApp(App):
    title = 'My App'
    def build(self):
        root = RootWidget()
        root.bind(
            size=root._update_rect,
            pos=root._update_rect)
2
inclement 4 grudzień 2013, 20:39
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()
0
ZenCODE 23 luty 2014, 00:24