Для Kivy в Python я не могу получить цвет на макете холста, когда формирую несколько виджетов - PullRequest
0 голосов
/ 20 января 2020

Таким образом, я использовал 'для l oop', чтобы создать несколько прямоугольных angular виджетов (например, box) в строке, где я планирую поместить дополнительные элементы внутри. Я подумал, что было бы хорошо, чтобы эти виджеты были разнесены и имели цвет фона. Я в течение недели изучаю все (включая «связывание»), но у меня все еще нет результатов, которых я хочу. По сути, все виджеты (например, box) находятся в функции с именем def test(self): и вызывают ее в __init__ для создания строк виджетов. Я использую with self.canvas.before и self.rec = Rectangle(size=box.size, pos=box.pos) и def redraw(self,*args): технику ... но все, что я получаю, это маленькая коробка в левом нижнем углу.

Пожалуйста, посмотрите и скажите мне, что мне не хватает , Я упросту код:

from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.graphics.context_instructions import Color 
from kivy.graphics.vertex_instructions import Rectangle

class TestWindow(BoxLayout):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.test()
        self.redraw

    def test(self):
        for i in range(3):
            box = BoxLayout(size_hint=(None,None), size=(300,50), pos=self.pos)
            with box.canvas.before:
                Color(1,0,0,0.5)
                self.rec = Rectangle(size=box.size, pos=box.pos)
                self.bind(size=self.redraw,pos=self.redraw)

            bt = Button(text='world')
            box.add_widget(bt)
            self.ids.stack.add_widget(box)

    def redraw(self, *args):
        self.rec.size = self.rec.size
        self.rec.pos = self.rec.pos

class TestApp(App):
    def build(self):

        return TestWindow()

if __name__=='__main__':
    TestApp().run()```

```The kv file is:
<TestWindow>:
    StackLayout:
        id:stack
        padding:10
        spacing:10```

[the output...][1]


  [1]: https://i.stack.imgur.com/EyElC.jpg

Ответы [ 2 ]

0 голосов
/ 24 января 2020

Я не уверен, почему этот код работает сейчас, когда мои предыдущие попытки потерпели неудачу. Может быть, потому что я использовал словарь для своего boxlayout (так же, как то, что предложил Джон Андерсон). В любом случае, похоже, что теперь он работает отлично ... позже могут быть некоторые ошибки, которые я пропустил:

from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.graphics.context_instructions import Color
from kivy.graphics.vertex_instructions import Rectangle

class Test2Window(BoxLayout):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.test()

    def test(self):
        box = {}
        for i in range(5):
            box[i] = BoxLayout(size_hint=(None,None),size=(200,80),padding=5, spacing=5)
            box[i].bind(pos=self.redraw)

            bt = Button(text='Hello World')
            box[i].add_widget(bt)
            self.ids.stack.add_widget(box[i])

    def redraw(self,inst_box,*args):
        inst_box.canvas.before.clear()
        colr = Color(1,0,0,0.5)
        rec = Rectangle(size=inst_box.size, pos=inst_box.pos)

        inst_box.canvas.before.add(colr)
        inst_box.canvas.before.add(rec)

class Test2App(App):
    def build(self):

        return Test2Window()

if __name__=='__main__':
    Test2App().run()```

The KV file:
```<Test2Window>:
    StackLayout:
        id:stack
        padding:10
        spacing:10```
0 голосов
/ 23 января 2020

Есть две основные проблемы с вашим кодом. Первое, что я упомянул в своем предыдущем комментарии (атрибуты pos и size еще не установлены в методе __init__()). И второе: ваш redraw() метод на самом деле ничего не делает (установка переменной для ее собственного значения ничего не делает).

Итак, вот модифицированная версия вашего кода, которая использует Clock.schedule_once() для преодолеть первую проблему. И вторая проблема решается путем сохранения словаря Rectangles, набранного на соответствующем BoxLayout, и корректировки каждого Rectangle с использованием size и pos его BoxLayout:

from functools import partial
from kivy.app import App
from kivy.clock import Clock
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.graphics.context_instructions import Color
from kivy.graphics.vertex_instructions import Rectangle


class TestWindow(BoxLayout):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.recs = {}
        Clock.schedule_once(self.test)

    def test(self, *args):
        for i in range(3):
            box = BoxLayout(size_hint=(None,None), size=(300,50))
            with box.canvas.before:
                Color(1,0,0,0.5)
                self.recs[box] = Rectangle(size=box.size, pos=box.pos)
                redraw_box = partial(self.redraw, box)
                self.bind(size=redraw_box,pos=redraw_box)

            bt = Button(text='world')
            box.add_widget(bt)
            self.ids.stack.add_widget(box)
            Clock.schedule_once(partial(self.redraw, box, None))

    def redraw(self, box, window_size, *args):
        self.recs[box].size = box.size
        self.recs[box].pos = box.pos


class TestApp(App):
    def build(self):

        return TestWindow()

if __name__=='__main__':
    Builder.load_string('''
<TestWindow>:
    StackLayout:
        id:stack
        padding:10
        spacing:10
    ''')
    TestApp().run()
...