Wie rufe ich eine Funktion eines geklickten Rechtecks auf?

Fragen zu Tkinter.
Antworten
sw42x
User
Beiträge: 8
Registriert: Samstag 19. August 2017, 13:43
Wohnort: Österreich

Hallo miteinander,
ich versuche beim klick auf ein Rechteck eine "Markier-Funktion" aufzurufen. Das Click-Event funktioniert schon gut, aber wie rufe ich die Funktion "markieren" in der Klasse E_E auf?

Code: Alles auswählen

[code]from tkinter import *

class E_E(object):

    def __init__(self, X0, Y0, R):
        # attribute eines ende-elements E_E
        self.__F0 = Farbe0_E_E      # originalfarbe
        self.__F1 = Farbe1_E_E      # farbe wenn markiert
        self.__markiert = False     # element ist nicht markiert

    def markieren(self):
        # beim markieren die farbe ändern
        if self.__markiert == False: 
            self.itemconfig(self, fill=self.__F1, outline=self.__F1)
            self.__markiert = True 
        else:
            self.itemconfig(self, fill=self.__F0, outline=self.__F0)
            self.__markiert = False  

# klick-event für elemente am board einstellen.
def onclick(event):
    # klick-event auf dem board definieren. 
    Element = board.find_closest(event.x, event.y)
    print(Element)
    farbe = board.itemcget(Element, 'fill')
    print(farbe)
    # Element.markieren()
[/code]

Kurze Erklärung des Events "onclick":
beim Mausklick ins Fenster wird des Element gefunden, und ich kanns auch printen.
Auch das Setzen der Variable "farbe" funktioniert prächtig,
ABER wie rufe ich jetzt "markieren" in der Klasse "E_E" auf?

danke.
__deets__
User
Beiträge: 14480
Registriert: Mittwoch 14. Oktober 2015, 14:29

Deine Namenskonventionen sind auesserst ungewoehnlich, schau dir mal PEP8 an wie man in Python Dinge benennt. Sternchenimporte (from tkinter import *) sind auch boese(tm), da sie dir unbekannte Namen in den Modulnamensraum goebeln, und man nicht mehr weiss, was woher kommt.

Um deine eigentliche Frage zu beantworten reicht der Ausschnitt nicht aus, den du da zeigst. Du hast ja gar keine Instanz von E_E erzeugt. Es gibt desweiteren eine Reihe von Namen, die nicht bekannt sind, zB das Farbe0_*-Zeug. Last but not least rufst du "self.itemconfig" auf, aber auch das gibt es ja nicht.
sw42x
User
Beiträge: 8
Registriert: Samstag 19. August 2017, 13:43
Wohnort: Österreich

ja, ich wollte das code-snippet so kurz wie möglich halten, um das "allgemeine" Geschwätz kurz zu halten.

1.) Variablen sind alle definiert und für meine eigentliche Frage nicht relevant.
2.) hier der Code für die Erstellung der Instanz.

Code: Alles auswählen

# window-fenster erstellen.    
root = Tk()
root.geometry("1500x800+10+10")
root.wm_title(Titel + " " + Version)

# 2d-zeichenbereich erstellen, platzieren im window, klick-event dazu-binden. 
board = Canvas(root, width=1500, height=800)
board.pack()
board.bind('<Button-1>', onclick)

# erstes ende-element in den zeichenbereich stellen.
XN = X0
YN = Y0
RN = 0
E_E1 = E_E(XN,YN, RN)
E_E1.zeichne(board)

mainloop()


danke.
__deets__
User
Beiträge: 14480
Registriert: Mittwoch 14. Oktober 2015, 14:29

Um solchen Missverstaendnissen vorzubeugen ist es besser, lauffaehige Minimalbeispiele zu erstellen. Damit kann dann erstens der geneigte Leser hier rumspielen, und oft loesen sich die Probleme auch von selbst.

Die Methode E_E.itemconfig etc ist trotzdem nicht definiert, ausser du hast auch die Klassendefinition gekuerzt. Mit dem ganzen Stueckwerk ist da nicht so viel anzufangen.

So oder so kannst du nicht erwarten, dass Canvas seine Items vom Typ deiner Klasse anlegt. Der kennt halt seine eigenen Items, und das war's. Aber die bekommen eine ID, und die musst du dir merken. Sowohl in deiner E_E-Instanz, aber auch an einer Stelle, an der du den canvas handhabst. Dort bildest du dann eine Zuordnung von ID zu E_E-Exemplar, und aus der kannst du dann die Instanz ermitteln & darauf etwas aufrufen.
sw42x
User
Beiträge: 8
Registriert: Samstag 19. August 2017, 13:43
Wohnort: Österreich

Alles klar.... das hat mir weitergeholfen .... :-)

der code schaut jetzt so aus, und funktioniert schon fast !

Code: Alles auswählen

[Codebox=python file=Unbenannt.py]

from tkinter import *

class E_E(object):

    def __init__(self, X0, Y0, R):
        # attribute eines ende-elements E_E
        self.__X0 = X0              # top-left-ecke x-koordinate
        self.__Y0 = Y0              # top-left-ecke y-koordinate
        self.__markiert = False     # element ist nicht markiert
        self.__T = "E_E"            # typ des objekts, E_E

    def markieren(self, canvas):
        # beim markieren die farbe ändern
        print("markieren.")
        if self.__markiert == False: 
            canvas.itemconfig(self, fill="red", outline="red")
            self.__markiert = True 
        else:
            canvas.itemconfig(self, fill="orange", outline="orange")
            self.__markiert = False  

    def zeichne(self, canvas):
        # zeichne ein ende-elements E_E (=quadtrat) bei X,Y (links-oben) mit der kante E_E_K0 im Massatb M_div
        X1 = self.__X0 / M_div
        Y1 = self.__Y0 / M_div
        X2 = (self.__X0 + E_E_K0) / M_div
        Y2 = (self.__Y0 + E_E_K0) / M_div
        canvas.create_rectangle(X1,Y1,X2,Y2, fill=self.__F0, outline=self.__F0)

# klick-event für elemente am board einstellen.
def onclick(event):
    # klick-event auf dem board definieren. 
    Elem = board.find_closest(event.x, event.y)
    # board.itemconfig(Elem, fill="red", outline="red")
    Elemente[int(Elem[0])-1].markieren(board) 
  
.-.-.-.-.-.-.-.-.-


# erstes ende-element in den zeichenbereich stellen.
XN = X0
YN = Y0
RN = 0
E_E1 = E_E(XN, YN, RN)      # element erstellen und element-werte einstellen.
E_E1.zeichne(board)         # element aufs board zeichnen.
Elemente.append(E_E1)       # element in liste merken. 

AnzElem = AnzElem + 1       # anzahl der elemente am board einstellen.

mainloop()

[/Codebox]


Gespeichert habe ich das erstelle Element in der Liste "Elemente".
Problem:
es wird jetzt schon das richtige Element aufgerufen, aber das "itemconfig" im "markieren" ändert die farbe nicht ??? :-(

Bitte um Hilfean Euch. Danke.
__deets__
User
Beiträge: 14480
Registriert: Mittwoch 14. Oktober 2015, 14:29

Eine Liste ist ziemlich sicher die falsche Datenstruktur. Eine Abbildung von Schluesseln (ID) auf Wert (Instanz E_E) macht man durch ein Woerterbuch/Dict. Und canvas.itemconfig braucht eben auch genau diese ID, *NICHT* deine selbstgebastelte Instanz vom Typ E_E. Darum habe ich geschrieben, dass du dir die ID beim anlegen deines Rechtecks merken musst.
Sirius3
User
Beiträge: 17703
Registriert: Sonntag 21. Oktober 2012, 17:20

@sw42x: in Python gibt es gewisse Konventionen, wie z.B. Variablennamen aussehen. Das soll das Lesen von fremden Code erleichtern, weil alle gleich schreiben, wobei "fremde" auch der Code ist, denn Du vor zwei Monaten geschrieben hast. Dazu zählt, dass Variablennamen aussagekräftig sein sollten, E_E ist das nicht. Alle Variablen werden klein geschrieben. Die doppelten Unterstriche bei Deinen Attributen gehören weg (zumindest einer davon), die Existenz von self.__T erschließt sich mir nicht. Wenn Du den Typ eines Objekts wissen willst, gibt es die type-Funktion.
Antworten