Добавить изображение динамически внутри gridlayout kivy python - PullRequest
0 голосов
/ 18 июня 2020

Я сделал простое касание пользователя, чтобы добавить изображение, используя add_widget в gridlayout. Я сделал простой прототип.

Я нажимаю определенную сетку, и изображение добавляется всегда последней сеткой.

но мне нужно добавить изображение к нажатой сетке.

Спасибо за любые предложения.

from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.uix.image import Image
from kivymd.uix.imagelist import SmartTileWithLabel
KV_CODE = '''
RecycleView:
    viewclass: 'RVItem'
    RecycleGridLayout:
        #orientation: 'vertical'
        cols:2
        size_hint_y: None
        height: self.minimum_height
        default_size_hint: 1, None
        default_size: 100,300
        spacing: 20
        padding: 10
'''
class RVItem(SmartTileWithLabel):
    def on_release(self):
        image=Image(source='2.jpg')
        self.add_widget(image,index=-1, canvas='before')

class SampleApp(MDApp):
    def build(self):
        return Builder.load_string(KV_CODE)
    def on_start(self):
        rv = self.root
        rv.data = ({'text': str(i), } for i in range(5))
SampleApp().run()

Ответы [ 2 ]

0 голосов
/ 20 июня 2020

Вот еще один способ сделать это, добавив MDCheckBox к RVItem:

from kivy.properties import BooleanProperty, StringProperty
from kivy.uix.relativelayout import RelativeLayout
from kivymd.app import MDApp
from kivy.lang import Builder

KV_CODE = '''
<RVItem>:
    MDCheckbox:
        id: cb
        active: root.added
        size_hint: None, None
        size: 50, 50
        pos: 0, root.height - self.height
    SmartTileWithLabel:
        size_hint: None, 1
        width: root.width - cb.width
        pos: cb.width, 0
        text: root.text
        source: root.source

RecycleView:
    viewclass: 'RVItem'
    RecycleGridLayout:
        #orientation: 'vertical'
        cols:2
        size_hint_y: None
        height: self.minimum_height
        default_size_hint: 1, None
        default_size: 100,300
        spacing: 20
        padding: 10
'''


class RVItem(RelativeLayout):
    added = BooleanProperty(False)
    text = StringProperty('')
    source = StringProperty('')

    def on_touch_up(self, touch):
        if touch.button == 'left' and self.collide_point(*touch.pos):
            # find this item in the data
            root = MDApp.get_running_app().root
            data = root.data
            for d in data:
                if d['text'] == self.text:
                    # found this item, change `added` to opposite
                    d['added'] = not d['added']
                    root.refresh_from_data()
                    break
            return True
        else:
            return super(RVItem, self).on_touch_up(touch)


class SampleApp(MDApp):

    def build(self):
        return Builder.load_string(KV_CODE)

    def on_start(self):
        rv = self.root
        rv.data = ({'text': str(i), 'source':'1.jpg', 'added':False } for i in range(5))


SampleApp().run()

Теперь RVItem - это RelativeLayout, который содержит MDCheckbox и SmartTileWithLabel. Поскольку RVItem - это viewclass, у него должны быть все свойства, которые появляются как ключи в данных, поэтому он имеет added, text и source. Эти свойства используются в KV_CODE для установки свойств MDCheckbox и SmartTileWithLabel.

0 голосов
/ 19 июня 2020

Проблема в том, что вы добавляете 2.jpg Image к viewclass из RecycleView. Функция RecycleView заключается в переработке экземпляров viewclass. Поэтому, если вы измените один из этих экземпляров, он может появиться в любом месте RecycleGridLayout и, вероятно, будет перемещаться без учета RVItem, к которому вы хотели применить эту модификацию.

Ответ следующий: что всякий раз, когда вы хотите изменить RVItem, вы должны сделать это, используя data из RecycleView. Вот модифицированная версия вашего кода, которая добавляет изображение к canvas из RVItem путем добавления ключа added к данным:

from kivy.properties import BooleanProperty
from kivymd.app import MDApp
from kivy.lang import Builder
from kivymd.uix.imagelist import SmartTileWithLabel

KV_CODE = '''
<RVItem>:
    canvas:
        # uncomment these lines to get a black background behind the checkbox
        # Color:
        #     rgba: 0,0,0,1
        # Rectangle:
        #     size: 32, 32
        #     pos: self.x, self.y + self.height - 32
        Color:
            rgba: 1,1,1,1
        Rectangle:
            size: 32, 32
            pos: self.x, self.y + self.height - 32
            source: 'atlas://data/images/defaulttheme/checkbox_on' if self.added else 'atlas://data/images/defaulttheme/checkbox_off'

RecycleView:
    viewclass: 'RVItem'
    RecycleGridLayout:
        #orientation: 'vertical'
        cols:2
        size_hint_y: None
        height: self.minimum_height
        default_size_hint: 1, None
        default_size: 100,300
        spacing: 20
        padding: 10
'''


class RVItem(SmartTileWithLabel):
    added = BooleanProperty(False)

    def on_release(self):
        # find this item in the data
        root = MDApp.get_running_app().root
        data = root.data
        for d in data:
            if d['text'] == self.text:
                # found this item, change `added` to opposite
                d['added'] = not d['added']
                root.refresh_from_data()
                break


class SampleApp(MDApp):

    def build(self):
        return Builder.load_string(KV_CODE)

    def on_start(self):
        rv = self.root
        rv.data = ({'text': str(i), 'source':'1.jpg', 'added':False } for i in range(5))


SampleApp().run()
...