Seite 1 von 1

Canvas beerben analog zu Java JComponent???

Verfasst: Donnerstag 4. März 2021, 22:01
von fffg
Hallo, wenn ich in Java z. B. eine Klasse Rechteck schreiben möchte, ist es ja Standard, JComponent zu beerben und die paint-Methode zu überschreiben.
Ist ein analoges Vorgehen in Python mit tkinter auch möglich? Canvas scheint man ja nicht zu beerben, soweit meine Recherche richtig ist...

Re: Canvas beerben analog zu Java JComponent???

Verfasst: Donnerstag 4. März 2021, 22:56
von __blackjack__
@fffg: Du kannst von `Canvas` erben wenn das für den einsatzzweck Sinn macht. Aber eine `paint()`-Methode macht keinen Sinn weil das `Canvas` schon selbst macht, das Neuzeichnen wenn es nötig ist. `Canvas` ist auch Vektorgrafik und keine Pixelgrafik.

Re: Canvas beerben analog zu Java JComponent???

Verfasst: Samstag 6. März 2021, 20:57
von fffg
Vielen Dank!
1. Was wäre denn ein Kontext, in dem erben vin canvas sinnvoll wäre?
2. Gibt es andere grafikmodule, mut denen das eingangs beschriebene Vorgehen sinnvoll wäre?

Re: Canvas beerben analog zu Java JComponent???

Verfasst: Sonntag 7. März 2021, 00:29
von __blackjack__
@fffg: Ad 1. Wenn man irgendetwas mit einem `Canvas` implementieren möchte bei dem man den um Methoden erweitert. Das kann alles mögliche sein.

Ad 2. Was willst Du denn eigentlich machen? Python ist nicht Java und keines der GUI-Rahmenwerke ist Swing. Also ausser natürlich wenn Du Jython nimmst und da von JComponent ableitest natürlich. 😜

Die Frage klingt nach ich habe eine Lösung und suche ein Problem. Oder in diesem Fall nach ich habe eine Lösung und suche ein GUI-Rahmenwerk mit dem die auch funktioniert. Normalerweise hat man ja ein Problem und ein GUI-Rahmenwerk und sucht dann eine Lösung.

Re: Canvas beerben analog zu Java JComponent???

Verfasst: Montag 5. April 2021, 07:53
von fffg
Naja,
wie mache ich es denn z. B. wenn ich eine geometrische Figur zeichnen will, die ich zur Laufzeit modifizieren will?
In Java beerbe ich JComponent und überschreibe die Paint-Methode. Dort kann ich festlegen, wie das Ding prinzipiell aussehen soll.
Dann kann ich von einer anderen Klasse (später) aus auf das referezierte Kreisobjekt zugreifen und mit den vorhandenen Methoden von JComponent zB die Position verändern.
Wie mache ich so etwas in tkinter?

Re: Canvas beerben analog zu Java JComponent???

Verfasst: Montag 5. April 2021, 08:49
von Sirius3
Bei tkinter brauchst du keine Vererbung. Du zeichnest in ein Canvas die geometrischen Objekte und kannst sie auch nachträglich über ihre ID verändern.

Re: Canvas beerben analog zu Java JComponent???

Verfasst: Montag 5. April 2021, 10:41
von fffg
Kann ich dann nicht - wie im obigen Beispiel - den Code in z. B. eine Klasse Rechteck auslagern und dann in der "Hauptklasse" nur sowas schreiben wie rechteck.PositionSetzen...?
In Java könnte ich ja zB separate Klassen für Rechteck, Kreis, Dreieck, ... erstellen und dann in der Hauptklasse Objekte erzeugen und verwalten und diese dann modifizieren.
Muss ich das in Python (tkinter) alles in derselben Klasse machen?
Objektorientiert "schöner" wären doch die eigenen Klassen..

Re: Canvas beerben analog zu Java JComponent???

Verfasst: Montag 5. April 2021, 11:05
von __blackjack__
@fffg: Du kannst machen was Du willst. Und natürlich auch die ID und das Canvas-Objekt in Objekten kapseln die geometrische Formen repräsentieren. Dafür muss man nicht von `Canvas` ableiten. `rechteck.setze_position(…)` kannst Du in einer Methode in einer von `Canvas` abgeleiteten Klasse aufrufen, oder in irgendeiner anderen Methode oder Funktion. Kommt halt darauf an wie *Du* das gestalten möchtest. Was wiederum ein bisschen von den Anforderungen abhängt.

Re: Canvas beerben analog zu Java JComponent???

Verfasst: Montag 5. April 2021, 12:40
von fffg
vielen Dank aber ich komme leider immer noch nicht zurecht.
Ziel: Eine Spielfläche entwickeln, auf der ich zwei Bälle (Kreise) erstellen und dann positionieren kann (mit tkinter)

Ich habe hier einen Versuch gemacht, der aber Quatsch ist, weil ich wohl beide Bälle in ein Canvas packen muss (damit sie sich auch überlappen können)
also muss ich das canvas wohl in Spiel erstellen.
Außerdem ist es auch Quatsch, von Canvas zu erben, weil ja nicht Canvas eine PositionSetzen Methode hat sondern das Oval.

Code: Alles auswählen

from tkinter import *

class Ball(Canvas):
    
    def __init__(self, master, x, y, r):
        super().__init__(master, width = 2*r, height = 2*r)
        
        self.create_oval(x-r, y-r, x+r, y+r, width=1)
        


class Spiel:
    def __init__(self):
        master = Tk()

        ball1 = Ball(master, 50, 50, 50)
        ball2 = Ball(master, 25, 25, 25)
        #...
        ball1.pack()
        ball2.pack()
        mainloop()


k = Spiel()
ich müsste es so hinbekommen, dass ich beim Erstellen eines Kreisobjekts eine id zurückbekommen, so wie ich sie beim Aufruf von create_oval zurückbekomme.
das ginge über Methoden in der Klasse Spiel, wie aber mit eigenen Klassen?

Re: Canvas beerben analog zu Java JComponent???

Verfasst: Montag 5. April 2021, 14:42
von Sirius3
Man benutzt keine *-Importe weil man damit verschleiert, woher welcher Name stammt. __init__ ist dazu da, ein Objekt zu initialisieren, nicht das es ewig läuft. Das mainloop gehört da nicht rein
Und warum willst du unbedingt etwas vererben?

Re: Canvas beerben analog zu Java JComponent???

Verfasst: Montag 5. April 2021, 18:02
von __blackjack__
@Sirius3: Javaprogrammierer wollen immer was vererben, und alles in Klassen stopfen. Da können die aber nichts für, die sind so sozialisiert worden. 😉

@fffg: Dein Ball muss Zugriff auf das `Canvas`-Objekt haben und die ID die beim erstellen des Kreises zurückgegeben wird. Also etwas in dieser Richtung:

Code: Alles auswählen

#!/usr/bin/env python3
import tkinter as tk


class Ball:
    def __init__(self, canvas, x, y, radius):
        self.canvas = canvas
        self.item_id = self.canvas.create_oval(
            x - radius, y - radius, x + radius, y + radius, width=1
        )


def main():
    root = tk.Tk()
    canvas = tk.Canvas(root)
    canvas.pack()

    ball_a = Ball(canvas, 50, 50, 50)
    ball_b = Ball(canvas, 25, 25, 25)
    ...

    root.mainloop()


if __name__ == "__main__":
    main()

Re: Canvas beerben analog zu Java JComponent???

Verfasst: Montag 5. April 2021, 21:48
von fffg
ok, danke, aber wie greife ich dann auf den jeweiligen Ball zu?
Statt in der Main-Methode hätte ich ja z. b. die Bälle in einer Klasse Spiel erstellt, die vllt. eine Methode
positioniereAlleBälleZufällig hat.
Ich hätte angenommen, dass ich dafür dann die item_id brauche.
Aber wie soll ich das machen? Ich könnte zwar als öffentliches Attribut darauf zugreifen, aber das ist doch nicht sinnvoll?
Außerdem klappt es bei mir selbst dann nicht, ich kann keine Methoden aufrufen.

Re: Canvas beerben analog zu Java JComponent???

Verfasst: Dienstag 6. April 2021, 05:16
von Sirius3
Ob du jetzt das was in main steht wieder in einer Klasse Spiel packst, ist doch nebensächlich, __blackjack__ hast die Klasse nur weggelassen, weil sie für das Beispiel keinen Mehrwert bietet.
Und niemand hindert dich daran, der Klasse Ball auch noch eine Methode `positioniere` zu geben.

Re: Canvas beerben analog zu Java JComponent???

Verfasst: Dienstag 6. April 2021, 08:43
von fffg
Dem Ball kann ich eine solche Methode schon geben, aber genau mein Ziel ist es doch, vorhandene Methoden nutzen zu können und nicht alles nochmal implementieren zu können.
Daher wollte ich das ja ursprünglich analog zu Java machen, wo ich JComponent beerbe und meine Klasse Ball dann automatisch alle Methodne wie Positionieren() und setColor und was weiß ich alles hat.

Re: Canvas beerben analog zu Java JComponent???

Verfasst: Dienstag 6. April 2021, 09:04
von Sirius3
Diese Methoden gibt es halt bei tkinter nicht direkt, von daher macht es Sinn, solche Methoden zu definieren.

Re: Canvas beerben analog zu Java JComponent???

Verfasst: Dienstag 6. April 2021, 11:12
von fffg
ok, dann muss man das wirklich grundlegend anders strukturieren.
Oder bietet ein anderes GUI-Modul hier mehr Analogie?