2016-05-07 10 views
1

Ich versuche, ein Programm in Python zu schreiben, das Teile eines Bildes nimmt und sie in Kivy rendert, mit einem GridLayout.AttributeError in Kivy: GridLayout-Objekt hat kein Attribut _trigger_layout

Unter Verwendung einer XML-Datei mit meinen Kartendaten lese ich jede Kachel von ihrer globalen ID (oder "GID", siehe here für eine Erklärung, wie es funktioniert und den Prozess, den mein Programm verwendet), indem ich das Quell-Tileset umwandle Bild in eine Textur und eine Region dieser Textur mit der .get_region() -Methode. Ich erstelle dann ein Bild-Widget mit diesem Teil der Textur, um in das GridLayout zu gelangen. Aber ich bekomme diesen Fehler:

Traceback (most recent call last): File "test_parse_xml.py", line 92, in Ground = Layer(root[1].attrib['name'], int(root[1].attrib['width']), int(root[1].attrib['height'])) File "test_parse_xml.py", line 85, in init self.add_widget(Image(current_texture)) #returns an error. What am I doing wrong?
File "/Applications/Kivy.app/Contents/Resources/kivy/kivy/uix/layout.py", line 85, in add_widget size=self._trigger_layout, AttributeError: 'Layer' object has no attribute '_trigger_layout'

Irgendwelche Ideen, wie ich das beheben kann? Der Punkt von Interesse ist die Zeile, die

self.add_widget(Image(current_texture)) 

Hier ist mein komplettes Programm.

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() 

Antwort

1

Sie benötigen, um Ihre Super-Konstruktor in Ihrem __init__ Methode

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 
+0

Dank nennen! Das hat den Fehler beseitigt, aber ich konnte das Image-Widget immer noch nicht zum Laufen bringen: Datei "kivy/_event.pyx", Zeile 438, in kivy._event.EventDispatcher.bind (kivy/_event.c: 6026) KeyError: 'size_hint') Also habe ich self.canvas.add (Rectangle (texture = current_texture)) und es zog ein weißes Feld in der unteren linken Ecke des Bildschirms ... Ich muss herausfinden, wie zu bekommen Dies ist die anzuzeigende Texturregion. – Bam8000

+0

Normalerweise verwende ich 'kivy.uix.image.Image', wenn ich ein Bild auf den Bildschirm setzen muss (aber ich mache auch keine Spiele) –