Design-Problem: Composite ohne friend



  • Okay. Dennoch danke für die vielen Anregungen in diesem Thread! Der Programmierer bedient die GUI ja nicht gleich wie der Anwender, das ist jetzt nur ein Spezialfall. Aber mit dem Subjektiven hast du wahrscheinlich Recht, dir würde mein Framework wohl nicht besonders gefallen. 😉

    Über das ursprüngliche Problem habe ich nochmals nachgedacht, und ich denke, ich werde es vorerst doch mit friend machen, um den Zugriff auf die zwei Klassen zu beschränken. Aber das kann sich auch wieder ändern. Auf jeden Fall werde ich mir die Indirektion über Forward-Funktionen für protected -Zugriff merken!



  • Ehm.. wtf? - Das war ein Link auf "Let me google that for you", wo ja ein Mausklick in dem Sinne gemacht wird, ohne dass es die Maus macht..
    Wahrscheinlich hat das Markus mal zensiert.. 😉


  • Administrator

    drakon schrieb:

    Ehm.. wtf? - Das war ein Link auf "Let me google that for you", wo ja ein Mausklick in dem Sinne gemacht wird, ohne dass es die Maus macht..
    Wahrscheinlich hat das Markus mal zensiert.. 😉

    Dir ist schon klar, dass da nicht wirklich der Button gedrückt wird, sondern du über Javascript und window.location weitergeleitet wirst. Der Query wird dann über die URL Google mitgeteilt. Ich verwende die gleiche Vorgehensweise, um zum Beispiel über die Adresszeile von Opera direkt mit IxQuick/MSDN/Bing/Wikipedia suchen zu können.

    Grüssli



  • Dravere schrieb:

    drakon schrieb:

    Ehm.. wtf? - Das war ein Link auf "Let me google that for you", wo ja ein Mausklick in dem Sinne gemacht wird, ohne dass es die Maus macht..
    Wahrscheinlich hat das Markus mal zensiert.. 😉

    Dir ist schon klar, dass da nicht wirklich der Button gedrückt wird, sondern du über Javascript und window.location weitergeleitet wirst. Der Query wird dann über die URL Google mitgeteilt. Ich verwende die gleiche Vorgehensweise, um zum Beispiel über die Adresszeile von Opera direkt mit IxQuick/MSDN/Bing/Wikipedia suchen zu können.

    Grüssli

    Jap. Ist mir schon klar. Aber ich habe dort eben in die Textzeile noch geschrieben, dass so ein Vorgehen bei einem In Game GUI praktisch wäre.

    Das ich in einem PC Spiel keine Animation mit bewegter Maus und Textfeld im vornherein erstelle sondern eben da einfach den Cursor im Code rumschiebe und dann den Klick ebenfalls im Code mache, ist denke ich klar. 😉


  • Administrator

    drakon schrieb:

    Das ich in einem PC Spiel keine Animation mit bewegter Maus und Textfeld im vornherein erstelle sondern eben da einfach den Cursor im Code rumschiebe und dann den Klick ebenfalls im Code mache, ist denke ich klar. 😉

    😮
    Ich hoffe, dass war nicht dein Ernst? 😉

    Grüssli



  • Dravere schrieb:

    😮
    Ich hoffe, dass war nicht dein Ernst? 😉

    Grüssli

    Ehm.. Doch? - Was ist denn nicht gut daran? - Bei z.B einem Game Tutorial oder so kann ein solches Verhalten durchaus nützlich sein und lässt sich dann ganz einfach umsetzen. (à la : "Wenn sie mit der Maus auf dieses Symbol klicken *klick*, dann erreichen sie das Menü so und so")


  • Administrator

    drakon schrieb:

    Ehm.. Doch? - Was ist denn nicht gut daran? - Bei z.B einem Game Tutorial oder so kann ein solches Verhalten durchaus nützlich sein und lässt sich dann ganz einfach umsetzen. (à la : "Wenn sie mit der Maus auf dieses Symbol klicken *klick*, dann erreichen sie das Menü so und so")

    Das habe ich schon mehrmals gesehen und jedesmal wurde eine zweite Maus animiert oder dann mit Blinken oder ähnlichem auf eine Schaltfläche aufmerksam gemacht. Du darfst doch nicht einfach die Kontrolle über die Maus des Benutzers übernehmen. Da schlägt am Ende gar noch ein Anti-Viren Programm alarm.
    Aber auch sonst ist das eine sehr schlechte Technik. Der Benutzer sollte selber über die Geschwindigkeit eines Tutorials entscheiden, also wann er weitergehen will. Wenn du einem Kunden ein Haus zeigst, dann bugsierst du ihn ja wohl auch nicht durch das Haus?
    Zudem was machst du mit den Mausbewegungen des Benutzers? Wenn er sich gegen deine erzwungenen Bewegungen der Maus "wehrt"?

    Ein solches Vorgehen wäre meiner Meinung nach völlig benutzerunfreudnlich.

    Grüssli



  • Dravere, deiner Ansicht nach wäre diese Funktion also äusserst böse? 😉

    Ich selbst würde auch nicht direkt die Benutzermaus bewegen. Aber eigentlich ging es ja ums Klicken.

    Wenn man einen Benutzerklick simulieren möchte, gehts natürlich auch ohne Click() . Nur läuft das darauf hinaus, dass man die assoziierten Funktionen selbst aufrufen muss und zudem noch dafür zu sorgen hat, dass die Klick-Animation korrekt abgespielt wird. All das könnte die Schaltfläche wunderbar selbst, aber ohne Click() zwingt man den Benutzer zum Nachbauen. Vor allem die Animation wird interessant, da müsste man wohl die Einzelbilder separat speichern und rechtzeitig zeichnen. Richtig lustig wirds, Änderungen konsistent zu halten. Das meinte ich eben mit unnötiger Komplexität.

    Wenn ein Feature auf der einen Seite sehr nützlich ist, aber bei unbedachter Benutzung zu schlechtem Design führen kann, würdest du es nur wegen letzterem verbieten? Ich sicher nicht, aber das ist wohl wirklich subjektiv. Um das konsequent durchzuziehen, dürfte man allerdings nicht mehr programmieren.


  • Administrator

    Nexus schrieb:

    Dravere, deiner Ansicht nach wäre diese Funktion also äusserst böse? 😉

    Nein. Damit kann man schon sinnvolles machen. Man könnte die Option anbieten (oder gleich die Einstellung vom System holen), dass der Cursor immer zur Standardschaltfläche springt. Das kannst du damit implementieren. Aber dann sollte man dem User die Wahl lassen. Ich schalte sowas zum Beispiel immer ab.

    Nexus schrieb:

    Ich selbst würde auch nicht direkt die Benutzermaus bewegen. Aber eigentlich ging es ja ums Klicken.

    Naja, aber du wirst ja auch nicht den Benutzer zu einem Klick zwingen? Den Besucher des Hauses gegen eine Tür drängen, damit er diese aufmacht ... ok, die Metapher ist jetzt nicht mehr so gut oder der Besucher ist von der Billag/GEZ 😃

    Nexus schrieb:

    ..., dass die Klick-Animation korrekt abgespielt wird.

    Wieso sollte die abgespielt werden, wenn der Benutzer nicht darauf klickt? Und wenn du wirklich sowas anbieten möchtest, dann würde ich das eher getrennt anbieten: PlayAnimation, PlayClickAnimation oder sowas. Wobei ich, wie gesagt, gar keinen Zweck dafür sehe. Falls das irgendjemand mal wünscht und tatsächlich einen sinnvollen Verwendungszweck zeigen kann, kann man es immer noch anbieten. Wie das grundsätzlich Laurent bei SFML macht, finde ich ein sehr gutes Vorgehen.

    Nexus schrieb:

    Wenn ein Feature auf der einen Seite sehr nützlich ist, aber bei unbedachter Benutzung zu schlechtem Design führen kann, würdest du es nur wegen letzterem verbieten?

    Nein, ich sehe nur den Nutzen von diesem Feature nicht. Für mich gibt es hier dieses "sehr nützlich" nicht. 😉

    Übrigens @drakon,
    Mir kam nochwas gestern Abend in den Sinn. Wenn du die Bewegungen für den Benutzer übernimmst, hat das noch einen negativen Effekt. Der Benutzer lernt nicht, wie man es macht, denn man lernt etwas nur, wenn man es selber macht 😉

    Grüssli



  • Jaja. Es war ein Beispiel, wo man es brauchen kann. Es kommt da wahrscheinlich nicht all zu oft vor, aber man kann es benutzen und es ist imo einiges einfacher, als wie nexus sagt alles andere von Hand zu machen.

    Aber wie wäre es z.B bei einer Aufzeichnung eines Spieles? Also wenn ich die Aufzeichnung ablaufen lasse, dann kann ich ganz gut einfach die Eingaben des Spielers tracken und dann nachproduzieren. Oder aber auch eine eigene machen für die Ansicht des Gegners. Klar kann man das anderst lösen, aber ich sehe den Sinn nicht alles nachzuprogrammieren, wenn man genau die Funktionen ja bereits hat.


  • Administrator

    @drakon,
    Du bestätigst meine Meinung mehr und mehr. Du würdest diese Funktionen genau für solchen Unsinn missbrauchen. Das Beispiel ist schlecht, sowas macht man einfach nicht. Also braucht man auch diese Möglichkeit nicht.
    Wenn du sowas sagst wie "Theoretisch könnte man es brauchen, ist vielleicht nicht so gut, aber immerhin hat man die Möglichkeit", dann machst du eben nichts anderes, als möglichst viele Features reinpacken, ohne zu überlegen, wie sinnvoll die eigentlich sind.

    drakon schrieb:

    Aber wie wäre es z.B bei einer Aufzeichnung eines Spieles? Also wenn ich die Aufzeichnung ablaufen lasse, dann kann ich ganz gut einfach die Eingaben des Spielers tracken und dann nachproduzieren. Oder aber auch eine eigene machen für die Ansicht des Gegners. Klar kann man das anderst lösen, aber ich sehe den Sinn nicht alles nachzuprogrammieren, wenn man genau die Funktionen ja bereits hat.

    1. Worauf war das nun bezogen? Du willst doch hoffentlich im Replay nicht die Maus des Benutzers benutzen?
    2. Oft löst man das tatsächlich anders und zwar deutlich einfacher: Video Aufzeichnung.
    Ich habe jedenfalls noch nie davon gehört, dass da jemand angefangen hat im Replay irgendwelche Klicks zu reproduzieren.

    Und es geht ja auch nicht darum, dass du dies nachprogrammieren sollst. Es geht darum, dass du es gar nicht brauchst. Oder es sind irgendwelche hoch speziellen Sonderfälle. Dann biete für diese Sonderfälle lieber eine explizite Schnittstelle an, welche für den Sonderfall gemacht ist. Aber nicht etwas allgemeines, was schnell zu unsauberen Code führt.

    Grüssli



  • Dravere schrieb:

    1. Worauf war das nun bezogen? Du willst doch hoffentlich im Replay nicht die Maus des Benutzers benutzen?
    2. Oft löst man das tatsächlich anders und zwar deutlich einfacher: Video Aufzeichnung.
    Ich habe jedenfalls noch nie davon gehört, dass da jemand angefangen hat im Replay irgendwelche Klicks zu reproduzieren.

    1. Nein. Einfach ein Cursor. Also die echte Maus muss ja nicht an dem Cursor attached sein..

    2. Nein. In Age of Empires 2 und vielen anderen Strategiespielen, die ich kenne läuft das so, dass man sogar auswählen kann, ob man eben den Spiele beobachtet und da sind die Bewegungen der Maus nicht unwichtig, oder ob man selbst rumscrollen kann. Da kann man dann auch die ganze Welt anschauen und in den Gebäuden nachsehen, was für Einheiten produziert werden usw. Das als Video zu machen ist nicht möglich.


  • Administrator

    drakon schrieb:

    2. Nein. In Age of Empires 2 und vielen anderen Strategiespielen, die ich kenne läuft das so, dass man sogar auswählen kann, ob man eben den Spiele beobachtet und da sind die Bewegungen der Maus nicht unwichtig, oder ob man selbst rumscrollen kann. Da kann man dann auch die ganze Welt anschauen und in den Gebäuden nachsehen, was für Einheiten produziert werden usw. Das als Video zu machen ist nicht möglich.

    Age Of Empires, schon lange nicht mehr gespielt. Aber war es da nicht so, dass man da beobachtet hat und nicht gesehen hat, wie der Benutzer auf die Gebäude geklickt hat? Somit wäre die Simulation eines Button-Clicks immer noch nicht nötig 😉
    Und abgesehen davon, würde ich sowas ganz anders lösen. Da würde ich eine Event-Aufzeichnung machen und beim Abspielen diese Events wieder auslösen. Da dadurch die Mausbewegung und der Klick als Event gespeichert werden, wird das im Hintergrund automatisch wieder ausgeführt.

    Somit würde ich das als ein Spezialfall anschauen und eben einen EventRecorder anbieten oder sowas. Bzw. man könnte dem User auch die Möglichkeit geben, den Events irgendwo zentral zu lauschen, bzw. auch die Quelle angeben. Also gäbe es die Möglichkeiten das System als Quelle abzukopplen und dafür dann die Aufzeichnung als Quelle angeben. Das meinte ich dann mit der expliziten Schnittstelle. 😉

    Grüssli



  • Dravere schrieb:

    Wieso sollte die abgespielt werden, wenn der Benutzer nicht darauf klickt?

    Weil der Klick realistisch aussehen soll, so à la: "Schau mal, was passiert, wenn du hier klickst". Sodass der Benutzer ohne Weiteres weiss, dass ein Klick durchgeführt wurde.

    Dravere schrieb:

    Und wenn du wirklich sowas anbieten möchtest, dann würde ich das eher getrennt anbieten: PlayAnimation, PlayClickAnimation oder sowas.

    Ja, eben. Eine kleinere Schnittstelle hast du dadurch nicht, eher musst du noch Spezialfunktionen, die man sonst nicht braucht, anbieten. Soviel zum Thema "Features genau abwägen".

    Dravere schrieb:

    Nein, ich sehe nur den Nutzen von diesem Feature nicht. Für mich gibt es hier dieses "sehr nützlich" nicht. 😉

    Ich habe es nun aber genügend oft erklärt. Auf das Hauptargument, dass du dir ohne Click() Workarounds basteln musst, bist du gar nie wirklich eingegangen. Wenn das nützlicher ist, okay.

    Dravere schrieb:

    Du würdest diese Funktionen genau für solchen Unsinn missbrauchen. Das Beispiel ist schlecht, sowas macht man einfach nicht. Also braucht man auch diese Möglichkeit nicht.

    Weil ein mögliches Beispiel schlecht ist, braucht man die Funktionalität nicht? Sogar mit Begründung könntest du diesen Schluss nicht ziehen.



  • Schau dir halt einfach andere Frameworks an.

    Die Aufrechterhaltung von Ordnung ist keine Zensur.


  • Administrator

    Nexus schrieb:

    Weil der Klick realistisch aussehen soll, so à la: "Schau mal, was passiert, wenn du hier klickst". Sodass der Benutzer ohne Weiteres weiss, dass ein Klick durchgeführt wurde.

    Aber es fehlt mir immer noch ein: wozu?
    Als wenn jemand nicht wüsste, wie ein Klick auf einen Button aussieht. Wenn schon musst du die Aufmerksamkeit zum Button lenken und diesen klar blinken oder strahlen lassen. Ich sehe keinen Sinn, wieso man diese Klickanimation überhaupt ohne Klick durch den Benutzer auslösen können muss.

    Nexus schrieb:

    Ja, eben. Eine kleinere Schnittstelle hast du dadurch nicht, eher musst du noch Spezialfunktionen, die man sonst nicht braucht, anbieten. Soviel zum Thema "Features genau abwägen".

    Du hast eine saubere und besser getrennte Schnittstelle. Wobei ich allerdings trotzdem keine solche Funktion anbieten würde. Es ging mir dabei nur um das "wenn überhaupt". Wenn zum Beispiel dann nur jemand die Animation ausführen möchte, wäre dies bei deiner Lösung unglaublich umständlich 😉
    Allerdings sehe ich, wie schon gesagt, gar keinen Grund, wieso dies jemand tun möchte.

    Nexus schrieb:

    Ich habe es nun aber genügend oft erklärt. Auf das Hauptargument, dass du dir ohne Click() Workarounds basteln musst, bist du gar nie wirklich eingegangen. Wenn das nützlicher ist, okay.

    Und wie oft soll ich es noch sagen, dass ich gar keinen Grund für sowas sehe? Ich sehe nicht mal ein, wieso jemand einen Workaround bauen sollte. Wieso sollte er diese Schnittstelle überhaupt brauchen? Wieso? Wozu?

    Nexus schrieb:

    Weil ein mögliches Beispiel schlecht ist, braucht man die Funktionalität nicht? Sogar mit Begründung könntest du diesen Schluss nicht ziehen.

    Der Satzbau war ein wenig schlecht gewählt. So extrem war das nicht gemeint. Aber bisher habt ihr meiner Meinung nach kein sinnvolles Beispiel genannt, wieso man diese Möglichkeit überhaupt brauchen würde. Das ist ja schliesslich auch mein Problem hier. Ich sehe keine sinnvolle Anwendung für die Ausführung eines Klicks über die Button-Schnittstelle.

    Zusammengefasst:
    Wozu? Wieso? Warum? Wofür? Wann? Wo? Wie? usw. 🤡
    Ich möchte doch eigentlich nur sinnvolle Praxisbeispiele hören. Bringt ein Beispiel als Widerspruchsbeweis meiner Aussage. Um es mal mit den Mitteln der Logik zu sagen 🙂
    Oder wir lassen es einfach bleiben und einigen uns darauf, dass wir uns nicht einigen können 😃

    @€ schrieb:

    Schau dir halt einfach andere Frameworks an.

    Wer ist damit gemeint?
    Wie auch immer, ist eigentlich egal wer gemeint ist, die Argumentation ist trotzdem unsinnig. Nur weil andere es anbieten und machen, heisst es nicht, dass es auch gut ist.

    Grüssli



  • Gut, dann möchte ich das angesprochene Beispiel verdeutlichen.

    Nehmen wir an, ich habe ein Abenteuerspiel, bei dem man einzelne Gegenstände kaufen und verkaufen kann. Zudem kann man alles aufs Mal verkaufen. Es gibt die Gegenstände Schwert, Schild und Rüstung, man kann alles entweder haben oder nicht. Die Oberfläche könnte so aussehen:

    Schwert       Schild        Rüstung
    +-----------+ +-----------+ +-----------+
    |  Kaufen   | |  Kaufen   | |  Kaufen   |
    +-----------+ +-----------+ +-----------+
    +-----------+ +-----------+ +-----------+ +---------------+
    | Verkaufen | | Verkaufen | | Verkaufen | |Alles verkaufen|
    +-----------+ +-----------+ +-----------+ +---------------+
    

    Nun habe ich ein Schwert und möchte es loswerden. Mit dem Verkauf kann ich mehrere Aktionen verknüpfen:

    Button BuySword("Kaufen");
    Button SellSword("Verkaufen");
    
    // Da man kein Schwert mehr verkaufen kann, Button deaktivieren
    SellSword.AddClickListener(tr1::bind(&Button::SetActive, &SellSword, false));
    
    // Es wird wieder möglich, ein Schwert zu kaufen; diesen Button aktivieren
    SellSword.AddClickListener(tr1::bind(&Button::SetActive, &BuySword, true));
    
    // Geld erhalten
    SellSword.AddClickListener(tr1::bind(&Player::EarnMoney, &MyPlayer, 254));
    
    // Schwert aus dem Inventar entfernen
    SellSword.AddClickListener(tr1::bind(&Player::RemoveItem, &MyPlayer, Inventory::Sword));
    
    // Meldung anzeigen
    SellSword.AddClickListener(tr1::bind(&ShowMessage, "Schwert verkauft!"));
    

    Okay. Nun gibt es ja noch die Schaltfläche "Alles verkaufen", wodurch Schwert, Schild und Rüstung verkauft werden. Hier ist eben Click() praktisch, weil man einfach die Aktionen der anderen drei "Verkaufen"-Buttons aufrufen kann:

    Button SellEverything("Alles verkaufen");
    
    SellEverything.AddClickListener(tr1::bind(&Button::Click, &SellSword));
    SellEverything.AddClickListener(tr1::bind(&Button::Click, &SellShield));
    SellEverything.AddClickListener(tr1::bind(&Button::Click, &SellArmor));
    

    Und schon hat man die Funktionalität!

    Ich glaube, du nimmst "Click" etwas zu wörtlich. Eigentlich geht es mir vor allem ums Aufrufen der Listener. Du kannst du die Funktion ja auch "CallListeners" oder ähnlich nennen. Mit "AddClickListener" bin ich übrigens auch nicht 100% zufrieden, aber die Aufgabe sollte klar sein. Ich denke, das Standardverhalten bei Click() ist sinnvoll ohne Animation, man könnte aber einen entsprechenden Parameter einrichten.

    Wenn du kein Click() hast, sehe ich folgende Möglichkeiten:

    • Alle Funktionen, die den einzelnen Gegenständen zugeordnet sind, einzeln zuweisen. Schlecht wegen Codeduplizierung und leicht möglichen Inkonsistenzen bei der Wartung.
    • Gesamte Aktionen auf den Verkauf der einzelnen Gegenstände in jeweils eine Funktion auslagern, sodass schliesslich drei Funktionen vorhanden sind. Schlecht, weil man die Möglichkeit, mehrere Funktionen zu registrieren, nicht ausnutzt und std::tr1::bind() ebenfalls nicht. Ausserdem werden die Funktionen recht gross mit entsprechend vielen Parametern und müssen sich um GUI und Logik kümmern.
    • Vor dem Aufruf von AddClickListener() für die einzelnen Gegenstände den entsprechenden Funktor zusätzlich an einem anderen Ort speichern. So braucht man zwar keinen Zugriff mehr auf die einzelnen Buttons, dupliziert aber unnötigerweise Information und nimmt die damit verbundenen Probleme in Kauf.
    • Auf Observer-Pattern ganz verzichten und in prozedurale Muster zurückfallen ("ask, don't tell").

    Alle vier Möglichkeiten sind für mich Rückschritte und machen den Code komplexer.



  • Nexus schrieb:

    Gut, dann möchte ich das angesprochene Beispiel verdeutlichen.

    ne ne ne, ganz schlecht.
    Was wenn du zB einn click sound auf einen Button hast?
    Ne, du willst bei BuyAll einen anderen Sound als 3 mal kaufen haben 😉

    Wofür man die click() Methoden braucht ist für Agenten. zB wenn ich einen funktionstest implementiere, dann geh ich durch die fenster und simuliere user eingaben. und dann muss ich einen click simulieren und das geht entweder darüber dass ich die maus auf dem element positionieren und dem system ein click sende, oder aber ich rufe direkt click auf, was viel praktischer ist.

    solche agenten braucht man aber nur selten, und functional testing ist jetzt spontan das einzige was mir dazu einfällt...

    schaden tun die methoden aber nicht. aber bitte bitte bitte nie programmlogik über das view laufen lassen. Das view ist nur ein interface für den user, keins für den programmierer...



  • Shade Of Mine schrieb:

    aber bitte bitte bitte nie programmlogik über das view laufen lassen. Das view ist nur ein interface für den user, keins für den programmierer...

    Aber wie gesagt kommen mir alle Alternativen noch schlimmer vor. Wie würdest du denn sowas sauber implementieren?



  • Nexus schrieb:

    Shade Of Mine schrieb:

    aber bitte bitte bitte nie programmlogik über das view laufen lassen. Das view ist nur ein interface für den user, keins für den programmierer...

    Aber wie gesagt kommen mir alle Alternativen noch schlimmer vor. Wie würdest du denn sowas sauber implementieren?

    Jeder Button ruft eine Methode vom Controller auf.

    BuySwordButton ruft BuySword() auf. bzw. bekommt das callback eben bei der erstellung.

    Die Idee ist ja, dass du den Button einfach wegnehmen kannst und durch was anderes ersetzen kannst: zB könntest du scripting des spiels erlauben und dann will man keine clicks auf die buttons sondern direkt ins system rein.

    jedenfalls hast du ja trigger auf den buttons. es passiert ja etwas wenn du ihn clickst. es kommt ein sound, es kommt eine animation etc. deshalb ist ein click auf buyAll eben nicht das selbe wie ein click auf alle buttons einzeln.

    je nachdem wie das view aussieht, ruft der buyAll button wirklich nur direkt den controller auf, oder aber das view kennt die einzelnen callbacks und ruft sie bei buyAll selber alle auf.

    es hängt halt wirklich von der struktur ab die du hast. und ja, manchmal muss man ein bisschen code verdoppeln. das view und der controller/model sind eben getrennte einheiten.

    PS:
    den functor bei addClickListener musst du ja nicht extra speichern, du machst zB:

    buySwordButton.addListener(buySword);
    buyAllButton.addListener(buySword);

    und fertig.


Anmelden zum Antworten