Herzlich willkommen zur neunten Vorlesung von SE2. Vorab erst mal,
wir haben momentan von Betreuerseite in den Übungen ein etwas besorgniserregenden Eindruck.
Offensichtlich investiert ihr nicht genügend Zeit. Ich spreche immer die Falschen an.
Also meistens sind die, die in der Vorlesung sind,
nicht diejenigen, die irgendwie zu wenig tun.
Deswegen trifft es euch eigentlich jetzt hier fälschlicherweise,
aber ich muss es ja irgendwo mal zentral ansagen.
Offensichtlich wird zu wenig Zeit investiert in die Übung
Das merken wir einfach,
weil wir den Übungsbetrieb genauso machen wie im letzten Jahr,
aber in diesem Jahr ihr deutlich weniger fertig bekommen habt,
in der Zeit, als wir uns das gedacht haben.
Also Blatt 6 ist irgendwie auf breiter Fläche nicht zu Ende implementiert.
Das ist erstaunlich, das ist ganz erstaunlich.
Habt ihr irgendeine Idee, woran es liegen könnte,
ist in diesem Semester irgendwas anders in eurer Umgebung? Hat sich irgendwas,
ist immer speziell, das könnt ihr natürlich schlecht einschätzen,
weil ihr ja nicht den Vergleich zum Vorjahr habt,
ist richtig, ja.
Hm, ja,
ich bin Feuerwehr
7. Sehr schöne Frage. Ich wiederhole die Frage.
Sind die Betreuer vielleicht pingbiger geworden? Ich würde sagen,
das verneine ich jetzt erst mal,
weil das mit den Betreuern ja relativ wenig zu tun hat.
Vielleicht sind sie nicht pinglig genug,
um euch so ein bisschen auf die Finger zu gucken.
Wer ist noch ein Vorschlag? Das ist der
erste Teil, den ich dir gestern gezeigt habe.
Hat er beide mit uns gesprochen, hat mich fest moderiert.
Das ist ein Städteinfizierter. Das ist der andererseits,
um die Information zu zeigen. Weitere Glauben. Auch,
was für gute Freunde es halt arbeiten
Okay, also was er sagt, ist,
dass die anderthalb Stunden für das,
was wir da verlangen, möglicherweise zu wenig Zeit sind,
um das vollständig mit Tests zu machen und allem drum und dran.
Das mag ja sein. Wir haben ja auch nicht erwartet,
dass dann an dem Termin alles fertig ist.
Was wir natürlich erwarten, ist, dass wenn wir dann sagen,
zum nächsten Mal machen wir zu Anfang die Abnahme von Platz sechs,
wenn nämlich eigentlich Platz sieben dran ist.
Und dann kommen Leute und haben irgendwie das noch nicht fertig.
Weil dann war ja nun klar, dass man das jetzt
zu Hause fertig machen soll. Naja, okay,
also wie auch immer, Platz sieben ist Sagen wir etwas anders gestrickt.
Von daher sehe ich da jetzt die Hoffnung,
dass wir das auch wieder aufholen können.
Ja, da ist noch eine Meinung. Aus meiner Sicht,
was zum Beispiel hier vor dir sorgt, immer noch erwähnt an sich.
Wieder auf einmal, das ganze Schwert im Griff,
die erste passiert, was nach dem, zumindest meine ganze Gruppe,
das Forschen gemacht hat, in meiner Professionalität betroffen hat,
erwartet hat, oder ich war nach dem Zeitraum ein großes Team.
Da habe ich schon mich auch aus dem Weg zu gemeinsam.
Okay, das ist eine weitere wichtige Aussage, dass die Vorlesung,
in der ich hier diese Entwurfsregeln vorgestellt habe, Etwas spät kam.
Für einige, die haben dann schon ihren Entwurf gemacht und
hatten sozusagen nicht die Vorlesung dazugehört.
Das ist ein Aspekt, ja. Du warst jetzt genau
im Service reinkommen. Ich weiß, dass alle in die Suppe bei uns,
glaube ich, haben dann alles ins Werkzeug drangeschrien gemacht.
Kann man sonst mit einem Material, was der natürlich anfangen konnte,
und es eigentlich gesagt haben, ja,
es ist halt so, aber warum auch immer.
Ja, also was in einen Service reinkommt,
ich wiederhole das nochmal, was in einen Service reinkommt,
war vielen nicht klar, haben vieles in die Materialklassen gebaut.
Das ist, man muss immer unterscheiden zwischen dem Entwurf und dem Bauen,
ja, also das in der Woche mit dem Entwurf haben wir auch nicht erwartet,
dass das da irgendwie wahnsinnig super wird.
Dafür ist es ja genau die Entwurfswoche
Im Gegenteil ist es sogar ganz gut, wenn ihr das Gefühl habt,
oh Mensch, ich mache einen Entwurf und glaube,
dass ich das eigentlich ganz gut im Griff habe.
Und dann eine Woche später muss ich es implementieren und
dann ist da doch noch einiges offen.
Das ist ja auch das, was wir erreichen wollen.
Nur wie gesagt, im Vergleich zum Vorjahr fällt das sehr auf,
dass extrem viel weniger mit Blatt 6 jetzt fertig sind.
Na gut, schauen wir mal, wie das weitergeht.
Ich bin eigentlich noch guten Mutes. Dann hattet ihr
ja letzte Woche eine kleine Überraschung hier.
Guido Gritzan hat vorgetragen. Das war bestimmt ganz unterhaltsam.
Ich habe das einmal ganz kurz reingeschaltet. Da dachte ich,
oh Mensch, jetzt muss ich mich mal wieder aufregen,
weil das Mikro ist anscheinend ausgefallen.
Hinterher habe ich dann gesehen, dass er es mit Absicht
ausgemacht hat
Um irgendeinen Witz zu erzählen, von dem ich bis heute nicht weiß,
welcher es ist. Das ist eigentlich eine ganz coole Idee,
wie man sozusagen das Kommen in die Vorlesung schmackhaft machen könnte.
Ich schalte zwischendurch mal das Mikro aus, tu so,
als wenn ich einen Witz erzähle. Und dann sitzen Leute
zu Hause oder gucken sie das Video an und sagen sich, oh
Mensch, wäre ich doch in die Vorlesung gegangen.
Ich finde das ganz cool. Also es ist ein sehr schönes Element.
Wir werden sehen, ob wir das aufgreifen können.
Gut. Heute geht es um die Programmierung von grafischen Benutzungsoberflächen
. Also jetzt geht es tatsächlich mal um etwas,
was so richtig handfest ist, wo man richtig was sehen kann,
was da rauskommt
Nicht einfach nur irgendwelche Entwurfsregeln, die sagen, ah,
der Quelltext sollte so und so strukturiert sein.
Das ist zwar auch wichtig, aber jetzt könnt ihr mal
richtig zeigen, dass da auch wirklich was rauskommt.
Wir werden das ein bisschen in drei Abschnitten machen.
Zum einen werde ich etwas über Guy-Komponenten sagen, wie sie denn
in einer Oberfläche existieren können, was es für welche gibt.
Dann wollen wir ja, das ist ganz wichtig,
dass euer Anwendungscode auf Ereignisse in der Oberfläche reagieren kann.
Zweiter Schritt. Und dritter Schritt dann, wie kann man
das Layout steuern? Also wie kann man dafür sorgen,
dass wenn man das Fenster größer oder kleiner zieht,
dass da nichts Übles passiert?
Ich greife jetzt das auf, was ich vor zwei Wochen
erzählt habe. Da habe ich ja die Entwurfsregeln vorgestellt
Und hat dann unter anderem gesagt, naja,
wir wollen eigentlich unterscheiden zwischen Materialien, zwischen Fachwerten, Werkzeugen und Services.
Also irgendwie sollte man mehr oder weniger die meisten Klassen diesen Kategorien zuordnen können.
Und hatte dann auch angefangen, einen relativ kleines System zu bauen,
also von Grund auf. Also diese Regeln sind verbaut,
sowohl in der Mediathek als auch in dem Kinoticket-Verkaufssystem.
Das heißt, ihr könnt eigentlich das immer überprüfen,
ob wir diese Regeln auch tatsächlich umgesetzt haben. Ich habe auch mitbekommen,
die Regeln standen auch relativ spät im Komsi,
also die Regeln selbst, das sind ja irgendwie sechs Seiten,
diese Entwurfsregeln, die waren wohl auch etwas spät im Kamsi diesmal.
Das sind so Sachen, das ist natürlich ärgerlich.
Aber wir haben auch jetzt wieder das Feedback bekommen von Betreuern,
die sagten, naja, die Leute haben die Regeln noch gar nicht so richtig wahrgenommen.
Nehmen nur das, was in der Vorlesung dran war oder so.
Also liest euch schon mal das durch, was da auf dem Zettel steht.
Es ist ja nicht so, dass ihr das alles sofort verstehen müsst,
aber ihr sollt versuchen, das abzubilden auf den Quelltext.
Das ist schon ganz spannend. Okay, ja,
also das sind relativ große Systeme, die wir euch hier vorgeben.
Die Mediathek ist riesig, das Kino-Ticket-Verkaufssystem ist ein bisschen kleiner,
aber auch noch relativ groß.
Wir können eigentlich nicht erwarten, dass alle von euch
da komplett durchsteigen
Und deswegen habe ich ja ein sehr kleines System angefangen zu bauen,
das sozusagen ohne einen Service auskommt, auch ohne Fachwerte,
einfach nur ein Material hat und ein Werkzeug,
das dieses Material interaktiv manipulierbar macht.
Das war dieses wunderschöne kleine Beispiel hier.
In BlueJ. Ich habe einen Ereigniszähler, das ist mein Material.
Ich kann doch mal hier die Schnittstelle zeigen. Das war
wirklich relativ simpel gestrickt. Das war so diese Idee,
ich habe auch irgendwo eine Live-Live-Dings,
was ich
mal zeigen kann
Ah, hier, das war wieder dieses Schaf springt über den Zaun,
ja, kann also hier in dieser wunderbaren kleinen Gui,
das ist sozusagen ein Werkzeug, mit dem ich das Material bearbeiten kann,
große Worte für, ich erhöhe den Zähler, ja, klar,
aber es ist, im Kleinen ist es genau das,
da ist irgendein Material und ich habe jetzt hier eine grafische Oberfläche,
ein Werkzeug, mit dem ich jetzt diesen Zähler,
der dahinter hängt, diesen Ereigniszähler manipulieren kann,
kann also hier auf Registrieren klicken und der Zähler zählt da hoch.
Hier ist irgendwie das Datum,
wann der Zähler angelegt wurde, die Idee war,
als Motivation, jemand möchte wie Tiere in der Wildnis beobachten,
im Afrika Busch und hat dann verschiedene Zähler auf seinem Bildschirm
für verschiedene Tiere und kann dann immer da klicken und hinterher kann diese Materialien wunderbar auswerten.
Es ist eine Möglichkeit, wie man seine Arbeit organisieren kann.
Es ist ein bisschen weit hergeholt, aber nicht so absurd.
Und das ist hier, wie gesagt,
das Schaf über Zaun, das ist das Werkzeug,
mit dem ich mein Ereignis erzählen kann,
wenn ich abends versuche einzuschlafen.
Toll, habe ich jetzt hier schon einige Schafe erzeugt, beziehungsweise gezählt.
Dann, genau, jetzt nochmal die Schnittstelle von diesem Ding hier.
Ich kann also mir den Zählerstand geben lassen.
Gib mir einfach
den aktuellen Zählerstand
Ich kann ein Ereignis registrieren. Das ist sowas wie,
erhöhe den Zähler, registriere ein Ereignis.
Die Ereignisart kann man sich als Dring geben lassen.
Also man kann da bei der Erzeugung, ein Konstrukte,
eine Ereignisart angeben, nichts weiter als eine Zeichenkette,
scharf über Zaun oder was hatte ich letztes Mal,
ich glaube, Chuck and Norris rettet die Welt oder sowas.
Und dann kann man eben halt für dieses Ereignis dann immer
Dinge abfragen und kann sich außerdem auch noch den Erzeugungszeitpunkt als String geben lassen.
Also eine sehr einfache Schnittstelle, ein sehr einfaches Material.
So, das hat soweit auch für sich funktioniert.
Ich kann da ja ein Material hier auch interaktiv erzeugen,
irgendwie scharf über Klinge. Ach nee, das ist was anderes.
Na gut, ihr wisst Bescheid. Und dann kann ich
hier tatsächlich interaktiv auch in Blue Jay das Ding manipulieren.
Also ich kann jetzt hier irgendwie, ja,
da den Zähler erhöhen, ihr registrierereignis und das funktioniert auch interaktiv.
Aber das geht ja, wie gesagt, nur in Blue Jay
so schön und deswegen machen wir das jetzt hier mit einem Werkzeug.
Wir wollten jetzt eine Guy bauen, mit der wir das hier machen können,
also praktisch die Guy-Nachbauen, die ich da gezeigt habe.
Dazu habe ich hier das Zielwerkzeug gebaut, sehr,
sehr klein nach den Entwurfsregeln
Also auch hier nochmal so ein bisschen relevante Entwurfsregeln,
bis die Werkzeugklasse, erhält ihr Material als Konstruktorparameter über Setter
oder holt es sich über Services?
Nur gut, wir haben keinen Service hier.
Wir haben also nicht einfach gesagt, das materiell,
das Werkzeug bekommt das Material als Konstruktorparameter reingereicht.
Das ist der Konstruktor. So,
dann wird dieser Zähler einfach hier in den Exemplarweihern abgelegt.
Und das Zielwerkzeug erzeugt sich ein Exemplar seiner eigenen UI-Klasse.
Das ist diese UI hier. Und diese UI-Klasse war sehr
klein bisher. Da war nichts drin. Die haben wir
noch leer implementiert. Und dann hatten wir hier das Start-up,
das nichts weitermacht als ein Exemplar
Ein Ereigniszählerexemplar zu erzeugen und das dann an ein Zielwerkzeug zu übergeben.
Ja, auch das sehr, sehr überschaubar hier.
So. Gut, das ist das Ausgangssystem. Dann hatte ich gesagt,
die UI-Klasse eines Werkzeugs hat die Aufgaben,
die Gui-Komponenten zu erzeugen, zu layouten und zu verwalten.
Also einfach, das ist so die Kapsel um diese Gui-Komponenten.
Diese Gui-Komponenten habt ihr bis jetzt noch nicht kennengelernt,
weil ich da gesagt habe,
na bevor wir das jetzt uns genauer angucken können mit diesen Gui-Komponenten,
solltet ihr erstmal ein bisschen was über Entwurfsmuster lernen.
So, und hat Guido letzte Woche euch hier
das Beobachtermuster vorgestellt
Ein sehr zentrales Entwurfsmuster für grafische Benutzungsoberflächen.
Nicht nur für grafische Benutzungsoberflächen. Man kann da,
wer da wen beobachtet, das kann sehr flexibel sein.
Aber gerade bei grafischen Benutzungsoberflächen ist dieses Muster exzessiv verbaut in der Software.
Okay. Jetzt sind wir ja nicht so weit.
Jetzt können wir endlich mal in die grafischen Benutzungsoberflächen rein.
Und jetzt kommt sozusagen hier die Motivation, warum macht man
überhaupt das so, wie wir es auch hier beschreiben?
Also warum erzählen wir euch jetzt,
dass man eine Google-Klasse hat und das getrennt hat im Werkzeug
von den Materialien
Der erste Satz, trifft das eigentlich ganz gut, Technologiezyklen unterscheiden sich von fachlichen Zyklen.
Das klingt erstmal so abstrakt. Letztendlich ist es eigentlich ganz einfach,
wenn man für eine Versicherung eine Software baut,
die interaktiv ist, dann gibt es in der Versicherung fachliche Änderungszyklen,
also es gibt neue Gesetzeslagen, es gibt neue Versicherungsverträge,
es gibt,
also die Fachlichkeit in der Versicherung ändert sich und das passiert halt in mehr oder weniger regelmäßigen Abständen.
Und davon unabhängig gibt es aber auch Technologiezyklen,
also es gibt eine neue Generation von grafischen Benutzungsoberflächen für für Software.
Es gibt überhaupt grafische Benutzungsoberflächen. Ja, früher haben die
ja mit irgendwelchen Hostmaschinen gearbeitet. Heutzutage kommt als nächste Technologie
zyklus hinzu. Wir wollen das alles auf mobile Geräte bekommen.
Da passiert also ganz viel und das ist ja völlig unabhängig erstmal von der Fachlichkeit.
So, was wir wollen, ist, dass wir das erstmal einander entkoppeln.
Das heißt, wir trennen diese Präsentation, die Handhabung,
die grafische Darstellung von der eigentlichen Funktionalität. Ja,
das heißt also, im Idealfall ist es so,
wenn ihr eure fachlichen Klassen modelliert, also eure Materialien,
eure Services, dann sollte es vollkommen irrelevant sein,
ob diese fachliche Operation, die da aufgerufen wird,
über eine grafische Benutzungsoberfläche ausgelöst wird oder vielleicht über eine textuelle Oberfläche,
so wie wir es ja gerade hier auch in Blue Jay gesehen haben.
Ich konnte dieselbe Schnittstelle ja von Hand aufrufen in Blue Jay in
der IDE oder ich kann das über eine Gummi machen.
Das heißt, man möchte eben halt bei gleicher Fachlichkeit auch eine andere Gummi draufsetzen können,
das ist kostengünstig und deswegen diese Forderung nach dieser Trennung.
Und das ist wieder ein weiterer Grund,
warum die Regeln so sind, die Entwurfsregeln,
wie wir sie formuliert haben,
nämlich dass Werkzeuge zuständig sind für diese Handfrage der Präsentation.
Was wird gezeigt von Material
Und wie kann man das handhaben? Also was kann man
denn mit dem Material dann tun über dieses Werkzeug,
über die grafische Oberfläche? Und Services, Material und Fachwerte
, die bilden eigentlich genau die Funktionalität ab.
Das Eigentliche, was da zu tun ist.
Ja, jetzt gibt es da eine ganze Menge Goey-Tokels.
Diese Folie ist immer noch ziemlich veraltet. Jedes Jahr denke ich wieder,
Mensch, da müsste man eigentlich mal ein bisschen die Formulierungen ändern.
Also Betriebssysteme bieten seit einigen Jahren Unterstützung für grafische Oberflächen.
Das ist jetzt schon ziemlich lange, dass sie das anbieten.
Also so 20 Jahre vielleicht, 30. Was haben wir denn,
Mac? Wann war der? Mac da 84?
Ja, sind jetzt
30 Jahre
Diese grafischen Benutzungsoberflächen waren sehr plattformspezifisch. Ja,
also es gab dann für den Mac was,
dann gab es irgendwann Fluwindows was und dann auch für die
Unix-Systeme und die waren auch sehr häufig zu Anfang nicht objektorientiert,
diese grafischen Benutzungs-, diese grafischen Toolkits.
Und deswegen wurde für Java und ihr wisst ja,
dass Java den Anspruch hat, plattformübergreifend zu funktionieren.
Das heißt, ich kann tatsächlich auch eine Gui in Java
programmieren und die läuft auf jeder Plattform auf eine Java Virtual Machine läuft.
Und deswegen wurde für Java, wurden Gui-Toolkits gebaut,
zum einen das AWT, Abstract Windowing Toolkit, das war so sozusagen,
die ich glaube, die Version 1-1 oder so.
Und dann kam in Version 1-2,
kam dann Swing dazu von Java und Zwing setzt teilweise dann auf den AWT-Komponenten auf.
Im Skript sind da noch zwei Folien mehr,
die werde ich jetzt nicht vorstellen,
wo dann so ein bisschen nochmal auseinandergemüset ist,
dass man irgendwie mit AWT versucht,
so den kleinsten gemeinsamen Nenner zu kriegen und zwingen eigentlich dann tatsächlich die Komponenten selbst baut.
Das ist aber erstmal gar nicht so wichtig. Was wir wollen,
ist, dass diese Gree-Komponenten uns überhaupt ermöglichen, ja,
grafische Oberflächen zu bauen, also den Umgang mit grafischen Oberflächen,
auch die Portierung zu erleichtern.
Und Das mit Java hier entsprechend gut hinzukriegen.
Das ist tatsächlich auch mit diesen Toolkits gut möglich,
diese Forderung nach dieser Trennung durchzusetzen. Hier ist jetzt genau das,
was wir schon mehr oder weniger gesehen haben.
Unsere erste Swing-Applikation. Also ein Knopf,
ein Ausgabefeld in unserem Beispiel jetzt noch ein bisschen mehr.
Also wir haben jetzt hier noch irgendwie unseren Erzeugungszeitpunkt.
Und dann habe ich aber hier genau das,
was da auf der Folie auch draufsteht.
Wenn der Knopf gedrückt wird, dann wird ein Zähler hochgezielt.
Die Frage des Tages oder die Fragen des Tages.
Erstens,
welche Green-Komponenten
Uns zur Verfügung, sowas wie Buttons oder auch so Labels,
die da so angezeigt werden,
dann wie können wir diese Komponenten mit unseren fachlichen Klassen verbinden?
Und dritte Frage, wie können wir das Layout steuern?
Also wenn ihr da auch hier das Layout so anguckt,
dann ist das ja hier erstmal irgendwie so erkennbar.
Man sieht aber zum Beispiel, wenn ich jetzt das hier größer ziehe,
dann wird das irgendwie, bleibt das mittig und so.
Das gucken wir uns dann später auch noch an.
Wir wenden uns also jetzt erstmal der Frage zu,
was für Greek-Komponenten gibt es denn so?
Und da gibt es eine ganze Menge, also jetzt einfach in Swing.
Swing ist die Bibliothek, die wir jetzt hier einsetzen.
Wie gesagt, teilweise schimmert da auch noch das AWT
mit durch
Das sind lauter so Elemente, die man
alle mal auch mal probiert haben sollte, gesehen haben sollte.
Also zum Beispiel ein J. Label,
das ist nichts weiter als ein Etikett,
das man irgendwo hinkleben kann auf so einer Oberfläche.
Da kann man auch teilweise Bilder drauf ablegen.
Meistens ist es ein Textlabel. Dann sowas wie Buttons.
J. Button gibt es als Radio-Button, als Check-Button oder als so einen Click-Button.
Textfields, das sind so typischerweise so einzeilige Textfelder,
wo man Texte eingeben kann.
Text Area kann auch mehrteilig sein. J. List,
eine Liste von Einträgen,
wie auch immer
Geordnet oder eine Combo-Box, sowas kennt ihr auch,
dass man irgendwie hier auf so ein Dreieck klickt,
dann klappt so eine Liste runter von den Einträgen,
während die Liste hier eigentlich sozusagen immer zu sehen ist.
Man kann es mit so einem Scrollbalken versehen. Jays Grollpain ist tatsächlich
so eine Abstraktion, mit der man dann erlauben kann.
Dinge, die logisch größer sind auf einem kleineren Bildschirm,
Scrollbar zu machen, alles mögliche.
Da gibt es, wie gesagt, eine ganze Menge.
Dann gibt es hier so die eher etwas größeren Elemente.
Sowas wie einen Jay Frame, so das, was man hier sieht,
das hier ist tatsächlich ein Jay Frame, eine Komponente,
die zum vom Betriebssystem, in dem das Ganze läuft,
maßgeblich beeinflusst wird in seinem Aussehen.
J. Dialog, also sowas wie, da poppt was auf.
Willst du jetzt weitermachen? Ja, okay, oder gibt irgendwas ein?
Internal Frames, bei denen man dafür sorgen kann,
dass die innerhalb eines Fensters bleiben, also ein Subfenster,
das aus dem Umgebungsfenster nicht raus kann.
J. Color Chooser, kennt ihr wahrscheinlich auch aus verschiedenen Anwendungen,
wie, was weiß ich, Word oder so, oder PowerPoint.
Und dann so Option Pain hier, um irgendwelche Nachrichten aufzuzeigen,
wo man dann eine Bestätigung abwartet. Das sind meistens modale Dialoge,
also im Sinne von modal, ein Dialog heißt ein Modal,
wenn er erscheint und man darauf reagieren muss,
also nicht irgendwie jetzt auf ein anderes Fenster kicken kann
Okay, das ist auch hier mal in der API noch mal zu sehen.
Das ist relativ viel Zeug. Das ist aber ganz toll,
weil ihr dadurch wirklich eine unglaublich große Bandbreite an spannenden Gummi-Komponenten habt, die ihr einsetzen könnt.
Ich kann das hier mal zeigen. Also Java-AWT. Wenn
wir da mal draufklicken, dann sieht man hier,
es gibt also eine ganze Reihe von Interfaces.
Und dann gibt es hier relativ viele AWT-Klassen.
Und wenn ich jetzt hier auf Java-X Swing gehe,
also Java-X für Java Extension, Irgendwo,
hier muss es ja mal kommen, swingen, komm, swingen.
Da, Java Ex-Swing. Das ist die andere große Bibliothek.
Die ist halt auch ganz schön groß. Also auch wieder
eine ganze Menge Interfaces. Und dann eine ganze Menge Klasse.
Hier so ein Box-Layout, gucken wir uns gleich mal an.
Und irgendwelche Input-Maps. Und da sind natürlich auch viele Hilfsklassen dabei,
sind nicht nur Gui-Elemente, aber das ganze Zeug liegt hier.
Und ihr könnt es euch in Ruhe auch dann auch mal ansehen.
So, wie bauen wir jetzt mit diesen Komponenten Oberflächen?
Ganz einfach, die werden hierarchisch angeordnet
Relativ simpel. Man kann also diese Komponenten unterscheiden in Container-Komponenten,
die andere enthalten und atomare Komponenten, die keine anderen Komponenten enthalten können.
Container bieten deshalb eine Schnittstelle an, mit der die Komponenten
dann eingetragen werden können. Es gibt also eine Operation Ad,
wo man sagen kann, jetzt hier in diesen J Frame
sollen jetzt mal irgendwelche Panel, irgendwelche Buttons eingefügt werden.
Dass man hier an einem Beispiel gezeigt,
also ich habe hier so eine grafische Benutzungsoberfläche, so das gesamte Fenster,
dann gibt es hier eine Überschrift, irgendwie ein Label,
dann gibt es da irgendwie so etwas,
was so tabellenartig angeordnet ist mit zwei Labels
Zwei Textfeldern offensichtlich so angedeutet. Und darunter ist dann etwas,
wo dann so drei Buttons in einem anderen Ding angeordnet sind.
So, wenn man sich das jetzt überlegt,
wie das wohl hierarchisch aufgebaut ist, ist das relativ einfach.
Das Außenrum ist ein J. Frame,
der enthält auf der obersten Ebene ein J. Label,
ein J. Panel und noch ein J. Panel.
Das sind hier gelb und hellblau, hervorgehobene Elemente.
Und die wiederum enthalten weitere Elemente. Also der J. Panel
kann jetzt hier zwei Label enthalten und zwei Textfelder.
Und der hellblaue Panel da unten enthält drei Buttons
Das ist schon mal ganz wichtig. Dann muss man natürlich wissen,
dass es irgendwie sowas geben muss wie die Container,
die quasi direkt den Kontakt zum Betriebssystem haben.
Das sind die sogenannten Top-Level-Container in Swing. Das heißt,
da ist ein direkter Zusammenhang da. Top-Level,
Container ins Ring sind Jay Frame, J. Dialog,
J. Option Pain J. Applet.
Das sind hier so mal einige genannt.
Und ein Jay Frame enthält unter anderem einen sogenannten Content Pain
und da sind dann die ganzen Hauptkomponenten der Oberfläche eingetragen.
Das kann man sich hier nochmal
ganz schön ansehen
Also, wenn ihr so ein allgemeines Fenster habt,
ich kann ja auch hier, was weiß ich,
Blue Jamie mal hernehmen, ja,
da habe ich auch jetzt ja oben eine Menüleiste,
ja, das Ganze ist ein J Frame,
dann gibt es eine Menüleiste mit Menüeinträgen,
dann gibt es hier irgendwelche Buttons,
dann gibt es hier irgendwie so eine Komponente, hier unten auch nochmal,
ist also tatsächlich genau strukturiert nach diesen Prinzipien, das heißt,
ich habe hier oben, hier unten irgendwie diese große Fläche,
wo die ganzen Elemente drin sind,
dann gibt es irgendwie ein Menübar mit diesen Menüeinträgen.
Optional muss es ja nicht geben. Und ein Titlebar,
der üblicherweise vom Betriebssystem festgelegt ist, was da alles erscheinen darf.
Das Ganze ist dann ein J Frame. Okay,
das wollen wir jetzt mal als erstes hier direkt umsetzen,
was wir gerade uns so angesehen haben
Wir haben gesagt, wir zerlegen ein Werkzeug immer in eine Werkzeugklasse, eine UI-Klasse.
Werkzeugklasse vermittelt zwischen grafischer Oberfläche und den fachlichen Klassen.
Die Werkzeugklasse erzeugt ein Exemplar in ihre UI-Klasse im eigenen Konstruktor.
So, und jetzt kommen wir nämlich dazu,
das mal ein bisschen aufzufalten hier. Diese UI-Klasse,
eines Werkzeugs hat die Aufgaben, die GUI-Komponenten zu erzeugen.
So, jetzt können wir einfach mal hier das mal implementieren.
Eine Aussage ist hier eine UI-Klasse,
erbt nicht von UI-Framework-Klassen wie J Frame oder J Panel,
um die eigene Schnittstelle schmal zu halten.
Sie definiert als oberste UI-Komponente üblicherweise einen J Frame
Wenn ihr in Lehrbücher reinschaut, mit grafischem Benutzungsüberflächen,
mit Umgang mit Zwingen,
dann steht da irgendwie das erste Beispiel immer MyClass,
Extense, J Frame.
Da erbt die fachliche Klasse von dem J Frame aus dem Collection Strangwork.
Da kann man sich jetzt fragen, warum ist das so gemacht?
Weil das führt dazu, dass alle Operationen,
die ein J Frame hat, auch zur Schnittstelle von eurer eigenen Klasse gehören.
Wie sinnvoll das ist, kann man sich fragen.
Das ist so ein, sagen wir, eine typische Unart,
dass das eben halt für so kleine Beispiele in Lehrbüchern gerne gemacht wird.
Wir haben es sozusagen hier als Entwurfsregel anders gemacht.
Wir sagen halt, eine UI-Klasse erbt da nicht von,
sondern die hat eben halt ein Exemplar davon.
Die hat ein Exemplar einer solchen J-Frame, klasse.
Ja, dann bauen wir das doch einfach mal hier.
Gehen wir mal hier dieses Zielwerkzeug rein. UI, das
ist hier noch relativ klein. Schreibe ich hier erst mal
einen Konstruktor, Public, Zähl, Werkzeug, UI.
Und da sagen wir jetzt einfach mal, der soll ja
hier jetzt einen solchen Jay Panel, einen J-Frame enthalten.
Private Jay Frame, das ist sozusagen mein Frame.
Und in dem Konstrukt, als erstes mache ich jetzt
mal hier einen Frame ist gleich New J Frame.
So, das kann ich jetzt so hinschreiben. Dann habe
ich sozusagen in meiner Jörg-Klasse erstmals die erste UI-Komponente hergeholt.
Ich brauche ja so erstmal diesen umgebenden Frame. Das kann
ich jetzt versuchen zu übersetzen, das wird nicht gehen.
Kennot Find Simble Class J Frame. Okay, also schreibe
ich hier mal als erstes Import JavaX, glaube ich.
Swing Stern. Und ich hoffe, dass das die richtige,
der richtige Import ist.
Ja, also Jay Frame ist eine Klasse aus dem Swing.
Was ist der Swing-Bibliothek?
So, wunderbar
Wir wollen ja, dass in dem, hier,
in diesem Beispiel, dass da oben der Titel,
in dem J. Frame auch die Information darüber enthält,
was ist das denn für ein Material,
was jetzt hier gerade manipuliert wird,
was für ein Ereignis wird denn da gerade gezählt?
Gut, kann man jetzt einfach so machen,
dass man hier sagt, ich habe hier einen Parameter bei dem UI,
bei dem Konstruktor und lasse mir hier den Titel geben.
Ja, gut, dann kann ich hier tatsächlich diesen Titel setzen.
Das heißt, bei einem J. Frame kann ich genau sagen,
welcher String da jetzt als Titel gesetzt wird.
Das müsste jetzt übersetzbar sein. Problem ist,
in unserer benutzenden Klasse, hier in unserem Zielwerkzeug,
da ist natürlich jetzt hier der Parameter noch konstrukterlos aufgerufen worden.
Jetzt wollen wir da natürlich was übergeben.
Was wollen wir denn da übergeben? Wo kriegen wir jetzt
sozusagen den Titel für den Frame her? Wir hatten Vorschlag,
wie wir das jetzt hier konkret bauen, ja?
Übergeben lassen. Ja, also haben wir den nicht schon?
Genau, wir wollen ja hier, das Werkzeug bekommt als
Parameter ein Ereignis Zähler, das ist das Material.
Und in der Gui soll natürlich erscheinen,
was für ein Ereignis ist es denn
Und wenn wir das wissen wollen, was ist es für
eine Ereignisse, dann schreiben wir das halt genau hierhin.
Also kann ich hier sagen, entweder Zähler, Zähler, gib.
So, jetzt kann ich hier hoffentlich, oh, keine passende Vervollständigung.
Nein, das heißt Get, Get, Get.
Oh, guck mal hier. Code Completion in Blue Jay
, hab ich noch nie gesehen.
Get Ereignisart. So, jetzt kann ich das hier übersetzen.
Und das müsste jetzt gehen. Genau. Also jetzt haben
wir schon mal in unserer UI.
Hier unseren Titel
Gut. Was wollen wir denn als nächstes machen?
Wir brauchen ja jetzt auch einen Button und wir brauchen auch diesen Label,
der anzeigt, wann das Ereignis erzeugt wurde.
Also jetzt fange ich hier an, tatsächlich mir diese Exemplarvarianten zu deklarieren.
Also Private, das ist jetzt genau das,
was so eine UI-Klasse macht.
Sie verwaltet die ganzen Gummi-Komponenten. Also ich sage jetzt hier
zum Beispiel Jay Label
und das ist jetzt irgendwie Zeit-Label
Und jetzt möchte ich hier an dieser Stelle diesen J-Label erzeugen,
diesen Zeit-Label erzeugen. Und sage hier New J. Label.
Und bei dem Label kann ich beim Konstrukteaufruf angeben,
was er anzeigen soll, den Text.
So, biete das Problem, wo kriege ich das jetzt her?
Naja, wir haben es ja schon gesehen.
Ich kann mir ja hier als weiteren Parameter übergeben lassen,
wann das Ding erzeugt wurde.
Das heißt also, ich mache jetzt hier wieder String einfach.
Zeitpunkt, ja, Zeit irgendwie und so weiter.
Und dann kann ich hier diesen Parameter Erstmal mit übergeben.
Auch das lässt sich jetzt übersetzen. Also zurück in das andere Werkzeug hier.
Ich muss also jetzt hier wieder ran und muss sagen,
da muss noch ein weiterer Parameter übergeben werden.
Also auch hier jetzt Zähler, Get, Erzeugungszeitpunkt.
Wunderbar. Als Dring hoffentlich übersetzbar. Ja. Gut.
Zurück wieder in unsere UI. Wir haben jetzt,
wir gucken mal, was wir bauen wollen.
Das Ding liegt hier mal so ein bisschen da rechts.
Da können wir dann mal so, wir wollen,
dass man diesen Label da hat.
Was ich vielleicht noch mal eben mache, ist,
ich werde hier jetzt ein bisschen tricksen.
Ich schalte jetzt hier nämlich hin, Container, Content, Pay.
Bis gleich. New J Frame. Nein. J Panel.
Ein J Panel ist so ein Teil in einer grafischen Oberfläche,
das wie so in einer Art Zeichenfläche ist.
Wo man dann Dinge zusammenfassen kann. Ich habe ja eben
schon gesagt, so ein Hauptfenster, Top-Level,
Window hat immer so einen Content-Pay
Und ich kann jetzt hier an diesem Frame sagen, Set Content Pain.
Und übergebe hier diesen Content Pain. Damit habe ich sozusagen hier
diese Kontrolle darüber, dass es wirklich ein J. Panel ist.
So, und jetzt ist sie es hoffentlich übersetzen.
Container, aha, okay, kennt er nicht.
Da muss ich jetzt mal eben hier importen. Und das ist auch
relativ häufig so, dass sie das schon machen müsst.
Java, AWT und dann auch wieder die einfachste Art und Weise.
Ich importiere einfach erst mal alles. Ob das jetzt schön
ist an dieser Stelle, sagen wir mal, dahingestellt.
Ich benutze jetzt diesen Typ Container und der kommt tatsächlich aus
dem AWT
So, J. Panel kennt er nicht.
Konnte. Ja, okay, habt ihr recht.
Danke für den Hinweis. New J. Panel, ja.
Klasse übersetzbar. Kein Problem. Also, was haben wir
jetzt gemacht? Wir haben jetzt ein Frame, Pop-Level-Frame,
haben da ein Content-Pain gesetzt, haben jetzt ein Zeitlabel.
Hm, jetzt würde ich natürlich gerne irgendwie dann
diesen Zeitlabel auch in diesen Content-Pain reinschmeißen.
Also, kann ich jetzt hier schreiben,
Content?
Pain.at. Zeitlabel
Tatsächlich habe ich jetzt einfach diesen Zeitlabel in diesem Panel mit reingeschmissen.
Ich hoffe, das lässt sich übersetzen. Das lässt sich
übersetzen. Gut. Dann brauche ich natürlich einen Button.
Ich will ja da oben hier was klicken.
Machen wir doch mal hier. Nächste Google-Komponente Jay-Button. Juhu,
das ist mein Button. Okay, den muss ich natürlich
auch erzeugen hier. Button ist gleich New J Button.
Da ist es jetzt auch wieder so,
da kann man den Text, der auf dem Button angezeigt wird,
den kann man übergeben
Ja, ich werde das jetzt einfach mal hier hardcodieren.
Das ist nicht unbedingt das, was man so machen würde.
Den Label würde man wahrscheinlich irgendwo wieder als Konstante definieren.
Das ist jetzt hier so ein bisschen Quick and Dirty für die Präsentation.
Lässt sich übersetzen. Immer gut mal so zwischendurch übersetzen,
um zu sehen, ob mal alles geht.
Nicht zu viel Code schreiben, wo man nicht weiß,
was der tut.
Ja, und dann mache ich das Gleiche wie eben.
Ich schreibe content-hain.head und schmeiße jetzt
diesen Button da rein
Wunderbar. Lässt sich übersetzen. Als letztes jetzt noch diese,
den Label, der den Zielstand anzeigen soll.
Okay, auch das hier einfach mal ganz schnell geschrieben.
Jay Label, Zähler. Ja,
und dann muss ich hier einfach nur diesen Zähler initialisieren.
Gleich New J Label. Und da ist es jetzt wieder
so, was wird denn da jetzt anzeigen? Naja,
wahrscheinlich genau den aktuellen Wert, den dieses Material da gerade anzeigt.
Die UI kennt das Material nicht. Das ist immer ganz wichtig,
dass die UI-Klassen, die Gui-Klassen, keine Materialien bekommen.
Man möchte nicht, dass in einer Gui ein Material ist
und dann in der Oberfläche verändert werden könnte.
Die Kontrolle, was mit dem Material passiert hat,
hat die Werkzeugklasse, die Gui kriegt immer nur Werte hochgereicht.
Also Strings, Ins und Ähnliches. Hm, okay. Ja,
wir lassen uns mal eben hier nochmal eben den Wert,
der angezeigt werden soll, übergeben.
Also sage ich hier einfach in Wert.
So. Und dann sage ich hier, mach mal so ein
J. Label und übergebe den Wert da.
Ja. Ich weiß nicht, ob das geht.
Ah, geht nicht. Ah. Ich kann natürlich
keinen Int als Parameter begeben,
weil der erwartet einen String
Gut, ich bin hier mal relativ einfach gestrickt.
Ich mache jetzt hier einfach mal so. Ich könnte es
auch noch anders machen. Könnt ihr hier ein String draus machen.
Der eine zeiget Wert. Und dann würde das hier auch funktionieren.
Dann würde auch sozusagen diese Gui gar nicht wissen,
dass es jetzt irgendwie ein Int ist, der da angezeigt werden soll.
Die kriegt einfach nur einen String, den sie anzeigen soll.
Lässt sich so übersetzen. Und auch diesen Label würde ich
jetzt in den Content-Pain reinschmeißen, Content-pain.at.
Zähler. So, lässt dich übersetzen.
Wir schließen das. Jetzt müssen wir nochmal in unser Zählwerkzeug anfassen.
Da ist natürlich jetzt noch ein bisschen was nicht in Ordnung.
Ich muss jetzt hier noch einen weiteren Parameter übergeben,
nämlich von diesem Zähler irgendwie Get. Was haben wir da?
Zählerstand. Das ist der dritte Parameter. Das ist jetzt
der Punkt, wo ich jetzt hier den Int übergebe,
an einens dringen, das wird nicht funktionieren.
Also er sagt hier, das funktioniert so nicht.
Also mache ich jetzt hier diesen Trick.
Quick and Dirty. Ich mache aus dem Int,
in dem ich jetzt mit einem leeren String verknüpfe, einfach einen String.
So, und das lässt sich jetzt übersetzen. Und fertig
ist unsere grafische Benutzungsoberfläche. Ich kann tatsächlich dieses Ding jetzt
hier ausführen. Passiert nichts. Was ist schief gegangen?
Hat jemand einen Vorschlag? Naja, die Leute,
die das schon wissen, da vielleicht jemand, lasst uns noch Fernzeigen.
Also ich glaube, das ist das Frames, was ich verpacke.
Ah, genau, ganz wichtige Aussage.
So ein Frame ist erstmal nicht sichtbar. Das heißt,
das Ding ist jetzt irgendwo im Hintergrund und man weiß nicht wo.
Und wir kriegen es auch nicht sichtbar. Das heißt,
wir müssen jetzt erstmal nochmal in unserer Zillwerk UI am Ende
hier sagen, Frame, Set Visible True.
Lässt sich übersetzen, schließen oh, die Aufregung und die Aufregung.
Und jetzt hier, ja. Sieht noch so ein bisschen doof
aus, ne? Aber man kann das schon erkennen,
da ist es. Tatsächlich, man kann die Button klicken.
Toll. Das kann man immer, weil der Button ist
ja da, aber es passiert noch nicht viel.
Also wir haben ja jetzt noch nicht diese Anbindung gebaut,
aber die Dinger sind da drin.
Wir haben gerade hier einen Norris rettet die Weltzähler gebaut.
Nur das mit dem Registrieren klappt noch nicht
Es ist also dann auch ganz schlau, an dieser Stelle zu sagen,
naja, machen wir das mal vielleicht dann drüber.
Irgendwie so ein Frame-Set, Size, 290 mal 40,
ist, glaube ich, eine ganz gute Größe.
Ich hoffe, das lässt sich so machen. Ja,
set size, so übersetzen, nach einem gucken,
dass das jetzt auch funktioniert.
Immer noch nicht so richtig. Sieht irgendwie noch nicht
so richtig doll aus. Da ist eine Meldung dazu.
Die Größe
Er sagt, könnte man die Größe nicht mit Peck vernünftig setzen.
Aha, okay. Also es gibt jetzt, jetzt kommen so
diese ganzen Spezialitäten, wenn man mit solchen Gui-Frameworks arbeitet.
Das ist hier wie im richtigen Leben, ja.
Also ich versuche das natürlich jetzt hier sehr plastisch zu machen.
So experimentell muss man dann teilweise vorgehen. Man muss rausfinden,
was da wie zu tun ist. Ich finde es jetzt
gerade erstaunlich, dass das hier noch nicht so richtig klappt.
Aber man kann natürlich jetzt mal mit Frame.pack probieren, ja.
Klar, Frame.pack, ja. So lässt sich übersetzen.
Schauen wir mal, was da jetzt rauskommt
Aha, roh, viel besser. Also jetzt sieht das hier ganz gut aus.
Gut, aber das ist jetzt erstmal der erste Aspekt.
Wir haben jetzt unsere GUI-Klasse, unsere UI-Klasse,
den ersten Schritt, aber wir haben die GUI-Komponenten zusammengesammelt,
haben uns überlegt, welche wir nehmen wollen.
Und haben die da einfach erstmal reingeschmissen. Was wir
uns gleich ansehen werden, ist das eine UI-Klasse,
die für ihre Werkzeugklasse relevanten UI-Elemente über Ghetter an ihrer Schnittstelle zur Verfügung stellt.
Das sehen wir uns gleich mal an.
Das brauchen wir jetzt momentan noch nicht, aber gleich.
Was auch wichtig ist, eine UI-Klasse hat keine Abhängigkeiten zu
anderen Elementtypen
Verwendet nur Importer aus dem UI-Framework. Also hier tatsächlich in
unserer UI-Klasse. Erstens ist es nur eine Klasse, keine
Public Class. Also wenn das in einem Werkzeugpaket liegt,
zusammen mit der Werkzeugklasse, dann ist die UI-Klasse üblicherweise Paket privat.
Weil niemand sonst braucht diese Klasse. Während das Werkzeug wahrscheinlich
von außerhalb des Pakete schon benutzt wird, zum Beispiel von dem Start-up.
Und man hat halt nur die Importe hier von irgendwelchen Gui-Elementen.
Wenn da irgendwie sowas steht wie Import, Material oder so,
Material.stern, dann ist da was faul.
Das sollte nicht so sein. Also die UI-Klasse sollte komplett
frei sein von Wissen über Materialien über Fachlichkeit
Gut. Eine UI-Klasse-Paketintern. So. Was wir,
wie gesagt, jetzt schon gesehen haben, ist,
dass die Werkzeugklasse ihr Material als Konstruktorparameter hält.
Was wir auch machen könnten, und das werden wir jetzt
einfach mal bauen, einfach um eine bestimmte Situation zu erzeugen,
der dann wir aktiv werden müssen.
Man kann es auch über Setter setzen. Also ich kann
tatsächlich jetzt hier in meinem Zielwerkzeug eine Methode reinschreiben,
die da heißt Public Void
Set-Zähler. Ja, wird also ein Ereigniszähler reingegeben.
Und entsprechend dann auch in den Exemplarvariablen abgelegt.
Ich habe ja hier oben meine Exemplarvariable für den Zähler.
Ja, und sage jetzt hier einfach, Mia, das ist hier EZ.
Das kann ich machen, ja, lässt sich jetzt machen.
Ich kann also jetzt an dem Werkzeug sagen,
zeige jetzt mal ein anderes Material an. Das ist jetzt
momentan nicht implementiert, wenn ich das jetzt hier mal tatsächlich benutze.
Also ich erzeuge mir einen Ereigniszähler hier, ja, irgendwie scharf über Zaun.
Ja, das ist mein erstes Ereignis. Mein Ereigniszähler,
mein Material 1. Ja, jetzt mache ich mir noch einen weiteren Ereigniszähler.
Norris und so weiter. Ihr wisst schon. Den kann
ich jetzt mal ein Zählwerkzeug hier erzeugen. Ja, ein
New-CL-Werkzeug. Übergebe zuerst mal diesen, dieses Jahr als Parameter.
Und dann kriege ich tatsächlich hier meine Gui angezeigt.
Also hier scharf über Zaun. Wenn ich jetzt an diesem Zielwerkzeug sage,
ist Z-Zähler und setze jetzt diesen Ereigniszähler da rein dann wäre es schön,
wenn in dem Moment tatsächlich sich da oben die Oberfläche auch ändern würde.
Also wenn da tatsächlich das aktualisiert würde, mal gucken,
wie ich das jetzt mache, dann ist das hier
immer noch scharf über Zaun und nicht irgendwie jetzt Norris rettet die Welt.
Also irgendwie haben wir jetzt zwar das Material geändert,
aber das Werkzeug reagiert darauf noch nicht.
Okay, also werden wir jetzt das mal da reinbauen,
in das Werkzeug, das ist darauf reagieren kann,
dass das Material jetzt sich geändert hat.
Das heißt, ich möchte ja eigentlich jetzt an dieser Stelle
der Gui sagen, zeig mir was Neues an.
Ich möchte also eigentlich, das Mandianer-Prinzip,
ich weiß nicht, ob ihr das Mandianer-Prinzip kennt,
habe ich vielleicht schon mal ein SE1 erzählt.
Ich schreibe das hin, was ich jetzt machen möchte.
Also ich möchte jetzt sagen, okay,
ich als Werkzeug habe jetzt ein neues Material anzuzeigen.
Meine Gui zeigt mir das alte Material an.
Dann sage ich jetzt einfach mal, aktualisiere UI.
Diese Methode, die möchte ich
jetzt aufrufen
Toll. Gibt's nicht, muss ich schreiben. Okay,
ich schreibe hier mir eine private Hilfsmethode, aktualisiere UI.
Okay. Und was macht die? Naja,
die setzt eigentlich jetzt nur, nachdem das Material neu gesetzt ist,
die ganzen Elemente bei der UI neu.
So, das ist jetzt ein bisschen blöd. Jetzt habe ich
ja diese ganzen ganzen Gui-Elemente gar nicht. Und jetzt fange ich halt an,
und das ist dann wieder da, wo es dann,
sagen wir, so ein bisschen hässlich wird,
wenn man mit diesen trennten Klassen umgeht,
aber es macht es eben halt an vielen Stellen auch wieder einfacher.
Jetzt muss ich, möchte ich eigentlich sagen können,
gib mir doch mal den Label. Ich kann also
meiner UI sagen, unterstrich UI, Get, Zeitlabel.
Und an dem möchte ich jetzt irgendwie Set-Text aufrufen, Set-Text.
Und jetzt tatsächlich wieder das Gleiche, was da oben steht.
Also Zähler, Get-Ereigniszeitpunkt. So, Das heißt,
was ich jetzt hier schreiben muss, ist relativ hässlicher Code.
Ich lasse mir jetzt mit einem Get-Zeit-Label von der UI erstmal
diesen Label geben und man könnte es auch anders machen.
Man könnte auch an der Schnittstelle von der UI jetzt sagen,
ich kann das da auch reinsetzen.
Ich kann also diesen Erzeugungszeitpunkt neu setzen. Ist jetzt hier,
ich baue es jetzt einfach mal so,
was ich tatsächlich auch machen könnte, auch nur,
dass ihr einfach mal diese Entwurfsunterschiede seht.
Ich habe jetzt genau die Situation, ich habe irgendwie eine Klasse,
die hat die ganzen Gree-Elemente und eine andere möchte jetzt da irgendwas ändern.
Jetzt könnte ich tatsächlich hier auch eine Methode schreiben,
die diese ganzen Strings einfach neu übergibt
Auch das könnten wir einfach jetzt mal so machen.
Ich könnte also jetzt mal in der UI hier diese Methode bauen,
also sowas wie am Public Sätze, Inhalte, neu,
was weiß ich.
So, jetzt werden hier genau die Dinge übergeben.
Also genau das hier wird jetzt hier unten auch übergeben
So. Und was dann passiert ist, mehr oder weniger genau das,
was man da auch erwarten würde, dass dann tatsächlich hier,
ich kopiere das einfach mal, also Zeitlabel,
ach nee, das kann ich nicht machen,
also ich muss tatsächlich jetzt hier auf die Dinger zugreifen,
also sage ich zum einen, am Frame Set,
Title, kann ich neu setzen mit dem Titel,
der übergeben wurde,
müsste eigentlich
so gehen
Public Void, ja, ich bin jetzt hier so
ein bisschen am Improvisieren, setze Inhalte neu, Frame,
Set-Peitle, ja, lässt sich übersetzen.
Also ich kannte bei dem Frame den Titel neu setzen.
Ich kann sagen, Zeit-Label, ups, Label,
Set, Set, Text, Zeit, lässt sich übersetzen.
Und was war das letzte Zähler, genau.
Zähler, Set, Text
Wert. Lässt sich übersetzen. Und jetzt habe ich also Sätze,
Inhalte neu in dieser Klasse hier gebaut und benutze das jetzt
einfach hier in meinen Dings, indem ich sage,
ja, also jetzt UI nicht Get Label, sondern Sätze,
Inhalte neu.
Und jetzt muss ich hier wieder diesen ganzen,
das ganze Gehubere übergeben. Also Ereignisart, Erzeugungszeitpunkt und Zählerstand
. Mache ich gerade einen Fehler? Achtet jemand darauf,
was ich mache
Einfach mal probieren, ob das hier funktioniert.
So. Ah, okay, hast ja recht. Ist auch
meine private Methode hier. Das könnte ich wahrscheinlich jetzt auch,
muss ich gar nicht mit dieser Methode machen.
Ich habe jetzt eine, so, keine Fehler als Ereignisart,
dann der Erzeugungszeitpunkt. Ah, dann müssen wir gucken,
da habe ich wieder genau das Problem,
dass ich möglicherweise die Reihenfolge jetzt umgeändert habe.
Titel, Zeit und Wert. Nee, das passt.
So, das kann ich jetzt nochmal probieren.
Also ich mache nochmal hier meine Ereignisdinger hier.
Norris und nochmal ein Ereignis
Mit Schaf. Und dann gebe ich jetzt hier den Ereignis
Zielwerkzeug rein. Zuerst den ersten, Norris, wunderbar.
Jetzt sage ich bei dem Zielwerkzeug, Sed Zähler,
setze den Zähler rein und siehe da,
es ist jetzt scharf, über Zaun.
Hat sich also tatsächlich geändert. Wunderbar. Ich kann also
jetzt an meinem Werkzeug das Material neu setzen.
Ich weiß, das war jetzt ein bisschen langweilig,
aber wir wollen ja letztendlich noch auf was anderes hinaus.
Nämlich, wir wollen ja gleich hier als nächstes jetzt
dafür sorgen, dass tatsächlich das Material verändert wird
Okay, ich würde sagen, das ist ein guter Moment für
eine kurze fünfminütige Pause. Es geht weiter. Ja,
wir haben noch ein bisschen Zeit, das ist gut.
Ich habe auch noch ganz schön was vor heute.
Ich bin irgendwie nicht sehr weit gekommen bis jetzt,
weil ich zu viel gequatscht habe. Was wir jetzt hier sehen ist,
wenn ich das jetzt mal übersetze und das Start-up aufrufe,
das Main hier, dann habe ich hier mein Werkzeug und kann jetzt hier irgendwie drauf klicken.
Aber was natürlich jetzt fehlt ist, da ist noch eine Frage.
Ah, der Freeze ist noch an, ne?
Ja, mein Lieblingsfehler. Also hier Ich habe jetzt einfach
noch mal in dem Budget-Projekt noch mal neu übersetzt und habe mir dann hier noch mal Main aufgerufen,
also sozusagen mir hier mein Exemplar erzeugt und kann jetzt hier klicken.
Und so was jetzt irgendwie, sagen wir,
das Besondere ist an solchen grafischen Benutzungsoberflächen ist,
der Code, der den Button dazu bringt,
dass der hier so sich irgendwie seinen, ja,
auf dieses hier so aktualisiert wird und dass man da,
das ist ja Code, der ist in der Bibliothek abgelegt.
Das ist uralter Code, der kann schon vor 10,
vor 15 Jahren geschrieben worden sein, dieser Code.
Aber was ihr wollt, ist, dass jetzt,
wenn da drauf geklickt wird, euer Code aufgerufen wird.
Das heißt also, alter Code soll einen neuen Code aufrufen,
Und wie das geht, das ist jetzt sozusagen der nächste Schritt. So,
und wenn man so ein bisschen auf die Geschichte der Datenverarbeitung guckt,
ja, so ein bisschen ausholt, dann gab das früher diese Computersysteme,
da war es einfach so, man hat eine Eingabe, verarbeitet das und liefert eine Ausgabe.
Das ist auch eine klassische Sichtweise in der Informatik,
also sämtliche Algorithmen basieren immer auf dieser Idee ja Eingabe für den Algorithmus,
Verarbeitung und dann Ausgabeergebnis des Algorithmus.
Das war tatsächlich früher so auf textuellen Oberflächen von irgendwelchen Mainframes und das heißt,
dieses prinzipielle Struktur war eigentlich immer so lange Ich noch nicht fertig bin mit meinem Job,
lasse ich mir den Input geben, verarbeite den und liefere irgendwelchen Output.
Irgendwelche Dinge, die hier gemacht werden.
Also der Vorteil ist an so etwas,
dass die vollständige Kontrolle des Programms beim Anwendungsentwickler liegt.
Also ihr wisst, was wann passiert. Ihr könnt also
sehr effiziente Programme entwickeln. Aber der Nachteil ist,
es gibt eigentlich keine Anleitung für die Trennung von fachlichem und grünspezifischem Code.
Also das, was wir eigentlich wollen,
dass man die Gui irgendwie sauber trennt von der eigentlichen Fachlichkeit
Und der Austausch der Oberfläche ist dann auch tendenziell schwierig,
wenn ich so etwas hier mehr oder weniger
selbst programmiere und dann irgendwelche grafischen Oberflächen da mit triggere.
Das heißt, was wir eigentlich wollen, sind solche Systeme wunderbare alte Folie.
Also uralter Mac-Oberfläche. Da ist es tatsächlich anders.
Da ist es nicht so, dass man jetzt weiß,
das Programm läuft, sondern was hier läuft, ist das Betriebssystem.
Und es wird reagiert auf irgendwelche Klicks. Und
wenn dann zum Beispiel auf dieses Ding hier geklickt wird,
dann heißt das, aktiviere jetzt mal irgendwie den Terminplaner.
Das heißt, wir haben hier eine reaktive Oberfläche
Und wir wissen aber bei so etwas auch überhaupt nicht,
was jetzt als nächstes passiert. Das heißt, es muss irgendwie so
ein Ereignis verarbeitet werden und dann muss irgendwas angestoßen werden.
Das heißt, es gibt hier keine festgelegte Reihenfolge,
in der der Benutzer irgendwas tun muss.
Und das ist auch tatsächlich ganz zentral für reaktive Software.
Das heißt, die Steuerung des Kontrollflusses liegt außerhalb in diesem Fall jetzt unserer Kontrolle.
Wir schreiben hier irgendwelchen Code. Wir wissen aber nicht,
wann der ausgeführt wird, weil wir wissen ja nicht,
wann da wirklich auf den Button geklickt wird.
Also auch eben schon, dass wir dieses Enden des Materials,
wir wissen nicht,
wann das passiert
Das heißt, was wir auch gar nicht wissen müssen momentan,
wenn ihr tiefer in diese Materie einsteigt,
dann werdet ihr das sicherlich euch auch mal genauer ansehen.
Aber erst mal müsst ihr nicht wissen, wie funktioniert das eigentlich,
dass da jetzt irgendein Klick auf der Oberfläche abgebildet wird in den Code.
Das ist komplett in dem Greenframework gekapselt. Ihr könnt es euch tatsächlich so vorstellen,
dass es in dem Swing-Framework irgendwo eine Schleife gibt,
die ganze Zeit nichts anderes macht, als abzufragen,
ob der Benutzer irgendetwas tut an der Oberfläche und dann geeignet versucht dann,
das weiterzuleiten an die Objekte,
die es interessiert
Das heißt, wir werden uns jetzt hier quasi als Beobachter an die Oberfläche ranhängen wollen.
Das heißt also, jetzt kommt hier tatsächlich auch das Beobachtermuster zum Einsatz.
Und wir können diese Trennung, die geforderte Trennung sehr viel leichter vollziehen. Okay,
Nachteile ist natürlich, man muss sich in diese Gui-Bibliotheken einarbeiten,
man muss dieses Grundverständnis haben,
dass da sozusagen die Kontrolle über das, was da passiert,
erst mal im Gui-Framework liegt, eine zentrale Steuerung.
Das heißt also, genau das,
was ich schon gesagt habe, es läuft irgendein System-Code,
ein Gui-Code, der darauf wartet, dass irgendwas passiert.
Und dann, wenn hier etwas geklickt wird,
dann soll ja mein eigener Code
aufgerufen werden
Okay, was da letztendlich passiert ist, dass Ereignisse verarbeitet werden,
also diese Dinge werden dann auch Ereignisse genannt.
Das heißt, jede Mausbewegung, jeder Mausklick und
jeder Tastendruck wird vorm System gut an der Gui registriert.
So, es ist tatsächlich jetzt so, dass ihr
euch das auch klarmachen müsst. Also es gibt Window-Systeme,
da ist es so,
wenn ich mit der Maus aus diesem Fenster rausfahre und hier wieder reinfahre,
das ist ein ganzer Strom von Ereignissen.
Also es kann also sein, dass man, die kann man auch abfragen.
Also ich kann tatsächlich jetzt in Swing auch fragen,
ist die Maus jetzt über meinem Fenster oder nicht?
Gibt es ein Maus-Enter, gibt es ein Maus-Out,
das kann man
alles abfragen
Die können eben, wie gesagt, sehr elementar sein,
Mausbewegung, oder die können sich aus mehreren Aktionen zusammensetzen.
Ein Mausklick zum Beispiel besteht aus den Aktionen,
Mausenhoff gedrückt, man macht es noch wieder losgelassen.
Und es gibt einen Entsprechenden dann für bestimmte Gui-Komponenten, so High-Level-Events,
eben die, die typischen Aktionen auf einer Komponente modellieren.
Das heißt, ich habe hier meinen Button und das
hier ist ja Maus runter und Maus wieder losgelassen.
Das ist tatsächlich ja jemand, man sieht das sogar auch
richtig schön, dass das ja klar getrennt ist.
Und das kann man aber als ein High-Level-Event auch abgreifen.
Also man kann da sozusagen
das beobachten
Ein solches Event wird an alle Teile des Anwendungssystems verschickt,
die sich für diese Aktion bei einer Gui-Komponente angemeldet haben.
So. Das heißt, diese Anbindung an die Oberfläche erfolgt,
dass man dadurch, dass da Ereignisse ausgelöst werden und dann kann,
jetzt können wir in unseren Code sogenannte Listener implementieren.
Man kann also, das ist im Grunde genommen,
wie gesagt, das Beobachtern musste,
aber eigentlich heißen die Dinger bei den grafischen Oberflächen dann gerne Listenern.
Durch diesen Benachrichtigungsminister kann die Oberflächenkomponente von der Applikation verwendet und
die Applikation von der Komponente benachrichtigt werden
Ohne, dass es eine direkte zyklische Benutzbeziehung gibt.
Die kann es ja gar nicht geben,
weil die Gummi-Komponente kennt ja unseren Jahre später geschriebenen Code gar nicht.
Und ohne, dass die Komponente auch alle ihre Listen ja
explizit kennen muss. Also genau diese Entkopplung,
die Guido auch beim Beobachter muss da letzte Woche erzählt hat.
Damit Anwendungscode vom System gut aufgerufen werden kann,
muss der Anwendungsgrund eine Schnittstelle haben, die dem System bekannt ist.
Das heißt, wenn ich jetzt eine Methode schreibe,
wie reagiere auf Änderung, dann wird dieser Gummi-Code das nicht aufrufen können.
Aber wenn ich ein Interface implementiere, dann kann tatsächlich die
Gummi-Komponente irgendetwas aufrufen, was hinter diesem Interface steht.
Das heißt, Ein Beispiel, was ist hier,
was wir uns jetzt generell ansehen werden, ist der genannte Action-Listender.
Sein Interface mit nur genau einer Methode, nämlich Action performt.
Und da wird dann als Parameter ein Action-Event übergeben.
Und das ist die Schnittstelle, die Gui-Komponenten kennen.
Die wissen, es gibt Action-Listender und ich kann mich selbst
als Action-Listender implementieren und dann auf diese Ereignisse lauschen.
Also wird hier im Anwendungscode geschrieben, der das dann tatsächlich macht.
Da steht dann das Action performt drin
Also, wenn also jetzt ein eigenes Eintritt auf einem Button zum Beispiel,
dann erzeugt die Komponente ein Eventobjekt und da gibt es
als Parametern alle Listen da.
Also man kann es ja so vorstellen, wir schreiben unsere Anwendung,
wir sagen einen Teil unserer Anwendung implementiert dieses Interface-Action-Listender.
Und unter anderem haben wir diese Implementation, unsere Reaktion auf Action performt.
Dann erzeugen wir in der Anwendung einen Button und fügen einen Action-Listener hinzu,
nämlich tatsächlich hier irgendwie den Code,
der hier das implementiert
Das ist sozusagen zur Übersetzungszeit, da bauen wir das so.
Jetzt gibt es zur Laufzeit, wenn das System läuft,
gibt es einen Klick auf den Button,
der erzeugt ein Action-Event und ruft an seinem Action-Listener hier das Action performt auf.
Und dann wird dieses Action-Event übergeben. Und dann kann eben
halt tatsächlich hier in der Implementation auf diesen Button-Click reagiert werden.
Und das passiert in Java, üblicherweise, man muss es
nicht so machen, aber üblicherweise mit anonymen inneren Klassen.
Das ist ein ziemlich spezielles Konstrukt von Java
Dass wir jetzt an dieser Stelle einfach mal kennenlernen.
Damit kann ich an der Stelle, an der ich ein Exemplar einer,
das Interface implementierenden Klasse übergeben muss, direkt ein solches Ding erzeugen.
Ich habe also tatsächlich jetzt hier an meinem Button,
kann ich sagen, Ad-Action-Listender, übergebe jetzt ein Exemplar einer Klasse,
dass dieses Action-Listender-Interface implementiert. Und ich muss das nicht,
ich muss nicht extra eine eigene Klasse schreiben,
die das implementiert und so weiter,
sondern kann hier on the fly etwas tun, nämlich,
dass hier ein Exemplar von dieser Action, ein Exemplar,
einer anonymen Klasse erzeugt wird,
die dieses Interface implementiert.
Da ist eine Frage
Ja, kann man so was setzen, einer Repode
beispielsweise in einem Kostrukt bei einer Klasse gemacht wird.
In dem Fall, dass Action performt, aufrufen soll,
so eine komplexe Wolkenoperation durchgeführt werden kann.
Das ist eigentlich sehr schnell sehr unübersichtlich werden,
weil Jets führen. Also was er fragt ist,
kann das nicht sehr schnell unübersichtlich werden,
wenn man sehr viele von diesen Actionlisten dann irgendwie in seinem Quelltext erzeugt,
zum Beispiel im Konstruktor und so weiter.
Ja, das kann durchaus passieren. Das ist das Unangenehme an Software.
Sie ist sehr schnell, sehr unübersichtlich. Deswegen gibt es
unter anderem unsere Entwurfsregeln, wo wir halt auch versuchen,
klar zuzuordnen, wo denn so was passieren wird.
Ich kann ja jetzt mal das hier mal reinbauen in unsere tolle Klasse.
Ich möchte jetzt in meinem Werkzeug reagieren können, wenn da Debatten geklickt wird.
Wie kann ich das tun? Ich schreibe mal wieder eine
Methode, eine Namen Methode, nach dem Manjana-Prinzip.
Das ist registriere Lissender. Das ist etwas,
was man üblicherweise in so einem Werkzeug schreibt.
Eine Methode, die das tut. Und das ist jetzt
hier mal wieder eine private Methode, privat mit Private,
Vood, registriere Listener.
Was ich jetzt brauche, ist Zugriff auf den Button.
Hier habe ich keinen Button. Blöd. Also gehe ich
in die UI-Klasse, ganz pragmatisch, und baue hier einen Ghetter.
Public, J. Button, ob es get button,
sodass jetzt meine Werkzeugklasse von der UI-Klasse
den Button bekommen kann,
also Return-Button
Kann ich hier so bauen? Jetzt kann ich wieder in
meinem Zählwerkzeug an dieser Stelle sagen, UI, Get Button.
Und jetzt kann ich hier sagen, at Action, Listener.
Das ist also mehr oder weniger genau das,
was jetzt auch auf der Folie steht hier.
My Button at Action Listener. Und jetzt mache ich mal
genau das, was da steht. New Action, Listener,
Klammer auf, Klammer zu. Und Simicola an. Das heißt,
das ist der eigentliche Aufruf, ja, Ad-Action-Listner,
hier ist die Runde Klammer auf, für die Parameters,
die hieß die Runde Klammer zu.
Dazwischen habe ich jetzt hier etwas, was Lucia ja auch
grün hervorhebt, also ein Klassenrumpf wird ja grün hervorgehoben.
Also man sieht hier, der gesamte Klassenrumpf ist grün.
Und was hier passiert ist tatsächlich, man definiert an dieser Stelle eine Klasse.
Eigentlich definiert man eine Klasse und sogar gleich ein Exemplar davon.
Es wird also gleich ein Exemplar von dieser anonymen Klasse erzeugt.
Naja, was muss ich jetzt hier schreiben?
Ich muss hier schreiben, Public, Void,
Action performt, glaube ich,
heißt das Ding
Ein Action-Event. AE. So, und jetzt kann ich hier
irgendetwas tun. Ich weiß nicht, ob das geht.
Aha, cannot find simple class action missender.
Mhm. Also schreibe ich jetzt hier mal Import, Java,
AWT oder Swing? AWT Event. Punkt. Stern.
Ja, lässt sich übersetzen, genau. Das heißt,
Action listener ist etwas aus einem Subpaket von AWT,
nämlich Event hier
So, jetzt kann ich also meinen Actionlisten da hier so hinschreiben.
Kann ja also tatsächlich, das ist ein Interface.
Und jetzt, was will ich jetzt machen?
Was will ich jetzt machen? Was soll jetzt passieren?
Was ist jetzt sinnvoll, was jetzt hier passiert an der Stelle,
wo ich das Ereignis abgefangen habe, der Button wurde geklickt, ja?
Genau, wir wollen jetzt, dass in der Oberfläche ist irgendwas
gemacht worden, wir wollen jetzt das Material möglicherweise manipulieren.
Also kann ich jetzt hier hinschreiben, Zähler, Punkt,
was können wir jetzt
hier machen
Hashcode, Notify, registriere Ereignis, das wollte ich sagen.
So, wunderbar. Das ist das eine. Okay,
jetzt ist die Frage, reicht das jetzt aus?
Jetzt ist sozusagen das Material verändert worden. Was muss jetzt noch passieren?
Ja. Genau, jetzt haben wir das Material geändert.
Die UI weiß es aber nicht. Also,
Kann ich hier jetzt, an dieser Stelle,
an der ich jetzt sage, naja,
da ist jetzt was passiert, kann ich sagen, aktualisiere UI.
Die habe ich ja zum Glück schon geschrieben.
Mal schauen, ob das jetzt funktioniert.
Das wäre ja natürlich sensationell, das funktionieren würde.
Also, hier, Norris rettet die Welt,
registrieren.
Wow. Toll
Also tatsächlich, wir können hier jetzt hier hochzählen und jetzt könnten wir womöglich so noch austesten,
ob wir das Material austauschen könnten, brauchen wir jetzt nicht machen.
Okay. Anonyme innere Klassen, das ist etwas,
was ich im Kontext von geschachtelten Klassen schon mal erwähnt habe,
ja, es gibt in Java das Konzept von geschachtelten Klassen,
es gibt eine Art von geschachtelten Klassen,
da sind die statisch geschachteten Klassen.
Alle anderen werden innere Klassen genannt. Und innere Klassen haben die Eigenschaft,
dass sie immer ein Exemplar der umgebenden Klasse benötigen.
Man kann sich das wirklich vorstellen wie so ein Parasitobjekt,
das ein Wirtsobjekt benötigt
Das heißt also tatsächlich hier in diesem Fall,
in dem ich in diesem Code hier,
in dem Zielwerkzeug, dieses Exemplar hier erzeuge,
hat dieses Exemplar automatisch eine Referenz auf das Zählwerkzeug.
Das Zielwerkzeug ist das Wirtsobjekt und dieses anonym erzeugte Objekt ist das Parasitobjekt.
Und das ist auch ein sehr enges Verhältnis.
Ich kann zum Beispiel jeweils private Methoden aufrufen.
Haben wir das sogar hier gesehen gerade, in dem Code?
Ich habe hier aktualisiere UI aufgerufen, das ist eine private
Methode,
konnte ich aber aufrufen
Aus meiner anonymen Klasse hier. Also sehr freundlich miteinander. Das ist wieder so ein Spezialfall,
wenn da jetzt eine lokale Variable ist in der Methode,
dann kann ich da nur zugreifen, wenn die Final ist.
Das sind so Probleme, die werdet ihr merken,
wenn ihr das mal programmiert. Gut,
dann einfach jetzt nochmal so ein paar weitere Listener-Interfaces,
also zum Beispiel bei einem J. Radio-Button,
da gibt es eben nicht nur die Möglichkeit zu sagen,
ich möchte darauf reagieren, dass der geklickt wird,
sondern ich könnte auch sagen, ich möchte wissen,
welcher von denen jetzt,
also wenn sich dieses bei einem Radio-Button die Auswahl geändert hat,
Bei einer Jaillist, nicht nur,
ob ein Doppelklick gemacht wurde, ob ein Listeneintrag,
sondern auch, ob überhaupt ein Element in der Liste selektiert wurde.
Bei einer Combo-Box ist irgendwie das Item selektiert worden und so weiter.
Also das sind so alles so verschiedene Listener,
die man als Interfaces benutzen kann und sich bei den verschiedenen Komponenten dann auch registrieren kann.
Zu jedem gibt es da noch eine Eventklasse, also diese Event-Objekte,
das, was ja hier auch übergeben wurde, dieses Action-Event,
die tragen dann auch alle möglichen Informationen über das Ereignis mit sich.
Da kann man teilweise dann sogar auch noch so ein Consume aufrufen,
um zu sagen, ich habe das Ereignis jetzt verarbeitet.
Hier noch so ein paar mehr davon, also Focus-Event,
gibt es den Focus-Listender, Focus-Game, Focus Lost,
was ich eben erzählt habe,
aus dem Fenster raus und wieder ins Fenster rein.
Item, state changed und so weiter. Gibt es also
eine ganze Menge, das ist nur hier,
um euch mal so einen Eindruck zu geben.
Was haben wir jetzt gesehen? Mechanismus ist hier der sogenannte
Event-Event-Listender-Mechanismus, allgemein so aufgebaut. Jede Greek-Komponente implementiert eine bestimmte
Art von Ereignissen, wo man dann Ad-Event-Listender aufrufen kann.
Über diese Methode kann an einer Greek-Komponente ein Objekt angemeldet werden,
welche das Interface-Event Lister implementiert, wird ein Ereignis durchgeführt,
dann werden alle benachrichtigt
Fine. Also, eine Juri-Klasse, eine UI-Klasse stellt die
für ihre Wechselklasse relevanten Elemente zur Verfügung. Das haben wir
gerade gesehen, den Button mussten wir mit einem Ghetter rausgeben,
damit wir dann den Button uns anmelden konnten.
Die Werkzeugklasse erzeugt für diese UI-Wichard Listener,
die passende Aktionen ausführen und registriert diese an den Widgets.
Und die Werkzeugklasse gibt die anzuteilende Materialien oder Fachwerte in die UI in folgender Weise.
Die Werksackklasse holt sich das, das Witch und setzt dann die entsprechenden Informationen.
Das haben wir jetzt anders gebaut. Wir haben jetzt irgendwie gesagt,
wir haben in der Werkzeugklasse gleich mehrere Labels auf einmal gesetzt.
Man kann das auch so machen, dass man sich die
ganzen Elemente rausgeben lässt und es von Hand setzt.
Gut, sehr schön, wir haben noch zehn Minuten mindestens
für Layout, Layout-Manager, eine ganz tolle Sache.
Was wir jetzt hier gerade gesehen haben,
ist, dass das Ding zwar läuft,
aber jetzt kann ich ja hier das Fenster mal größer ziehen.
Also zum Beispiel in die Breite, in ihr seht,
diese Komponenten bleiben in der Mitte. Wenn ich das jetzt
hier nach unten ziehe, bleibt das aber oben kleben.
Also es geht nicht wirklich in die Mitte rein.
Dieses Verhalten ist festgelegt über einen Layout-Manager
Das ist etwas, was bei der Gui-Logik in Swing sehr speziell ist.
Es gibt durchaus grafische Benutzungsoberflächen, da ist das anders.
Da muss man also pixelgenau Dinge zeichnen und hat so diese
relativen Operationen nicht so komfortabel.
Das finde ich an Zwingen insbesondere relativ speziell und auch sehr attraktiv,
weil man dann eben vergrößern und verkleinern, auch festlegen kann.
Also wenn ihr zum Beispiel jetzt euch BlueJ anguckt,
wenn ich jetzt hier nach unten aufziehe, dann seht ihr,
dieser Teil verändert seine Höhe nicht oder wenn ich das hier breiter ziehe,
dann wird eben genau ein bestimmter Bereich
nur breiter gezogen
Und das kann man sehr schön mit diesen Layout-Managern steuern.
Und jeder Container besitzt als Default einen Layout-Manager.
Also zum Beispiel ein Jay-Frame besitzt als Standard-Lyout-Manager ein Border-Layout.
Ein J. Panel kann man hier setzen,
hat einen Riddlayout und einen J. Panel hat als Standard-Lyout-Manager ein Flow-Layout.
Das heißt, was ihr gerade hier seht,
in diesem Beispiel, ist ein Beispiel für ein Flow-Layout,
weil ich hatte ja bei diesem Jay-Frame als Content-Pain ein J. Panel gesetzt.
Und der J. Panel hat, wie man hier sieht,
Ein Flowlayer standardmäßig. Und das ist hier genau dieses Flowlayout.
Was man auch sieht, dass das Flowlayout,
das heißt auch Flow-Layout, weil die Elemente jetzt hier fließen.
In dem Sinne, wenn ich das jetzt schmal mache,
dann schwupp bricht das um und dann ist die Acht da unten.
Man kann also tatsächlich hier dafür sorgen, dass die untereinander liegen.
Kleiner geht es jetzt leider vom Windows nicht, weil sonst
die Elemente verschwinden würden. Aber man sieht hier,
das fließt sozusagen hier so vom Layout rein.
Das ist ganz hübsch. Jeder Container hat einen Layout-Manager,
den kann man setzen und abfragen.
Das haben wir eingangs gemacht mit dem Setlayout-Manager
Standard-Layout für den Content-Pangle ist ein Border-Layout. Wenn ihr ganz
fortgeschritten seid, dann könnt ihr auch eigene Layout-Manager schreiben.
Es gibt da schon einige von, und die wollen wir uns mal angucken. Also,
wenn ihr zum Beispiel euch noch erinnert an die Mediathek,
dann hatten wir da ja so diese vier Buttons,
wo man sagte, irgendwie ausleihsicht, Vormerk an sich und so weiter.
Das war ein klassisches Card-Layout. Wo man tatsächlich mehrere
volle Panels hat und dann sozusagen zwischen denen umschalten kann.
Das ist immer so wie dieses, wie auch mit so Reitern,
auch Tabs in Firefox oder so, sind so ein ähnliches Konzept.
Dann gibt es das Borderlayer, Flowlayer, Grid Law,
Grid Bag Layout, ganz viel Zeug.
Ich habe zufällig ein Blue Jay-Projekt dabei,
wo die mal so ein bisschen verwendet werden,
die ich jetzt mal hier so ein bisschen zur Veranschaulichung zeigen will.
Also, hier machen wir das Flowlayout-Beispiel. Ganz einfach,
ich habe hier wieder eine private Variable J Frame,
vom Typ J Frame, mach mir einen Frame,
Flowlay or buy Example und erzeuge mir hier,
setze den Content Pain,
nee,
lass mir den Content Pain geben
Und Sätze, genau, ersetzte ein Flow-Layout an dem Content-Pain.
Und dann mache ich hier jetzt, füge ich mehrere Buttons dazu.
Enemine, Mu und raus, bist du.
Das ist also ganz einfach. Und dann ein Frame.pack
on Frames Head Visible. Okay, also mal gucken,
wenn ich hier das Ding aufrufe, dann sieht das so aus.
Enemine Mu und raus, das haben wir eben schon gesehen.
Das ist dieses typische Flow-Layout. Ich kann das jetzt
hier kleiner machen. Und dann sieht man, dass das
hier sozusagen auch untereinander gestapelt wird. Okay,
was ganz cool ist, ich kann auch jetzt hier
sagen,
Flow-Set Alignment
Flow on that out left. Wenn ich das jetzt so übersetze,
dann kann ich tatsächlich hier noch mal mir so ein Exemplar erzeugen.
Dann sieht das so aus,
dass jetzt mich das breiter ziehe, dass links kleben bleibt.
Also nicht in der Mitte bleibt. Könnte ich auch genauso
mit rechts machen. Also man kann da mit verschiedenen Parametern
dann bei diesen Layouts das steuern.
Nächstes Beispiel das Border Layout, ziemlich häufig vorkommendes Layout.
Ich habe hier fünf Buttons, vielleicht zeige ich erstmal
den Quelltext
Wieder ein J. Frame. Ich setze hier
einen Layout-Manager-Border-Layout und füge hier diese fünf Buttons ein.
Und da muss ich eben halt mit so konstanten angeben,
in welche Komponente das Layout, das rein soll.
Also es gibt tatsächlich genau fünf Kinder für ein Layout hier.
Norden, Süden, Mitte, Westen und Osten.
Und genau das ist jetzt hier auch am Laufen gerade.
Und wenn ich jetzt hier das Ding größer ziehe,
dann gibt es ganz klar diese Semantik,
die Mitte kriegt immer den Platz.
Westen und Osten bleiben mit ihrer Breite gleich.
Süden und Norden bleiben in ihrer Höhe gleich.
Also der Platz geht meistens in die Mitte
Das ist relativ ähnlich zu dem, was wir hier von Blue Jack kennen.
Ja, und tatsächlich ist das wahrscheinlich irgendwie so eine Center-Dings.
Das ist wahrscheinlich irgendwie so eine Südgeschichte hier. Und die
kann man eben halt auch wieder schachteln. Man kann jetzt
auch innerhalb der Südkomponente wieder weitere Layout-Manager reinschachteln und so weiter.
Also da hat man ziemlich viele Möglichkeiten.
Und wie gesagt, der Standard-Layout-Manager von einem J. Frame,
der Content-Pain, hat üblicherweise diesen Layout-Manager im Border Layout.
Ich habe das am Anfang also geschummelt,
ich habe da erstmal so ein Flow-Layout reingesetzt,
damit man das sozusagen relativ leicht sehen kann,
wie gut das funktioniert
Mit Ed einfach mehrere reinschmeißen kann. Vielleicht nochmal den Unterschied
. Hier habe ich jetzt ein Ad mit zwei Parametern,
nämlich nicht nur, welche Komponente reingeworfen wird,
sondern auch, welches Layout sie haben.
Also in welchen Slot es rein soll. Okay,
was haben wir noch? Moment, Gridlayout. Das ist
dann ein Beispiel, ja, also hier wieder genauso.
Ich habe ein Gridlayout mit einem bestimmten Zellen und Spalten,
also drei Zeilen, zwei Spalten. Und dann mit Ad
werde ich jetzt einfach hier die sozusagen spaltenweise auf zahlenweise auffüllen.
Wenn man das mal anguckt, Grid Layout, da sieht
das so aus. Und wenn ich das jetzt größer ziehe,
dann kriegen die alle gleichmäßig Platz zugeteilt.
Damit kann man so Tabellen ganz schick formatieren. Und letztes
ist dann irgendwie das Box-Layout. Das ist dann so,
wenn ich da jetzt hier das größer ziehe,
dann ist das hier zum Beispiel zentriert, linksbündig.
Und es ist aber auch so, dass es nicht
wie beim Flow-Layout, das jetzt irgendwie fließen lässt.
Auch da kann ich jetzt wieder im Quelltext hier Set-Layout,
Content-Pain, also Box-Layout an der X-Achse auslegen.
Das war jetzt irgendwie horizontal. Ich kann stattdessen auch
sagen, mach's mal an der Y-Achse
Das jetzt übersetze, dann Broxlayout, das gleiche Beispiel,
die gleichen Elemente jetzt, hier entsprechend horizontal, vertikal angeordnet.
Und auch da wieder, die bleiben da irgendwie da oben links in der Ecke kleben.
Das sind halt alles dann Dinge, die kann man mit Parametern steuern.
Das ist einfach nur, dass ihr es mal gesehen habt.
Da gibt es eine ganze Menge Zeug. Das Gridback-Layout,
das ist eines der anspruchsvollsten und auch kompliziertesten Layouts.
Da wird es dann schon ein bisschen haarig.
Da kann man mehr oder weniger sehr fein granular da steuern.
Das haben wir jetzt gesehen. Naja, zum Beispiel Flow-Layout,
Werkzeugkonstruktion, Layout, das ist ganz wichtig.
Das ist jetzt wieder genau diese Frage,
wo Kümmert man sich denn jetzt darum, um dieses Layout?
Naja, in der Gui-Klasse. Das heißt,
die UI-Klasse eines Werkzeugs hat die Aufgaben,
die Gui-Komponenten zu erzeugen, zu layouten und zu verwalten.
Also alles, was mit Layout zu tun hat,
ist in der UI-Klasse zu finden.
Gut, jetzt haben wir schon mehr oder weniger zusammengefasst,
was wir heute gesehen haben. Also grundlegende Techniken zur Konstruktion,
reaktive Programme, reaktiver Programme in einer Gui-Bibliothek kennengelernt.
ABT und Swing. Es gibt sehr unterschiedliche Gui-Komponenten. Listener
sind so die zentrale Möglichkeit, wie man dafür sorgen kann,
dass Anwendungscode von Ereignissen informiert wird,
die in der Oberfläche stattfinden
Layout kann man sehr flexibel auch gestalten.
Und jetzt können wir unsere ersten Desktop-Anwendungen konstruieren.
Dann die Entwurfsregeln jetzt nochmal. Wir haben also gesehen,
Entwurfsregeln definieren vier Elementtypen, Materialien, Fachwerte, Services, Werkzeuge.
Der Entwurf von Materialien, Fachwerten und Services ist primär fachlich anspruchsvoll.
Also was machen die Dinge? Was haben die für Schnittstellen?
Während die Konstruktion von Werkzeugen, das haben wir jetzt gerade gesehen,
diese Gui-Hudelei, das ist eher technisch anspruchsvoll,
dafür muss man sehr viel von der Technik verstehen.
So, jetzt haben wir noch ein bisschen Storesi zum Schluss
Ich hoffe, ihr habt euch alle Klicker genommen, beziehungsweise eure Geräte bereit.
Ich habe hier nochmal eine kleine Umfrage für euch.
In welcher Klasse sollte nach den SE2-Entwurfsregeln die Entscheidung
zu finden sein, wie auf einen Buttonklick reagiert wird?
A, in der UI-Klasse eines Werkzeugs,
B in der Werkzeugklasse eines Werkzeugs,
C in der Materialklasse des zu verändernden Materials oder D
in dem Service,
der das Material verwaltet
Musik Wahnsinn, fast 50 Stimmen? Ja,
50 Stimmen. Ich glaube, es reicht erst mal.
Zack. Wir gucken mal, wie so die Meinung aussieht.
Okay. Also, Immerhin 65 Prozent sind der Meinung,
das sollte in der Werkzeugklasse des Werkzeugs passieren.
Wäre heute aufgepasst hat, der hat gesehen,
dass es auch da passiert ist.
Das ist also auch die richtige Antwort. In der UI-Klasse
haben wir gesagt, da werden die Gui-Elemente nur verwaltet.
Zusammengefasst, das Layout wird kontrolliert, aber was passiert,
wenn wirklich was geklickt wird? Das soll in der Werkzeugklasse
verwaltet werden. Und in der Materialklasse und in dem Service,
na gut, da kann man natürlich argumentieren,
da passiert möglicherweise final dann wirklich irgendwas.
Da musst du irgendwas geschehen. Aber das war in
diesem Fall jetzt nicht das,
was hier gefragt war
Also die Entscheidung darüber, wie wird denn reagiert darauf?
Dass dann eventuell an einem Service, was aufgerufen wird,
ist sozusagen dann erst der nachgeordnete Gedanke.
Okay. Welche der folgenden Aussagen ist für Java falsch?
Also A, die Klasse J. Button implementiert das Interface Actionlisten,
ne? B, ein J-Frame kann eine Menüleiste anbieten.
C, die Swing-Komponenten setzen teilweise auf den AWT-Komponenten auf.
Oder D, ein J-Button kann deaktiviert werden
Musik Na gut. Fast 50 Stimmen.
Na, könnt ihr
nicht entscheiden
Okay, 50 Stimmen. Ich halte an. Erstmal die
Verteilung angucken. Okay. 60 Prozent sagen die Klasse J. Button
implementiert das Interface Action-Listen, da ist eine falsche Aussage.
Und das ist natürlich auch richtig. Also sehr gute Ergebnisse
bisher. Einige Leute haben gesagt, es ist falsch,
dass ein J. Button deaktiviert werden kann.
Das haben wir aber auch jetzt hier gerade nicht gezeigt.
Das ist richtig, dass es nicht sichtbar war,
aber ihr kennt es ja aus der Mediathek,
dass man einen Button durchaus deaktivieren kann
Dass man ihn nicht mehr klicken kann, so ausgrauen.
Und die Swing-Komponenten setzen tatsächlich teilweise auf den ABT-Komponenten auf.
Und ein J-Frame kann eine Menüleister anbieten.
Das ist in BlueJ zum Beispiel so, habt ihr gesehen?
Prima, das war's für heute. Wenn nicht noch
Fragen sind, dann können wir Schluss machen.