Seite 1 von 1
Instanz aus Variable verwenden
Verfasst: Sonntag 27. Januar 2019, 00:31
von TenchiMuyo1984
Hallo zusammen,
ich habe ein Problem und weiß keine Lösung :/
Code: Alles auswählen
schilddarstellungen = [
['101-10', 'Gefahrstelle', 'TRUE', 'Zeichen Hundert.ttf', [['drawblack', '1'], ['drawred', '2'], ['drawblack', 'A']]],
['102', 'Kreuzung oder Einmündung', 'TRUE', 'Zeichen Hundert.ttf', [['drawblack', '1'], ['drawred', '2'], ['drawblack', 'B']]],
['103-10', 'Kurve – links', 'TRUE', 'Zeichen Hundert.ttf', [['drawblack', '1'], ['drawred', '2'], ['drawblack', 'D']]]
]
def draw_sign(direction, pos_x, pos_y, size):
epd = epd4in2b.EPD()
epd.init()
i = 2
Blackimage = Image.new('1', (epd4in2b.EPD_HEIGHT, epd4in2b.EPD_WIDTH), 255) # 126*298
Redimage = Image.new('1', (epd4in2b.EPD_HEIGHT, epd4in2b.EPD_WIDTH), 255) # 126*298
drawblack = ImageDraw.Draw(Blackimage)
drawred = ImageDraw.Draw(Redimage )
schilddarstellungen[i][4][0][0].text((pos_x, pos_y), str(schilddarstellungen[i][4][0][1]), font = fontzeichen, fill = 0)
Ich möchte die Instanz "drawblack" bzw. "drawred" dynamisch aus meinem Array verwenden, sodass hinterher sowas interpretiert wird:
Code: Alles auswählen
drawblack.text((pos_x, pos_y), '1', font = fontzeichen, fill = 0)
Mein Ziel ist es, eine Schleife um diese Zeile zu bringen, die alle Elemente von
[4] in die Instanz "drawblack" und "drawred" übergibt.
Jedoch bekomme ich immer diese Exception:
Code: Alles auswählen
AttributeError: \'str\' object has no attribute \'text\
Ich hoffe ihr könnt mir helfen, oder einen alternativen Lösungsansatz bereitstellen.
Grüße
TenchiMuyo1984
Re: Instanz aus Variable verwenden
Verfasst: Sonntag 27. Januar 2019, 01:04
von __blackjack__
@TenchiMuyo1984: Binde die Bilder nicht an Namen sondern lege sie in einem Wörterbuch ab, mit den Namen als Zeichenketten. Dann kannst Du sie aus diesem Wörterbuch leicht mit der Zeichenkette aus der (unübersichtlichen) Datenstruktur auslesen.
`schilddarstellungen` ist wirklich ziemlich unübersichtlich und so eine Indexorgie wie ``schilddarstellungen[ i ][4][0][0]`` ist schwer verständlich weil man sich magische Indexzahlen merken muss.
Der `str()`-Aufruf in der Zeile macht keinen Sinn da `schilddarstellungen` doch ausschliesslich Zeichenketten enthält.
Ich würde die Datenstruktur so gestalten das man an ihr ablesen kann was die Elemente bedeuten. Also beispielsweise mehr Wörterbücher mit sinnvoll benannten Schlüsseln, oder Datentypen die mit `collections.namedtuple()` erstellt wurden.
Namensschreibweise für alles ausser Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase) ist in Python klein_mit_unterstrichen.
Re: Instanz aus Variable verwenden
Verfasst: Sonntag 27. Januar 2019, 11:02
von TenchiMuyo1984
Hallo __blackjack__
Ob ich das über diese "unübersichtliche" Art gestalte oder nicht, ist erstmal zweitrangig.
Ich bin Arrays von C und Java gewöhnt und hatte auch schon Überlegungen Richtung eines dictionaries angestellt. Jedoch wurde dieses durch meinen Anwendungsfall deutlich unübersichtlicher, weswegen ich zurück zu Arrays gegangen bin.
Hätte dann in etwa so ausgesehen:
Code: Alles auswählen
schilddarstellungen = {
'Schildtyp': 'Gefahrstelle',
'Schildcode': '101-10',
'Darstellbarkeit': 'TRUE',
'Schriftart': 'Zeichen Hundert.ttf',
'Zeichencodes': {
'Zeichen_1': {
'Farbcode': 'drawblack',
'Zeichencode': '1'
},
'Zeichen_2': {
'Farbcode': 'drawred',
'Zeichencode': '2'
},
'Zeichen_3': {
'Farbcode': 'drawblack',
'Zeichencode': 'A'
}
}
}
So mit arrays:
Code: Alles auswählen
['101-10', 'Gefahrstelle', 'TRUE', 'Zeichen Hundert.ttf', [['drawblack', '1'], ['drawred', '2'], ['drawblack', 'A']]],
Aber das ist auch nicht meine Frage gewesen.
Wie kann ich eben eine Variable als Instanz inpterpretieren?
Grüße
Edit:
Habe ein paar '' im Code vergessen.
TenchiMuyo1984
Re: Instanz aus Variable verwenden
Verfasst: Sonntag 27. Januar 2019, 11:29
von __deets__
Die Entscheidung welche Datenstruktur man wählt ist kein entweder oder. Wenn Zeichencodes durchnummerierte Schlüssel haben, dann ist das ein Zeichen dafür, dass DIE eine Liste sein sollten.
Und bezüglich deines Problems: alles in Python ist ein Objekt. So wie in Java (fast) auch alle sein Objekt ist. Ob du darauf nun per Namen oder per Index oder per Schlüssel zugreifst ist vollkommen unerheblich.
Code: Alles auswählen
drawred = ...
drawblack = ...
images = [drawred, drawblack]
images[0].text(...)
other_images = { “red”: drawred, “black”: drawblack }
other_images[“black”].text(....)
Re: Instanz aus Variable verwenden
Verfasst: Sonntag 27. Januar 2019, 11:50
von TenchiMuyo1984
Ich habe nun mal ein Schild in ein dictonary gepackt und kann die Inhalte auch aufrufen.
Jedoch bekomme ich immer noch die gleiche Exception:
Code: Alles auswählen
schilddarstellungen2[\'Zeichencodes\'][\'Zeichen_1\'][\'Farbcode\'].text((pos_x, pos_y), schilddarstellungen2[\'Zeichencodes\'][\'Zeichen_1\'][\'Zeichencode\'], font = fontzeichen, fill = 0)
AttributeError: \'str\' object has no attribute \'text\'
Code: Alles auswählen
schilddarstellungen2 = {
'Schildtyp': 'Gefahrstelle',
'Schildcode': '101-10',
'Darstellbarkeit': 'TRUE',
'Schriftart': 'Zeichen Hundert.ttf',
'Zeichencodes': {
'Zeichen_1': {
'Farbcode': 'drawblack',
'Zeichencode': '1'
},
'Zeichen_2': {
'Farbcode': 'drawred',
'Zeichencode': '2'
},
'Zeichen_3': {
'Farbcode': 'drawblack',
'Zeichencode': 'A'
}
}
}
def draw_sign(direction, pos_x, pos_y, size):
epd = epd4in2b.EPD()
epd.init()
i = 5
Blackimage = Image.new('1', (epd4in2b.EPD_HEIGHT, epd4in2b.EPD_WIDTH), 255) # 126*298
Redimage = Image.new('1', (epd4in2b.EPD_HEIGHT, epd4in2b.EPD_WIDTH), 255) # 126*298
drawblack = ImageDraw.Draw(Blackimage)
drawred = ImageDraw.Draw(Redimage )
fontzeichen = ImageFont.truetype('Zeichen Hundert.ttf', size)
print schilddarstellungen2['Schildtyp']
# gibt mir: 'Gefahrstelle'
print schilddarstellungen2['Zeichencodes']['Zeichen_1']['Farbcode']
# gibt mir: 'drawblack'
schilddarstellungen2['Zeichencodes']['Zeichen_1']['Farbcode'].text((pos_x, pos_y), schilddarstellungen2['Zeichencodes']['Zeichen_1']['Zeichencode'], font = fontzeichen, fill = 0)
epd.display(epd.getbuffer(Blackimage), epd.getbuffer(Redimage))
epd.sleep()
Ich möchte die Instanz "drawblack" bzw. "drawred" durch einen String aus einer Variablen austauschen:
von:
Code: Alles auswählen
drawblack.text((pos_x, pos_y), schilddarstellungen2['Zeichencodes']['Zeichen_1']['Zeichencode'], font = fontzeichen, fill = 0)
zu:
Code: Alles auswählen
schilddarstellungen2['Zeichencodes']['Zeichen_1']['Farbcode'].text((pos_x, pos_y), schilddarstellungen2['Zeichencodes']['Zeichen_1']['Zeichencode'], font = fontzeichen, fill = 0)
Re: Instanz aus Variable verwenden
Verfasst: Sonntag 27. Januar 2019, 12:09
von __deets__
entweder schlägst du den Namen in einem Wörterbuch exakt so wie ich es hinschrieb nach BEVOR du text () aufrufst.
Oder du steckst halt die Instanzen gleich rein.
Re: Instanz aus Variable verwenden
Verfasst: Sonntag 27. Januar 2019, 12:43
von TenchiMuyo1984
Ahh, jetzt habe ich es verstanden.
Du hast das über die Variablen drawred und drawblack gemacht. Ich habe die als string versucht in instanzieren ....
Wenn ich diese nun zu variablen umbenenne (Hochkomma entferne) und das dictionary mit in die Funktion schmeiße klappt es.
Aber wie kann ich es schaffen, dass ich das dictionary nicht mit in der Funktion haben muss?
Oder du steckst halt die Instanzen gleich rein.
Ich bekomme so immer eine Exception (was mir auch klar ist)
Re: Instanz aus Variable verwenden
Verfasst: Sonntag 27. Januar 2019, 13:49
von Sirius3
Alles, was eine Funktion braucht, sollte sie über ihre Argumente bekommen. Die Funktion soll ja nicht nur ein Schild zeichnen können:
Code: Alles auswählen
schilddarstellungen2 = {
'Schildtyp': 'Gefahrstelle',
'Schildcode': '101-10',
'Darstellbarkeit': 'TRUE',
'Schriftart': 'Zeichen Hundert.ttf',
'Zeichencodes': [
{'farbe': 'black', 'zeichen': '1'},
{'farbe': 'red', 'zeichen': '2'},
{'farbe': 'black', 'zeichen': 'A'},
]
}
def draw_sign(sign, pos_x, pos_y, size):
epd = epd4in2b.EPD()
epd.init()
image_black = Image.new('1', (epd4in2b.EPD_HEIGHT, epd4in2b.EPD_WIDTH), 255) # 126*298
image_red = Image.new('1', (epd4in2b.EPD_HEIGHT, epd4in2b.EPD_WIDTH), 255) # 126*298
draw = {
'black': ImageDraw.Draw(image_black),
'red': ImageDraw.Draw(image_red),
}
fontzeichen = ImageFont.truetype(sign['Schriftart'], size)
for code in sign['Zeichencodes']:
draw[code['farbe']].text((pos_x, pos_y),
code['zeichen'], font=fontzeichen, fill=0)
epd.display(epd.getbuffer(image_black), epd.getbuffer(image_red))
epd.sleep()
Re: Instanz aus Variable verwenden
Verfasst: Montag 28. Januar 2019, 10:18
von __blackjack__
Ich persönlich verwende bei so etwas dann auch noch gerne das externe `addict.Dict` um den Code dann mit Attributzugriffen schreiben zu können:
Code: Alles auswählen
fontzeichen = ImageFont.truetype(sign.Schriftart, size)
for code in sign.Zeichencodes:
draw[code.farbe].text(
(pos_x, pos_y), code.zeichen, font=fontzeichen, fill=0
)