AttributeError в Kivy: объект GridLayout не имеет атрибута _trigger_layout

Я пытаюсь написать программу на питоне, которая берет части изображения и отображает их в kivy с помощью GridLayout.

Используя файл XML с данными моей карты, я читаю каждую плитку по их глобальному идентификатору (или «GID», см. здесь для объяснения того, как это работает и процесса, который использует моя программа), преобразование исходное изображение набора тайлов в текстуру и получение области этой текстуры с помощью метода .get_region(). Затем я создаю виджет изображения с той частью текстуры, которая помещается в GridLayout. Но я получаю эту ошибку:

Трассировка (последний последний вызов): файл "test_parse_xml.py", строка 92, в Ground = Layer(root[1].attrib['name'], int(root[1].attrib['width']), int(root[1].attrib['height'])) Файл "test_parse_xml.py", строка 85, в init self.add_widget(Image(current_texture)) # возвращает ошибку. Что я делаю неправильно?
Файл "/Applications/Kivy.app/Contents/Resources/kivy/kivy/uix/layout.py", строка 85, в add_widget size=self._trigger_layout, AttributeError: объект "Слой" не имеет атрибута '_trigger_layout'

Любые идеи о том, как я могу это исправить? Интерес представляет строка, в которой говорится

self.add_widget(Image(current_texture))

Вот моя полная программа.

import xml.etree.ElementTree as ET
from kivy.uix.gridlayout import GridLayout
from kivy.graphics.texture import Texture
from kivy.core.image import Image
from kivy.core.window import Window

tree = ET.parse('test_tileset.tmx')
root = tree.getroot()


#import general elements from <map> tag
mapWidth = int(root.attrib['width'])
mapHeight = int(root.attrib['height'])
tileWidth = int(root.attrib['tilewidth'])
tileHeight = int(root.attrib['tileheight'])


class TileSet(object):
    """Stores data about tilesets to be accessed by tiles from that tileset"""

    def __init__(self, imagePath, imageWidth, imageHeight,    #creating instance attributes of the class,
                 tilesetFirstGid, tilesetTileWidth, tilesetTileHeight): #change values with each instance
        self.imagePath = imagePath
        self.imageWidth = imageWidth
        self.imageHeight = imageHeight
        self.tilesetFirstGid = tilesetFirstGid
        self.tilesetTileWidth = tilesetTileWidth
        self.tilesetTileHeight = tilesetTileHeight
        self.tilesetLastGid = (imageHeight//tilesetTileHeight)*(imageWidth//tilesetTileWidth)


#make a list of all the tilesets
tilesetList = []

#import data for each tileset from each <tileset> tag
Test = TileSet(root[0][0].attrib['source'], int(root[0][0].attrib['width']),
               int(root[0][0].attrib['height']), int(root[0].attrib['firstgid']),
               int(root[0].attrib['tilewidth']), int(root[0].attrib['tileheight'])
               )
tilesetList.append(Test)



def get_tileset(gid):
    """takes an integer, the gid. Returns an instance of the tileset that has that gid"""

    for i in tilesetList:
        if gid <= i.tilesetLastGid:
            return i



class Layer(GridLayout):
    """creates a grid of tiles based on information from a layer."""

    def __init__(self, name, width, height, **kwargs):
        self.name = str(name)
        self.width = width
        self.height = height

        #set the number of columns of the gridlayout
        self.cols = width

        #get the layer for ease of iteration below
        #using XPath to find all 'data' nodes that are children of nodes
        #with the name of the instance of the class
        self.layer = root.find(".//*[@name='"+self.name+"']/data")


        prevgid = 1
        current_texture = Image(Test.imagePath).texture
        current_texture = current_texture.get_region(0, 0, 32, 32)
        for gid in self.layer:
            gid = int(gid.attrib['gid'])
            if gid > 0:
                if gid != prevgid:
                    ts = get_tileset(gid)
                    current_texture = Image(ts.imagePath).texture
                    #getting a region of the texture based off the Global ID (GID)
                    current_texture = current_texture.get_region((ts.imageWidth//ts.tilesetTileWidth-1)*ts.tilesetTileWidth,
                                                                     (ts.imageHeight//ts.tilesetTileHeight-1)*ts.tilesetTileHeight,
                                                                     ts.tilesetTileWidth, ts.tilesetTileHeight)
                    prevgid = gid

                self.add_widget(Image(current_texture)) #returns an error. What am I doing wrong? 
                                                        #Is there a better way to add the texture to the GridLayout?
            else:
                self.add_widget() #something will go here once I figure out my main problem



Ground = Layer(root[1].attrib['name'], int(root[1].attrib['width']), int(root[1].attrib['height']))



if __name__ == '__main__':
    Ground().run()

person Bam8000    schedule 07.05.2016    source источник


Ответы (1)


вам нужно вызвать свой суперконструктор в вашем методе __init__

def __init__(self, name, width, height, **kwargs):
    GridLayout.__init__(self, cols=2, row_force_default=True, row_default_height=40, spacing=[0, 1],**kwargs)
    self.name = str(name)
    self.width = width
    self.height = height
person Joran Beasley    schedule 07.05.2016
comment
Спасибо! Это избавило от ошибки, но я все еще не мог заставить работать виджет изображения: Файл kivy/_event.pyx, строка 438, в kivy._event.EventDispatcher.bind (kivy/_event.c:6026) KeyError: ' size_hint') Поэтому я использовал self.canvas.add(Rectangle(texture=current_texture)) и нарисовал белую рамку в левом нижнем углу экрана... Мне нужно выяснить, как заставить отображать область текстуры . - person Bam8000; 07.05.2016
comment
я обычно использую kivy.uix.image.Image, когда мне нужно поместить изображение на экран (но я также не делаю игры) - person Joran Beasley; 07.05.2016