So, wunderschönen guten Tag. Liebe Studierende zur Vorlesung,
acht, neun oder zehn. Ist auch wurscht.
Jedenfalls immer mittwochs. Ach, das Leben ist schön.
Die Sonne lacht. Willkommen hier im Auditorium und willkommen daheim.
Die Millionen, die uns an den Fernsehschirmen zu Hause verfolgen.
Ja, ich kriege manchmal Mails von Menschen,
die das zu Hause gucken und nicht zu dieser Veranstaltung gehören.
Da wundert man sich. Heute werde ich dem werde ich Ihnen
eine Dreiviertelstunde lang etwas über die Freuden der Programmierung von Graphical User Interfaces erzählen.
So, aus gegebenem Anlass haben wir uns dann entschlossen,
dass Fred und ich haben uns entschlossen, die Vorlesungen dann wieder zu teilen.
Das passt also mindestens für dieses Thema ganz gut und für
die verbleibenden Themen haben wir dann gesagt, wollen wir auch erstmal dabei bleiben.
In diesem Sinne, 45 Minuten, wie geht das prinzipiell,
Graphical User Interfaces programmieren mit den Unterpunkten, die sie dort sehen und dann 45 Minuten
Wie machen wir das mit Java anhand eines kleinen Beispiels?
So, Graphical User Interfaces ist so ein Thema,
das wird sie schätzungsweise ihr Berufsleben lang, wird sie das beschäftigen.
Sie sind nicht so naiv wie ich in ihrem Alter,
der ich so dachte, hm,
du kannst jetzt so Baskengeneratoren schreiben und also das wird im Interface ist eigentlich kein Thema mehr.
Das Thema ist durch,
da hatte ich mich aber sowas von schwer getäuscht,
weil also als ich in ihrem Alter war,
da gab es noch, war mit Internet,
war noch nicht so viel,
um nicht zu sagen
gar nicht
Die ersten grafischen Benutzungsoberflächen kamen dann so gerade in Mode,
solche Bildschirme. Also so groß ist ja nicht das Problem,
aber die waren dann auch noch so tief.
Also so Fernseher mit doch etwas höherer Auflösung. Und das,
was sich dann so langsam abzeichnete, war,
dass also die Technologien, mit denen grafische Benutzungsoberflächen implementiert werden,
mussten sich doch in einem Maße und in einem Tempo entwickelt haben,
dass man also kaum hinterherkam, sich daran zu gewöhnen,
wie wird das Zeug denn jetzt nun wieder programmiert.
Also von sogenannten Rich Clients, haben wir schon kurz in
der Vorlesung drüber gesprochen, über SIN-Clients. Das,
was heutzutage ja gang und gäbe ist, mobile Anwendungen,
die noch wieder mit anderen Anforderungen an grafische Benutzungsoberflächen daherkommen.
Also diese Technologiezyklen, insbesondere was die Oberfläche anbetrifft, sind kurz.
Demgegenüber fachliche Zyklen, ich will nicht sagen,
dass die kürzer sind oder länger, aber die haben so ihre eigene Dynamik.
Und das, was wir als Softwareentwickler-Typ interaktiver,
reaktiver Systeme typischerweise tun, ist, wir bauen ein Software-System,
das eine bestimmte fachliche Funktionalität hat das in irgendeiner Form grafisch repräsentiert wird.
So, wenn wir jetzt diese zwei Punkte zusammennehmen,
nämlich die Unterschiedlichkeit der Zyklen, in denen sich diese Gegenstandsbereiche verändern,
dann sind wir wohl beraten, das zu tun,
was da auf dieser Folie im Großen und Ganzen steht.
Trenne, Handhabung und Präsentation auf der einen Seite von der Funktionalität auf der anderen Seite.
Wenn wir alles zusammen in einen Monolithen implementieren,
dann werden wir Schwierigkeit, größere Schwierigkeiten,
als wir es sowieso schon haben,
werden wir größere Schwierigkeiten haben,
langlebige Softwaresysteme zu schreiben
Weil wir immer an allen Stellen auf jede sich,
auf jede Veränderung in der Umwelt reagieren müssen.
Also wollen wir diese beiden Anliegen voneinander trennen und so wie sie das hier sehen.
Wir haben ja so eine Architektur-Blaupause, die Werkzeuge, Services,
Materialien und Fachwerte unterscheidet. So im Großen und Ganzen kann man sagen,
das, was hier steht, ist richtig, nämlich,
dass die hier in diesem Bullet-Point genannten Modellelemente machen,
eigentlich keine Annahmen über ihren interaktiven Kontext oder überhaupt über ihren Kontext,
der kann interaktiv sein, der kann auch funktional sein.
Die Werkzeuge sind die Modellelemente, die jetzt mal so vorrangig
für die Präsentation und Handhabung der Funktionalität zuständig sind.
Also die unteren auf gar keinen Fall mit irgendwas vermengen,
was auch nur ansatzweise mit Oberfläche zu tun hat bei den Werkzeugen,
das sind genau die Modellelemente, die dafür zuständig sind.
So, jetzt nehmen Sie mal so ein Display wie das,
was ich hier habe, so und so viele Millionen Bildpunkte,
das womit Sie sich wirklich nicht beschäftigen wollen, jedenfalls,
wenn ich das mal so für mich sagen darf,
womit ich mich nicht beschäftigen will,
also jedes einzelne Pixel zu programmieren, das dargestellt wird,
wenn ich so unsere typischen interaktiven Anwendungen baue.
Womit ich mich auch nicht beschäftigen möchte, ist,
dass was hier jetzt passiert, wenn es denn passiert.
Ah, da ist sie. So,
hier werden jetzt vermutlich, werden jetzt also tausende,
zigtausende von Ereignissen, von der zugrunde liegenden Fenstersystembibliothek erzeugt.
Wenn man jetzt gleichzeitig nochmal so einen Monitor laufen lassen würde,
könnte man das wahrscheinlich sehen. So das,
was hier von der Fenster zugrunde liegenden Fenstersystembibliothek erzeugt wird,
werden dann wahrscheinlich so Mouse-Move-Events. Also einzelne Ereignisse,
die von dieser Bildschirm-Oberfläche so wahrgenommen werden müssen,
um also den Mauszeiger an der Position zu zeigen,
also auf die ich ihnen durch Bewegung auf dem Touchpad positioniert habe.
Für jemanden, der eine Anwendung baut, das ist jetzt die Frage,
muss ich mich dafür interessieren für dieses Ereignis viele Anwendungen,
die auf einem Bildschirm laufen, werden sich fragen,
ist dieses Ereignis für mich als Applikation interessant oder kann ich das ignorieren?
Diese Frage zu beantworten, dazu helfen die sogenannten Gui-Graphical-User-Interface-Tool-Kids,
die sind nämlich Abstraktionen über dem zugrunde liegenden Fenstersystem,
die es einem unter anderem auch erlauben für unterschiedliche Betriebssysteme,
dann grafische Oberflächen zu schreiben,
die dann auf diesem Betriebssystem
jeweils abgebildet werden können
Wir werden eine Ausprägung eines Graphical-User-Interface-Toolkits kennenlernen. Das ist das Swing-Toolkit.
Das ist ein für Java sehr verbreitetes Toolkit. Das ist nicht das modernste,
aber es ist für unsere Zwecke, ist es insofern besonders geeignet,
weil man dann vergleichsweise einfachen Zugang dazu bekommt und die Techniken,
die es braucht, um grafische Oberflächen zu programmieren, können mit diesem Toolkit ganz gut eingeübt werden.
Das werde ich jetzt, oh, jetzt geht's los.
Jetzt gibt es ein Novum in dieser Vorlesung
Ich werde ein Stück Java präsentieren. Nee, habe ich,
glaube ich, schon gemacht. Okay, das Novum ist,
ich werde ein Programm mit einer grafischen Oberfläche laufen lassen.
Die Spannung steigt jedenfalls bei mir. Was wollen wir zeigen?
Wir wollen, oder was wollen wir jetzt uns anschauen?
Wir wollen eine Applikation bauen, die hochmathematische Funktion Successor implementiert,
also den Nachfolger. Wenn man darauf drückt,
soll das da um eins hochgezählt werden. Und das,
was wir uns im Weiteren angucken werden, ist,
wie kommt dieses Wunder der Programmierung?
Wie kommt das zustande
So, und jetzt zeige ich das mal,
aber jetzt passiert jetzt echt wieder genau das.
Die Bruch, ach, du Scheiße, ich wusste es.
Irgendwas geht schief. Das ist das Problem, wenn man startet.
Das ist das Problem, wenn man im Trailer ist,
laufen kann. Trennung von Handhabung und Präsentation.
Ich glaube, das Ding ist so weit abgeschmiert.
Ich kann es noch nicht mal mehr Super, ey.
Okay, die Vorlesung heute dauert länger.
Nein, das war es auch nicht.
Das wollte ich jetzt
Finde Blue Jay nicht mehr.
Okay, ich gebe mir noch eine Minute.
Sieht jemand Blue Jay
Und du sagst, es stürzt ab,
wenn ich jetzt den Beamer reinstecke?
Auch nicht. Ich meine, ich hätte das auch
schon mal laufen lassen
Ah. Das haben sie jetzt nicht gesehen,
so schnell kam das, oder? Da ist sie.
Und es läuft. So, jetzt bitte ich Sie.
Ja, ist schon okay. Technik, die begeistert. So,
und jetzt bitte ich Sie mal ganz genau hinzuschauen, was ich tue.
Was habe ich jetzt getan? Ich habe die den Knopf gedrückt
Und jetzt halte ich ihn. Und jetzt lasse ich los. Ja,
jetzt, da, das erzähle ich Ihnen deswegen so mit großer Liebe zum Detail,
weil ich habe vorher jetzt auch schon wieder zwei, drei Jahre her,
dass ich einen Kollegen abends verabschiedet habe, in einer sehr merkwürdigen Körperhaltung.
Der saß nämlich so, saß der an seinem Schreibtisch und
den Finger hatte er über dem Ausknopf seines Rechners.
Und er wusste genau, er darf nicht loslassen,
solange nicht dieses Programm, das er liebevoll gestartet hatte,
bevor er dieses Programm beendet gewesen ist
Die Funktionalität des Drückens wird nämlich erst ausgelöst, wenn man loslässt.
So sind viele von diesen Knöpfen implementiert. Und ab jetzt kann niemand
mehr von Ihnen behaupten, das habe ich nicht gewusst.
Das ist nämlich gefilmt, dass ich Ihnen das jetzt erzählt habe.
Wir werden uns bei der Programmierung von Anwendungen,
werden wir uns also sehr genau überlegen müssen,
wann wird welche Art von Ereignissen, wann wir auf welche Art von Ereignissen reagieren.
Und wie wir darauf reagieren wollen. Es macht nämlich einen
feinen Unterschied und einen mitunter großen Unterschied, ob ich die Funktionalität erhöhen,
wie in diesem Fall ist es eher unkritisch,
ob ich die auslöse,
wenn der Knopf gedrückt ist oder ob ich sie auslöse,
wenn ich den Knopf loslasse.
Es könnte nämlich jetzt auch Folgendes passieren,
ich drücke den Knopf und denke, oh nein, bitte nicht.
Und jetzt nehme ich den zweiten Finger und bewege mich aus
dem Fokus des Fensters raus und jetzt wird das Button-Release-Ereignis nicht
mehr im Fokus dieses Fensters ausgelöst und jetzt lasse ich los
Es ist nichts passiert. So, das sind jetzt
so Entwurfsentscheidungen, die sie zu treffen haben.
Und jetzt mache ich es mal noch einen besser.
Jetzt passen sie auf. Ich bewege mich hierhin auf die
Kante. Shape der Maus verändert sich. Und jetzt,
wer von Ihnen studiert, MCI? Hallo, liebe MCIler.
Jetzt passt mal auf, was haltet ihr von diesem Verhalten?
Das ist doch Design, oder? Das fällt doch sofort auf,
dass ich mir total viel Mühe gegeben habe,
dieses Programm so zu schreiben, dass es bei verändertem Layout,
also sich angemessen repräsentiert.
Ich meine, gut, ich habe jetzt ein paar Jahre Berufserfahrung.
Deswegen fällt mir das leicht. Solche Applikationen,
also die Windeseile mit Blue Jay zu programmieren und wie man sieht,
also auch zum Laufen zu kriegen.
Aber das sind jetzt so Entwurfsentscheidungen, die,
wo viel harte Arbeit dahinter steckt, das ist jetzt nicht da.
Sondern das Zeug so zu konstruieren,
dass es nicht auffällt, dass jemand viel Arbeit in
das Design hineingesteckt hat
Weil schlechtes Design, das erkennt man sofort. Gutes Design,
jetzt sage ich soweit, so wenig ich davon verstehe,
wie man gerade sieht, zeichnet sich dadurch aus,
dass man gar nicht merkt,
dass jemand viel Arbeit da reingesteckt hat, sondern gleich denkt,
ja, das muss ja wohl so sein.
Noch nicht mal das sollte man denken, sondern es ist einfach,
das Werkzeug liegt gut in der Hand.
So, zurück zu den softwaretechnischen Grundlagen. Die Fragen des Tages,
sie sehen Sie hier, schwarz auf weiß an die Wand gemalt.
Welche Gui-Komponenten stehen uns in Bezwingen, aber dann auch in anderen Bibliotheken,
dass es davon eigentlich unabhängig zur Verfügung um solche Oberflächen zu konstruieren?
Wie kommen die mit unseren Applikationen in Verbindung
Und welche Möglichkeiten darüber hinausgehend habe ich um das Layout dieser Anwendung zu gestalten. So,
jetzt sehen Sie hier mal so ein paar von denen Gui-Komponenten,
die Ihnen zur Verfügung stehen,
über Swing, mit denen Sie Ihre Applikationen zusammensetzen können.
Ganz einfache Sachen wie Label, also Texte werden auf
die Oberfläche geschrieben, Buttons, verschiedene Arten von Knöpfen.
Ob das jetzt Checkbuttons, Radio, Buttons oder der normale,
landläufige Knopf sind, bis hin also zu etwas komplizierteren,
zu etwas komplizierteren,
schon etwas größeren Gui-Komponenten wie einer Tabelle
So unterschiedliche Formen der Interaktion und der Präsentation können mit dieser
Art von Komponenten abgebildet werden. Und das geht jetzt,
und das ist eine weitere Ebene von Gui-Komponenten,
so ganze Dialoge, also etwas,
was man so standardmäßig musterartig anbieten können möchte.
Es steht Ihnen auch schon als vorgefettet, vorgefertigte Komponente zur Verfügung.
Also bis hin zu verschiedenen Arten von Dialogen,
die eigentlich immer nach einem gewissen Muster
in Applikationen
wieder auftreten
Die stehen, brauchen sie nicht mehr einzeln zu programmieren,
sondern die stehen ihnen einfach als Komponenten.
Es ist zur Verwendung, zur Verfügung. So, jetzt kommen wir dazu,
wie diese Komponenten, also in unsere Programme integriert werden können.
Also ich fange mal jetzt eine Stufe vorher an,
was sie da sehen, ist so eine typische Host-Rechner-Menü,
Masken-Menü, Fensterauswahl. Was sie da jetzt tun können,
wenn sie da vorsitzen, ist,
sie können sich entscheiden, Für eine von diesen neuen,
für eine von diesen neuen Auswahlmöglichkeiten und dann schreiben sie hier
eine Zahl rein oder sie drücken eine von diesen Funktionstasten,
da kommen sie dann in einen anderen Modus und die Art und das ist so die klassische Art,
also der Oberflächengestaltung.
Damit sind Großrechner über die Jahrzehnte bedient worden.
Das sind sogenannte 32-70-Applikationen und das zugrunde liegende Konzept,
um diese Oberflächen zu programmieren, ist also das Eva-Prinzip,
Eingabeverarbeitung,
Im Englischen Input Process Output, IPO. Und als Programmiermethodik wurde das jahrelang auch,
also hier so auf dieser Seite des Auditoriums so gelernt,
Hypo für Hyrakical Input Process Output.
Also so baumartige Strukturen, in denen man Programme organisieren kann.
Das Prinzip ist immer dasselbe. So,
sie sehen das so in so, in so einer Pseudo-Code-Notation,
solange nicht jemand auf die Endetaste drückt,
so machen wir, wir lesen den Input,
wir prozessieren ihn und dann geben wir das Verarbeitungsergebnis aus.
Ja, bitte. Die Frage,
was ist das Älteste, der Willen,
wo ich
was gelesen habe
Ganzen Stören, hat er dann auch noch gekannt,
hat mit der Bruders erscheint, aber nicht nur der ganze Infinite.
Ja, das ist, also das geht so munter ineinander über.
Also das ist schon diese Art von Oberfläche, die hat sogenannte Teletypes abgelöst.
Also so Dinge, die mit Endlospapier betrieben worden sind.
Also Schreibmaschinen mit Endlospapier, das war sowieso die erste Art der interaktiven Bedienung.
Parallel dazu konnte man selbstverständlich auch mit Lochkarten,
wenn so Programme, ist ja klar.
Eigentlich sollte ich jeden von ihnen noch so ein Lochkartenpraktikum machen lassen,
wissen, wie gut sie es heutzutage haben.
So, Wenn man das macht,
also wenn man so seine Programme strukturiert, naja,
dann hat es so mit ein paar Vorteilen verbunden.
Also sie haben die vollständige Kontrolle über das Programm,
so 24 mal 80 Applikationen. Wer hat das schon mal gehört
? 24 mal 80. Wow. Es war vor 20 Jahren
auch anders. 24 Zeilen und Zeilen und 80 Spalten
hat so ein typischer Bildschirm immer schon gehabt.
Und wenn man so einen Bildschirm programmieren möchte,
dann ist also diese Art von Programmierung
ist wunderbar
Das kann man machen. Dass diese Bildschirme, die kann man heutzutage noch
als Emulatoren, also als Emulation, kann man das kaufen.
Man kann also für 50 Euro, glaube ich,
eine 32,70 Emulation von der VM 370, kann man kaufen. Das programmiert man wie früher. Das,
was diese Art der Programmierung aber dann so an Nachteilen mit sich bringt,
also sie sehen, naja, es ist keine natürliche,
es ist sowieso nichts natürlich von dem, was wir hier tun,
aber es gibt keine Anleitung für die Trennung von fachlichem,
ungui-spezifischem Code und in der Folge ist dann eben auch,
also die Trennung dieser beiden, also dass der Austausch einer Oberfläche ist, also praktisch ein Ding der Unmöglichkeit.
Es erweist sich, wo ich gerade bei Unmöglichkeit bin,
aber es erweist sich eigentlich auch ziemlich,
also es ist kein tragfähiges Programmiermodell für die Programmierung von reaktiven Oberflächen.
Da muss man anders drüber nachdenken. Das klappt einfach.
Mit diesen Programmiermodellen nicht mehr. Warum ist das so?
Jetzt gucken wir uns mal so eine reaktive Oberfläche wie die da an.
Also Dieter. Und naja, Da sind also so verschiedene
Ikonen, kann man sehen. Und also das,
was sie ja mit der Muttermilch offensichtlich aufgesogen haben,
ist, wenn sie mit der Maus,
also über eine dieser Ikonen fahren und doppelt draufdrücken,
dann haben sie eine bestimmte Erwartungshaltung.
Umgekehrt bedeutet das, als Programmierer einer Applikation,
die über eine Ikone dargestellt wird, ist,
sie wissen ja nie, wann der,
der davor sitzt, jetzt wirklich draufdrückt.
Sie warten da auf das entscheidende Ereignis,
sondern drückt er meinetwegen doppelt drauf.
Der Doppelklick ist im Übrigen
auch interessant
Klick, klick. Ab wann wird ein Doppelklick als Doppelklick wahrgenommen?
Du kannst du schweigen vom Trippelklick. Das muss man,
also da muss man mit Zeit arbeiten im Programm.
Und das wird dann schon wieder noch schwieriger. So,
zurück zum Thema. Dann hat er möglicherweise einen Doppelklick,
also hinbekommen. So. Gibt er jetzt was ein?
Wo fährt er als erstes mit der Maus hin?
Man weiß es ja einfach nicht. So, das über diese Art von Programmsteuerung,
weil Not Ende Do, also hinzubekommen, ist etwas,
was für Anwendungsprogrammierung von solchen Systemen ist jetzt Programmiermodell nicht geeignet.
Es ist viel besser
Wenn man sich darauf versteift und sich versteift,
also man bleibt ja ganz elastisch heutzutage. Wir sind reaktiv.
Wir sitzen da und warten, dass jemand drückt. Nicht abdrückt,
sondern also auf die Maus drückt oder auf die Tastatur und so der Fokus,
ob der Fokus bei uns im Fenster liegt,
dafür soll bitteschön das zugrunde liegende Fenstersystem sorgen.
Und das tut es dann eben auch.
Und die Haltung, die ich sie jetzt bitte einzunehmen,
ist, da draußen außerhalb ihrer Kontrolle gibt es
ein Fenstersystem
Und dieses Fenstersystem sorgt dafür, dass Ereignisse,
die ihr Programm betreffen, auch bei ihnen ankommen.
Und ob sie dann etwas damit anfangen, das ist ihre Angelegenheit.
Und dieses Eventing, dieses Eventing, das hier steht,
das sorgt schon dafür, dass alle Ereignisse,
für die sie sich interessiert haben,
dass die bei ihnen ankommen und dass sie diese Ereignisse interpretieren können.
So, der Vorteil, hier steht es also,
was da genau im Hintergrund passiert,
dafür sorgt das Abstrahierende Fenstersystem
Der Nachteil ist, sie müssen sich darauf einlassen und
sie müssen verstehen, nach welchen Prinzipien das funktioniert.
So, die grundlegende Idee sehen Sie hier, so ein bisschen blurrt.
Das ist die Oberfläche, die Sie zusammengestellt haben.
Hier sind die Ereignisse, da wird mit der Maus rumgekurvt,
um ihre Applikation. Und dann drückt jemand tatsächlich diesen Knopf hier.
Und dann sollten sie in ihrem Programm in der Lage sein,
genau dieses Ereignis wahrzunehmen. Wenn es sie denn interessiert,
wenn es sie interessiert, dann haben sie auch den
entsprechenden Code dafür hinterlegt
Und um dieses Prinzip, diese grundlegende Idee zu realisieren,
gibt es also, gibt es die Möglichkeit,
diese vom zugrunde liegenden Betriebssystem erzeugten Ereignisse auf die zu reagieren.
Die gibt es, wie ich schon gesagt habe,
gibt es die auf unterschiedlichen Ebenen, also von,
also die Maus hat sich um einen Pixel bewegt bis hin zu den sogenannten High-Level-Events,
die also verschiedene Ereignisse zusammenfassen,
wie zum Beispiel der Knopf ist gedrückt worden,
der Knopf wurde so lange gehalten und
jetzt ist er
wieder losgelassen worden
Das ist ein Beispiel für ein High-Level-Event, oft für die
man sich dann auch beim zugrunde liegenden Fenstersystem registrieren kann.
Registrieren wird hier als Anmeldung auch bezeichnet, dass es dasselbe Prinzip.
So, jetzt, bevor wir mal so ein bisschen in
die eigentliche Verdrahtung einsteigen, bitte ich Sie, sich zu erinnern.
Wir haben hier in der Vorlesung auch schon über das sogenannte Beobachtermuster gesprochen.
Da gab es, wenn Sie sich erinnern,
zwei Komponenten, die wir prinzipiell voneinander unterschieden haben,
nämlich den Beobachter und das Beobachtbare
Und dieses Prinzip wird jetzt nur mit einer etwas anderen Metaphorik,
finden Sie jetzt wieder bei der Realisierung von grafischen Benutzungsoberflächen in Java,
heißen die Beobachter, nicht Beobachter, sondern die heißen Listener.
Also die Hörenden. Das macht eigentlich keinen Unterschied,
oder? Ob man jetzt guckt oder hört,
also es ist irgendeine Art von Aufmerksamkeit, sollte man demjenigen,
der wahlweise was sich bewegt oder der was sagt,
sollte man sich zuwenden.
Was Sie hier sehen, ist diese prinzipielle Beziehung des Listening
an der Stelle
Sie in ihrer Anwendung, Sie erzeugen in einer direkten Benutzbeziehung
genau die Elemente, die es braucht, um ihre Oberflächen darzustellen.
Und jedes dieser Elemente, jedem dieser Elemente für dessen Rückkopplung sie sich interessieren,
sagen sie, falls was passiert, dann benachrichtige mich bitte.
Das ist also genau das Prinzip des Beobachtens. Und dieser Knopf hier,
der weiß jetzt gar nicht, dass das ihre Applikation ist,
sondern es ist eben etwas,
das ein bestimmtes Interface implementiert und dieses Interface implementieren Ist eine Eigenschaft,
also die jede der Applikationen mitbringen muss,
wenn sie denn eine grafische Oberfläche von einer grafischen Oberfläche profitieren möchte.
Die heißen im Kontext der Graphical User Interface mit Swing,
heißen die jeweils Actionlisten da.
Wenn ich an einer Reaktion interessiert bin oder einer Aktion,
wie immer interessiert bin, die an der Oberfläche ausgelöst wird,
dann bin ich gut beraten, wenn ich ein Actionlisten,
ein Listener implementiere.
Wie tue ich das? Nun, ich muss
die Operation Action performt
Dementieren. Und das sieht dann so von der Grundstruktur her,
sie sehen, gucken Sie mal gleich hier unten auf den grünen Kau,
der ist zwar nicht komplett,
aber das ist so der eigentliche funktionale Kern der Knopfapplikation,
die Sie gerade gesehen haben, nämlich dieser Knopf sagt,
nun, ich bin da dann interessiert an das etwas,
was da draußen passiert,
dass ich darauf reagieren kann.
Deswegen implementiere ich jetzt mal diesen Actionlistener und das tue ich,
indem ich die Operation, also die Schnittstelle Action performt, implementiere.
Sie sehen, Knopf, wenn er denn mal gedrückt wird,
der liefert mir noch ein Action-Event mit.
Da steht also viel darüber drin,
welcher Arzt dieses Ereignis ist, das da ausgelöst worden ist.
Und dann kann ich darauf reagieren. Nun gucke ich mir im Code von Action performt,
so wie sie den hier sehen,
gucke ich mir dieses Ereignis gar nicht an,
weil ich weiß ja, da ist ein Knopf gedrückt worden,
ich zähle die Zähle hoch und gut ist.
Das Einzige, was jetzt noch fehlt, ist,
dass dieser Knopf, diese Klasse Knopf sich tatsächlich auch registrieren
muss und das tut sie dann bei dem Knopf,
in dem sie sich als Parameter,
als Listener in diesem Fall registriert.
Aber die Details wird ihnen Fred gleich noch zeigen
So, dann sind wir, können wir uns das jetzt
mal im Prinzip, können wir uns das mal anschauen,
wie das so im schematischen Ablauf, wie das funktioniert.
Also es gibt erstmal so eine Anwendung, in unserem Fall
war das der Knopf. Und dieser Knopf muss sagen,
ich implementiere jetzt mal einen Actionlisten, also diese Schnittstelle.
So, das tue ich,
indem ich die Operation Action performt in diesem Fall, implementiere.
Dann erzeuge ich einen Knopf, also da steht jetzt Quit
drauf und nicht, drück mich oder sonst was.
Und ich muss diesem Knopf dann mitteilen,
also welcher Actionlisten,
den jetzt
eigentlich zuhören möchte
Gibt man sich typischerweise selbst als Parameter, sodass der hier weiß,
also wenn was passiert, nehme ich das Klick,
dann muss ich Knopf, ein Action-Event erzeugen,
nämlich genau das im Knopf gedrückt worden ist zum Beispiel.
Und dann werde ich diesen Action-Listen da aufrufen,
indem ich seine implementierte Operation Action performt aufrufe.
Und dann kann die Anwendung darauf reagieren, was auch immer da jetzt,
also an Operation, an Funktionalität dahinter liegt.
So werden jetzt prinzipiell funktionale Elemente, sprich also hier in
unserem Beispiel der Knopf und Oberflächenelemente miteinander verbunden.
Fundamental zugrunde liegend ist, es sind reaktive Anwendungen und diese
reaktive Anwendung wird über die Anwendung oder eine Verwendung des Entwurfsmusters Beobachter
hier Listener genannt, miteinander verknüpft.
Glack. Der Knopfdruck verarbeitet, so ist es. So,
also hier steht das jetzt nochmal zusammengefasst, dass also diese Eventlistener,
ist der fundamentale Mechanismus mit dem Oberflächen mit funktionalen Klassen Oberflächenklassen und funktionale Klassen miteinander verbunden werden können.
Und das ist eine Anwendung des Entwurfs, muss das Beobacht,
Beobachter, dass wir schon an anderer Stelle auch kennengelernt haben.
Jetzt kommen wir noch, müssen wir noch ein konstitutives Element
für grafische Oberflächen, müssten wir noch mal jetzt besprechen.
Sie haben ja das Verhalten gesehen, wenn eine Klasse,
nein, wenn eine Oberfläche, wenn die mal in der Größe verändert wird.
Ich habe auch angekündigt, dass wir so ein bisschen
was über das Layout sagen
Ich habe Ihnen bis jetzt sogenannte atomare Komponenten für die Gestaltung von Oberflächen dargestellt.
Also gezeigt, also Knöpfe, Label, Texte,
Eingabeflächen für etwas. Jetzt können Sie sich schon vorstellen,
also wenn Sie sich mal so eine Applikation wie hier dieses PowerPoint oder so,
wenn Sie das auf der Ebene alles programmieren wollten,
zusammenstellen wollten, dass das etwas unübersichtlich werden könnte.
Deswegen gibt es in den meisten... Nein, in allen kann ich sagen,
in allen Fenstersystem-Bibliotheken gibt es auch sogenannte Container-Komponenten, die wiederum Container und am Ende dann eben immer atomare Komponenten enthalten können. Schauen wir uns mal so eine Oberfläche ein,
also wenn wir mal diese Oberfläche hier uns betrachten,
dann sieht die ja so aus,
als hätte die eins, zwei, drei, vier,
fünf, sechs, sieben, acht Elemente,
die kann man jetzt mal so einfach so nebeneinander stellen,
so von der Strukturierungsebene her ist es aber anders zusammengefasst und zwar sind also in dem,
das ist so der Top, der Top-Level-Container für,
jetzt in uns in unserem Fall für die meisten Swing-Applikationen,
für die meisten nicht für alle,
ist ein sogar genanntes Frame, also auf Deutsch ein Rahmen.
Und dieser Top-Level-Container kann entweder atomare Komponenten enthalten,
wie dieses Label, oder wiederum andere Container,
die dann atomare Komponenten in diesem Fall enthalten. Das heißt,
wenn ich also so ein Panel mir auswähle,
das ist so eine Schaltfläche,
dann kann ich diese Schaltfläche erstmal zusammenfassen und also dieses Kombination,
so was Formularartiges,
nämlich hier steht ein Text und da wird eine Eingabe
erwartet,
dann kann ich das in einem Panel zusammenfassen
So wie ich in einem Panel zusammenfasse, das,
was man da jetzt machen kann. Also das übliche Quid-Cancel-Self meinetwegen,
das fasse ich dann in einem anderen Panel zusammen, wie heißen,
mit den Elementen einer Oberflächenbibliothek sind nicht nur die sichtbaren Elemente beschreibbar,
sondern auch strukturierende Elemente, wie das, was sie hier sehen,
dass ich also eine größere Oberfläche in ihre verschiedenen strukturellen Elemente unterteilen kann.
Das wird bei der Gestaltung des Layouts, wird das auch nochmal gleich eine Rolle spielen.
So, dass ihr jetzt erstmal ein unsichtbarer, strukturelle,
unsichtbares, strukturierendes Merkmal für Oberflächen.
Dafür gibt es auch Elemente, Komponenten in diesen Swing-Bibliotheken.
Irgendwo muss es immer anfangen, habe ich schon gesagt,
dass in dem Fall, den Sie gerade gesehen haben,
ist der Top-Level-Container ein Jay-Frame und es gibt eben noch eine Reihe von anderen Top-Level-Containern,
die Nachricht an dieser Stelle ist eigentlich nur,
es muss die eine Stelle geben, die den Zusammenhang herstellt zwischen Fenstersystem,
Bibliothek und ihrer Applikation.
Und das ist in unserem Fall üblicherweise ein Jay Frank.
Das hat eine bestimmte Struktur. Es muss immer einen Titel geben.
Es muss immer einen Content geben. Und wenn man will
, kann man noch eine Menu-Bar integrieren. Das heißt,
sie sind schon so strukturierende Elemente durch, also das Jay Frame vorgegeben.
Das hat dann eben auch so einen bestimmten Wiedererkennungseffekt,
sowohl für sie als Programmierer, als auch für diejenigen,
die ihre Anwendung nachher verwenden. So, der letzte Punkt,
den ich jetzt noch machen werde, Ist das Layout?
Es gibt innerhalb der Swing-Bibliothek verschiedene Möglichkeiten,
das Layout, Layout festzulegen und zu beeinflussen,
damit man insbesondere beim Vergrößern und Verkleinern des Fensters ein Verhalten erzielt,
das etwas nachvollziehbarer ist als das, was ich gerade implementiert habe,
bei meiner Klopfableckknopf, nicht Klopf, Knopfapplikation.
Und sie sehen jetzt hier genau das,
was ich gerade gezeigt habe, nochmal bitte ergänzenden Information,
dass die gesamten Container eben auch Layout-Informationen mit sich bringen können
So, hier hat sich nämlich jemand Gedanken darüber gemacht,
wenn es eine Vergrößerung gibt, dann soll also bei dem Button-Panel,
soll sich den Knopf, bei der Knopfleiste, soll sich das Layout anders so verschieben,
als bei dem Formularartigen, als bei der Formularartigen Gruppe.
Und das gibt jetzt auch schon so einen Hinweis darauf,
nach welchen Kriterien man die Oberflächenelemente strukturieren sollte,
nämlich da unter anderem danach, wie die sich verhalten sollen,
wenn es zu Größenveränderungen kommt,
weil der Zusammenhang zwischen diesen beiden Elementen denke ich,
der ist zwingend und sollte immer erhalten bleiben,
wenn sich das Fenster also hier verkleinert, sollte das nicht,
dieses Element nicht auf einmal unter diesem Element stehen,
während das so bei den dreien hier eigentlich ziemlich wurscht.
Wahrscheinlich nicht, aber sagen wir mal, da existiert der Zusammenhang,
den ich jetzt hier oben gerade beschrieben habe, erstmal nicht.
Und insofern kann ich hier auch eine andere Layout-Strategie in Anführungsstrichen
wählen, als das bei diesem Container der Fall ist.
Und das sind so die Fragen,
die sich Also die sie sich stellen können bezüglich,
also des Verhaltens, also vor allem der Größenänderung ihrer Applikation.
Und es gibt eben standardmäßig, gibt es also unterschiedliche Strategien,
wie sie das Layout so beeinflussen können.
Und die sind jetzt erstmal hier nur so dargestellt.
Das, was die meisten einstellen, Möglichkeiten gibt,
ist also dieses Layout ist aber dann eben auch von der Verwendung her schon relativ aufwendig.
Aber so ist es halt. Man muss halt in ein
anständiges Design, muss man dann eben auch ziemlich viel,
also ziemlich viel programmatische Arbeit hineinstecken.
So, womit ich am Ende meiner Zeilen bin bezüglich
der Einführung in die Implementierung von Graphical User Interfaces.
Sie haben jetzt so verschiedene Möglichkeiten kennengelernt, etwas an der Oberfläche darzustellen.
Dazu gibt es Gui-Komponenten. Und das zentrale Moment ist also
hier eigentlich in dem Satz zusammengefasst. Somit der Verwendung von Listenern haben Sie die Möglichkeit,
Ihren Anwendungscode mit dem Code,
mit den Komponenten einer Gui-Bibliothek zusammenzubringen um dann darauf zu reagieren,
dass Ereignisse an der Oberfläche von der Fenstersystembibliothek an sie weitergeleitet worden sind.
So, mit diesen Kenntnissen können wir nun unsere ersten Desktop-Anwendungen konstruieren.
Viel Spaß! So, da bin ich wieder.
Heute mit drei Minuten mehr Zeit, das freut mich.
Man kann ja eigentlich gar nicht genug Zeit haben hier vorne beim Programmieren.
Ja, Ich wollte eigentlich heute ein riesiges Monster-Projekt mit euch bauen,
so eine kleine Chat-Anwendung, wo dann mehrere Leute in verschiedenen Fenstern miteinander chatten können.
Bei mir ist es gestern aufgefallen, dass es doch
ein bisschen zu viel für diese Dreiviertelstunde.
Das werde ich wahrscheinlich am Ende des MS das mal mit euch machen.
Heute fokussieren wir also auf Guis. Ich habe ein System
genommen, was ich schon letztes Jahr vorgestellt hatte.
Ich hatte so ein ganz kleines bisschen aufgeräumt.
Das ist, vielleicht zeige ich es euch erst mal,
wie dieses System zur Laufzeit aussieht.
Das ist ja eine frühe Version eines Systems,
was ja vielleicht aus SE1 kennt
Ah. Wir haben wieder das Problem,
dass man den linken Rand nicht sieht, oder?
Ja. Ich habe eben extra was gemacht. Ich habe
eine Zeile Code. Dann war ich dann die Zeile Code.
Hier. So, nochmal von vorn. Haha. Jetzt
kann ich nicht vergessen, das ist nach rechts zu schieben.
Sieht man jetzt alles? Ja. Also das ist ein
Tool, was sich schon immer über Gleitkommazahlen wissen wollten.
Ja, unsere erste eigene grafische Anwendung mit Zwing programmiert.
Man hat hier so ein eigenes Textfeld,
ich kann da irgendwas eingeben,
sagen wir mal
123. Dank gibt es hier drei verschiedene Buttons.
Der Button bewirkt noch nichts, der Button bewirkt noch nichts.
Und wenn ich diesen Button drücke, passiert was.
Man sieht, diese Zahl 123, für uns toll,
als Menschen lesbar, wie die intern im Double-Formal abgelegt ist.
Also intern wird das so gehandhabt, dass er sagt,
das ist irgendwie ein ganzer und ein halber und ein Viertel und
ein Achtel und ein 32. und ein 34., mal 32.
Könnt ihr euch vielleicht mal mit dem Taschenrechner ausrechnen,
ob das wirklich hinkommt. Da müsst ihr 133 rauskommen.
Und genauso kann man ja auch irgendwelche gebrauchenen Zahlen eingeben,
was ich 0,5 oder so
Die City ist relativ einfach, das ist einfach nur ein ganz normal,
zweibuch minus eins, das kriegt ihr vielleicht auch noch im Kopf hin.
Und was ganz spannend ist, was ihr denn schon kennt aus SE1,
dass eben viele dieser Zahlen periodisch sind und sogar unendlich periodisch.
Ihr seht ja dieses typische Muster von 0-0,
1-1, 0-0, 1-1,
das hatte ich euch auch schon in der SE1 gezeigt,
dass man eben das Problem hat,
ein Zittel ist ihm binär periodisch und deswegen muss am Ende irgendwie auf- oder abgerundet werden.
Und dann seht ihr, dann ist die Zahl,
die da wirklich gespeichert wird und ein ganz kleines bisschen anders. Okay,
und was ich jetzt, worauf wir heute hinaus wollen,
ist, dass eben, dass man mit diesem Knopf sagen kann,
zeigen wir doch mal die Zahl den unmittelbaren Vorgänger von dieser komischen Zahl,
ja, mach doch mal die Zahl ein bisschen kleiner in einem elementaren Schritt.
Und hiermit kann man dann zum Nachfolger gehen. Das ist
noch nicht implementiert. Aber bevor wir das machen können,
müssen wir uns erst mal angucken, wie ist das System überhaupt gebaut?
Dann ziehe ich das jetzt mal hier runter.
Das hat sich letztes Jahr als ganz hilfreich erwiesen,
immer gleichzeitig die Google zu sehen, wenn ich darüber reden will.
Okay. So. Es gibt jetzt zwei Klassen, die wir uns angucken müssen.
Eine Klasse behandelt dieses Thema, was man hier ja auch sieht.
Welche Komponenten verwenden wir überhaupt? Verwenden wir irgendwelche Panels oder Frames,
Buttons, dieser ganze Kram und wie werden die irgendwie ineinander gesteckt,
sodass es irgendwie hübsch aussieht? Ja,
also irgendwie erst diese Zeile, wo man das eingibt,
dann irgendwie so ein Bereich mit Buttons,
dann irgendwie hier so ein Bereich mit dieser binären Anzeige und hier so ein Bereich mit dieser dezimalen Anzeige,
dass es das überhaupt gibt, werden wir in dieser Klasse wiederfinden.
Diese Klasse heißt per Konvention, endet sie auf den beiden Buchstaben UI, User Interface.
Was aber in dieser Klasse nicht drin ist, ist,
was passiert, wenn ich auf diese Buttons drücke?
Das gucken wir uns anschließend an, das ist in dieser Werkzeugklasse.
Und unsere Systeme sind genauso aufgebaut
Die eigentlichen Swing-Komponenten, welche gibt es und
wie werden sie zusammengesteckt, ist immer in diesen UI-Klassen.
Und was passiert, wenn ich Knöpfe drücke oder sonstige Ereignisse,
dass es in diesen Werk zu stoßen.
Okay. Gut, am Anfang sind da so ein paar Imports,
die sind jetzt nicht so spannend, kann man die nicht sogar zuklappen.
Ja. Okay. Gut, man sieht erstmal,
ich habe ja immer, jedes Jahr nehme ich mir vor,
ich werde dieses alte Notebook nicht wiederverwenden nächstes Jahr,
ich werde mir ein besseres kaufen mit einer höheren Auflösung,
dann wird möglicherweise dieses Fenster viel kleiner, dann muss ich möglicherweise die Schrift größer machen oder so.
Ich habe mir erstmal hier ein paar Konstanten angelegt.
Ihr kennt ja vielleicht noch Static Final, das verwendet man ja für irgendwelche numerischen Konstanten.
Das ist einfach praktisch. Wenn ich irgendwann mal feststellen sollte,
in fünf Jahren, wenn ich mir wirklich mal ein neues Notebook kaufe,
ich muss jetzt wirklich mal irgendwas verändern,
dann habe ich relativ schnell Zugriff darauf.
Per Kombination habe ich diese konstant immer ganz oben.
Also hier ist einfach nur, mit dieser Schraube kann man eben einstellen,
wie viel Zeichen hier so reinpassen sollen,
so ungefähr 40 Zeichen sollen da reinpassen.
Dann ist hier die Schriftgröße, kann die also größer und kleiner machen,
wenn euch das jetzt zum Beispiel zu klein gewesen wäre.
Und ja, der Fenstertitel, der war letztes Jahr auch anders.
Also das ist dieser String, den man hier oben sieht,
was sie schon immer über Gleitkommazan wissen wollten.
Wenn wir dir nächstes Jahr nicht mehr gefallen sollte,
kann ich den
ganz schnell ändern
Okay. Gut, das hat erstmal noch nichts mit zwingend
zu tun, da sind ja nur irgendwelche Zahlen oder Strints.
Das ist jetzt unser erster Kontakt mit Zwingen. Ich sage also,
ich brauche einen J-Frame, ein J-Frame ist ja quasi dieses gesamte Fenster,
ein Fenster mit so einem Titelstream,
dann hat man hier oben irgendwelche Bereiche,
mit denen man was machen kann.
Das wird alles vom Betriebssystem zur Verfügung gestellt.
Auf dem Mac-Antorschen würden hier wahrscheinlich irgendwelche Symbole sein,
rot, grün und gelb oder so.
Ich hatte nie einen Mac-Antorsch. Und möglicherweise wird dann auch der Titel
nicht in der Mitte sein, sondern links oder rechts.
Das hängt immer so ein bisschen vom Betriebssystem ab. Aber gut,
der J-Frame ist ja so das äußerste Fenster um alles rum,
jedes Wing, Applikation braucht so ein J-Frame,
sonst würde man einfach nichts sehen
Das ist jetzt erstmal nur die Variable, die Erzeugung,
schauen wir uns gleich an im Konstruktor.
Gut. Jay Textfield. Ja,
das ist also diese Swing-Komponente, die ihr hier sieht,
ein Feld, wo man Text angeben kann.
Der Name ist ja eigentlich recht sprechend. Und ich habe
das einfach mal Eingabe genannt, weil mir nichts Besseres einfällt.
Also alles Mögliche, was man hier so eingibt,
das ist eben dieses J-Textfield, ja.
Okay. Dann, ja, ein Thema,
was geht auf einer der letzten Folien hatte.
Also dieses J-Textfield ist so eine atomare Komponente.
Und dieses Jay Panels, eine Container-Komponente. Das J-Panel an
sich sieht man also in dem Sinne gar nicht.
Ja, das ist also, ja,
dieser Bereich hier quasi,
das ist dieses J-Panel
Und ich benutze es nur deswegen, weil ich da drei Buttons eintun will.
Und diese drei Buttons zieht ihr hier. Das sind also
diese drei Buttons. Die Tatsache, dass diese drei Buttons
in diesem Panel sind, sieht man hier jetzt noch nicht.
Das sind jetzt hier erstmal nur Variablen-Deklarationen, ganz normales Java.
Ich werde euch gleich zeigen, wie wir die Bahns da reinkriegen.
Gut. Dann haben wir noch einen J-Textfield. Das ist hier für diese Ausgabe,
wo man also ja diese merkwürdigen periodischen Binär-String irgendwie sieht.
Und dann haben wir nochmal eine Text Area,
wo man dann sieht, ja, welcher exakte dezimale Wert
eigentlich wirklich jetzt repräsentiert wird von dieser leicht gerundeten Zahl.
Das heißt also, diese Swing-Komponente, wo ich was eingebe,
Und diese Swing-Komponente sind im Prinzip vom selben Typ,
aber sie sehen so ein bisschen anders aus.
Also ich kann nicht oben, kann ich ja was eingeben,
ich kann auch was löschen oder da,
dass sie auch irgendwelche Buchstaben eingeben oder irgendwas.
Wenn ich hier, hier kann ich nur mit der Maus markieren,
wenn ich mir das irgendwie in eine E-Mail kopieren will oder irgendwas.
Aber ich kann hier nichts verändern, ich kann da nichts löschen oder irgendwas.
Das ist sozusagen ein Schreibgeschütz. Deswegen ist das so grau.
Okay. Und diese J-Text Area unterscheidet sich von einem J-Text-Field
nur dadurch, dass die auch mehrere Zeilen erlaubt.
So ein J-Text-Field ist halt eine Zeit und wenn irgendwann
kein Platz mehr ist, dann hat der einfach Pech,
dann seht ihr es nicht mehr.
Und bei einer J-Text Area, die kann sich eben auch,
ja, die kann eben auch über mehrere Zeilen gehen.
Das ist, fragt man sich, warum sollte ich sowas haben wollen?
Ihr werdet nachher noch Zahlen sehen, die über sehr,
sehr viele Zeilen gehen.
Gut, das sind also sozusagen die Zutaten unseres Rezepts.
Was brauchen wir so alles, um diese Sing-Anwendung zusammenzubauen?
Aber ich mache noch nichts mit diesen Zutaten. Gut.
Schauen wir uns mal jetzt den Konstruktor dieser UI-Klasse an.
Und ich habe mir das irgendwann mal angewöhnt,
Konstrukturen nicht zu lang zu machen.
Das gilt ja eigentlich auch für normale Methoden.
Also eine Methode, ich bin immer ganz froh,
wenn eine Methode auf eine Bildschirmseite passt.
Okay, was macht dieser Konstruktor? Ich habe das jetzt also mal aufgeteilt.
Ich habe mich also quasi orientiert an der Struktur dieser GUI
und habe dann eigene Initialisierungsmethoden geschrieben für diese Bereich.
Also eine Methode, die sich darum kümmert,
dass irgendwie hier
was Sinnvolles initialisiert
Initialisiert wird. Eine Methode, die sicher um diese Initialisierung dieses Bereichs kümmert.
Eine hierfür eigentlich Hilfe. Da habe ich ja so vier
verschiedene Initialisierungsmethoden geschrieben, die wir uns gleich angucken werden.
Und standen noch eine weitere Methode, die einfach dafür sorgt,
okay, hey, Swing, mach jetzt mal,
ich will, dass der Benutzer wirklich was sieht,
auch das schauen wir uns gleich an.
Gut. Der J-Frame. Oh, ich sehe gerade,
das ist nicht 100 Prozent korrekt fortschritt. So. So erzeugt man
einen J-Frame. Das ist ein ganz normaler Java-Objekterzeugung, ja.
Ich kann also einfach dieses New davor schreiben. Ich sage,
ich brauche jetzt so einen J-Frame und dann gibt es ganz viele Konstruktoren,
entweder schreibe ich gar nichts rein,
dann kriege ich einen J-Frame zum Beispiel,
der noch nicht mal einen Titel hat.
Wenn ich will, dass der von vornherein einen Titel hat,
dann kann ich den Titel hier einfach übergeben und ich spiele
immer ganz gern bei sowas rum.
Also ich könnte auch jetzt hier zum Beispiel reinschreiben,
Und wenn ich das jetzt mal neu starte, unsere wunderbare Applikation,
dann seht ihr, das ist tatsächlich eine Auswirkung.
Hier oben steht jetzt Juhu. Ja, die Konsole wollte ich jetzt eigentlich
gar nicht sehen. So. Ja, also der Streaming,
den der übergibt, der ist dann eben der Fenstertitel.
Deswegen ist es ganz nett, wenn man solche sprechenden Variablen hat,
dann ist es ein Programmieranfänger sofort klar, ah, das,
was in den runden Klammern steht, ist der Fenstertitel,
alles klar.
So, das habe ich jetzt nur für die Vorlesung da reingebaut.
Damit kann ich also sagen, lieber Frame,
geh doch mal an X-Positionen 32,
an Y-Position 0 und sei mindestens einen Pixel bereit,
wenn nötig breiter und sei mindestens einen Pixel hoch
Wenn nötig, höher. Ich hatte jetzt keine Lust,
von Hand mir zu überlegen, was da sinnvolle Werte sind.
Das macht es weniger automatisch. Ich wollte aber nicht,
dass wir wieder dieses Problem haben,
dass man auf dem Beamer nicht alles sieht.
Deswegen habe ich das jetzt mal da reinprogrammiert.
Sowas müsst ihr normalerweise nicht programmieren. Okay,
wie werden jetzt die Komponenten innerhalb dieses Jay Frames angeordnet?
Ja, vielleicht ist einem das gar nicht so bewusst.
Wir schauen uns das nochmal ganz kurz an.
Also wir haben vier Komponenten, die untereinander angeordnet werden.
Die werden also nicht irgendwie nebeneinander gemacht oder irgendwie zufällig oder einer
bekommt ganz viel Platz und die anderen nur ganz wenig,
sondern die werden einfach stumpf untereinander gepackt.
Und das muss ich eben so programmieren. Ich kann also diesen Frame sagen,
Setzt doch mal ein bestimmtes Layout und dann kann ich so
ein Layout mir erzeugen, zum Beispiel das Box-Layout.
Das sind jetzt hier so ein paar Details,
die müsst ihr jetzt noch nicht verstehen, könnt ihr in der Dokumentation nachlesen.
Und dieser Parameter sagt, ich möchte,
dass das von oben nach unten angeordnet wird.
Und es gibt auch zum Beispiel von links nach rechts oder
von rechts nach links gibt es, glaube ich, auch.
Das muss man also extra sagen. Sonst sieht das vielleicht
komisch aus. Wir machen mal Ausbildung, was passiert,
wenn man das nicht macht, habe ich noch nie ausprobiert,
vielleicht kommt da was ganz Merkwürdiges bei raus.
Auskommentieren, wenn ich das Layout nicht setze, was dann passiert.
Okay. Ja, irgendwie nicht so sinnvoll, oder?
Wahrscheinlich hat er jetzt alle Komponenten an dieselbe Stelle getan und
die überdecken sich jetzt alle und deswegen kann ich jetzt
nichts Sinnvolles mehr mit dem Programm tun.
Dann machen wir das mal wieder rückgängig. Wieso kommt eigentlich
mal diese komische Zahl, wenn ich das Programm starte?
Das ist ja super nervig. Das will ich nicht.
Ach, das ist hier weg damit. So. Okay,
da waren wir jetzt also. Ich starte das wieder,
dass ihr das seht, dass ich drüber reden kann.
So, ne? Okay, also nochmal, wir haben ihn erzeugt,
den JFrame, damit ich irgendwie damit arbeiten kann.
Ich habe gesagt, verschiebe dich mal ein bisschen nach rechts.
Und dann habe ich gesagt, die Komponenten,
die ich gleich nicht reinstecken werde, bitte ordne sie von oben nach unten an.
Schön untereinander
Das war also diese Methode. Jetzt kümmern wir uns um
diese Methode als nächstes E-Need-Eingabe. Nicht besonders viel Text.
Schauen wir mal, was passiert hier.
Ich erzeuge mir dieses J-Text-Field und übergebe hier als Konstruktor,
wie viele Buchstaben oder Zeichen ich da so als Benutzer erwarte,
reinstecken zu können, beziehungsweise dass man das zumindest sehen kann.
Ich glaube, 40 hatte ich da eingegeben nach dem Motto,
keine Double-Zahl, auch mehr als 40 Zeichen.
Okay, dann habe ich mir noch so eine kleine Hilfsmethode geschrieben.
Normalerweise sind diese Texte extrem klein, was ist für Präsentationen immer blöd.
Also man will, dass die Schrift schön groß ist,
habe ich mir eine eigene Methode geschrieben, wir können da einmal ganz groß reinspringen,
ist aber nicht besonders spannend, was passiert.
Was passiert dir? Ich übergebe also eine Komponente,
wo ich die Schrift größer machen will
Dann sage ich dieser Komponente,
gib mir doch mal die Schriftart, die du gerade benutzt.
Und dann sage ich, aus dieser Schriftart will ich eine
neue Schriftart ableiten, die einfach ein bisschen größer ist.
Und die setze ich dann wieder. Ja, das ist
keine Magie. Ihr müsst euch einfach nochmal die API ein
bisschen von Swing angucken, was man alles machen kann.
Man kann eben auch aktiv mit Schriftarten umgehen.
Okay. Jetzt habe ich das Ding erzeugt. Es schwebt
aber so noch im luftwehren Raum. Und jetzt muss ich
das diesen Frameman zufügen. Ich muss also wirklich sagen,
das soll jetzt hier rein als oberster Komponente.
Und das tue ich mit dieser Ad-Methode.
Ad könnt ihr schon von Air-Realisten. Hier, das ist
eigentlich eine recht ähnliche Bedeutung. Ich sage also,
diesen Frame, du bekommst jetzt eine neue Komponente reingesteckt,
nämlich diese Eingabekomponente.
Dieses Trade-Tag-Field,
was ich gerade erzeugt habe
Ja, diese Zahl nur sorgt dafür, dass es hier
wirklich eingesteckt wird. Gut. Jetzt kommt dieser Schachtelungsaspekt,
den Google schon. Google. Guido schon angesprochen hatte.
Entschuldigung. Man kann jetzt Komponenten in Komponenten schachteln. Also,
nochmal, dieser Bereich, den ihr hier seht,
wo diese Buttons drin sind, ist auch eine eigenständige Google-Komponente.
Die muss ich erst mal erzeugen. Ein Japanel. Ein Japanel ist das,
was auf Verzeichnis eben ein Ordner ist, etwas,
wo ich Dinge reinstecken kann,
aber der an sich erst mal keine Existenzberechtigung hat,
solange da nichts drin ist.
Okay, ich erzeuge mir, also dieses J-Panel,
dieses Button-Panel habe ich
es genannt
Und dann rufe ich drei Hilfsmethoden auf,
die diese Buttons initialisieren, schauen wir uns auch gleich an.
Und nachdem ich das gemacht habe,
muss ich jetzt auch dieses Button-Panel dem Frameman zufügen.
Und so läuft das eigentlich die ganze Zeit. Ihr initialisiert euch
eure Komponenten, wenn sie in einem sinnvollen Zustand sind,
dann fügt ihr sie zu dem Frameman zu.
Und sowas ähnliches werden wir jetzt auch innerhalb dieser Hilfsmethoden sehen.
Zum Beispiel hier, die Button-Erzeugung ist extrem trivial. Ich erzeuge mir also,
wir warten auch mal Video über so einen New-Aufruf und ich übergebe dann,
in diesem Fall nicht einen Fenstertitel, sondern das,
was soll auf dem Button als Text stehen?
Auf dem einen soll so ein Minuszeichen stehen,
auf dem hier soll so ein V stehen,
das soll eigentlich mehr
so ein Pfeil nach unten sein
Dass das von hier oben quasi noch da kommt.
Und dieses Plus soll eben auf dem Baden stehen, ja.
Ich sage also dem Jabberton, das soll deine Beschriftung sein.
Und jetzt füge ich den, diesen Button-Panel hinzu.
Wollen wir aus Spaß vielleicht das nicht im Button-Panel hinzufügen,
sondern direkt den Frame? Macht das Sinn? Wir probieren das
einfach mal ganz kurz. Ich würde dann ja erwarten,
dass die irgendwie quasi direkt untereinander da stehen,
genauso wie alle anderen Komponenten, die wir bis jetzt hinzugefügt hatten.
Das sieht wahrscheinlich, ja, besonders lustig wird es nicht
aussehen, aber es sieht dann zumindest anders aus.
Schauen wir uns mal ganz kurz an. Nun seht ihr,
dann sind die einfach als einzelne gleichberechtigte Komponenten untereinander,
sind nicht gleich bereit. Das ist schon ziemlich hässlich.
Da können sich dann die NCI darum kümmern,
worum das jetzt liegt.
Machen wir das wieder rückgängig. Gut. Haben wir das wieder?
Ja, jetzt sind wir so quasi bis hier gekommen.
Was kommt als nächstes? Jetzt haben wir hier noch
diese Anzeige, die will ich ja auch initialisieren.
Das habe ich nochmal unterteilt in zwei Initialisierungsmethoden.
Ich bin sehr ordentlich heute. Okay. Was machen wir
jetzt hier? Wir erzeugen uns wieder ein neues J.Hexfield,
das war quasi dieses J.Hexfield sein. Ich sage auch wieder,
ich will hier eine große Schrift da drin haben, dieselbe Hilfsmethode wie oben.
Und jetzt kommt was Spannendes. Ich will nicht,
dass der Benutzer hier irgendwie reinklicken kann und irgendwie da was eingeben kann,
weil es soll ja eine Ausgabe sein oder eine Anzeige und keine Eingabe.
Ich sage also
diesen Textfield
Der Benutzer kann dich nicht editieren. Der Benutzer kann keine Veränderung in dir vornehmen.
Das macht man damit. Wenn ich das mal auskommentiere,
machen wir das mal wieder schön interaktiv,
ich kommentiere es aus, starte das Programm.
Ich sage jetzt irgendwie 0,5, dann kann ich jetzt hier irgendeinen Unsinn machen.
So zum Beispiel. Das will ich ja nicht. Das
ergibt irgendwie keinen Sinn, mache ich das mal wieder verkämmig.
Ja, und auch hier wieder dasselbe Spiel. Wenn ich also der Überzeugung bin,
ja, ich habe die Komponente jetzt sinnvoll erzeugt,
dann stecke ich sie mal in meinen JFrame rein,
damit sie dann hier, ja, ein Teil dieses JFrames ist.
Sonst schwebt sie einfach nur im luftleeren Raum
Gut. Dezimale Anzeige ist da irgendwas anders? Ja,
ich muss mir jetzt hier natürlich eine Text-Area statt einem Text-Field erzeugen.
Das ist ein offensichtlicher Unterschied. Das ist exakt dasselbe.
Das ist exakt dasselbe. Ich will auch nicht,
dass der Benutzer hier irgendwas eingeben kann. Ja,
und hier sage ich eben noch, wenn eine Zeile besonders lang wird,
dann darfst du sie aufteilen in optisch mehrere Zeilen.
Was passiert, wenn ich das nicht mache, können wir nachher auch mal ausprobieren?
Ist aber, glaube ich, jetzt nicht so spannend.
Dann sieht man einfach ganz viel nicht, wenn die Zahl zu lang wird.
Okay. Ja, gibt es bis hierhin erstmal Fragen?
Wir gehen nochmal ganz kurz hoch, wie wir angefangen hatten.
Also ich hatte gesagt, um diese Gui Ja.
Für unser erstes Beispiel mit der Gool-Premium müssen wir erstmal die ganzen Zutaten quasi hier notieren,
welche Komponenten brauchen wir so, brauchen wir so,
dann initialisieren wir die und müssen immer daran denken,
dass wir die in diesen Frame reinstecken.
Und ja, bei dem Button-Panel weiß noch das Interessante,
dass es da diese Schachtelung gab.
Die Buttons sind in dem Panel,
also drei Buttons sind im selben Panel und das Pendel
ist ein von vier Komponenten in diesem JFrame.
Gibt es dazu von eurer Seite erstmal Fragen?
Keine Fragen.
Okay. Gut
Ist, wo waren wir jetzt gekommen? Bis hier.
Und dann das Letzte, was man immer tun muss,
ich mache mal wieder Folgendes, ich kommentiere das einfach mal aus.
So ein paar drei magische Zeilen. Oder auch reichen wir
nicht nur die Hundesteuerung. Ich starte jetzt mal
das Programm. Ja, man sieht nichts. Okay,
läuft das Programm jetzt eigentlich irgendwie im Hintergrund?
Nee, ich glaube nicht, ne? Nee. Gut,
das heißt also, wir haben uns diesen J-Frame erzeugt,
haben alles wunderbar da reingesteckt und so.
Aber ich muss dem J-Frame noch auf jeden Fall sagen,
dass er sichtbar sein soll. Wenn er nicht sichtbar ist,
sehe ich ihn nicht. Und bevor man das macht,
ist es sinnvoll zu sagen, okay, lieber J-Frame,
du bestehst jetzt aus diesen vier Komponenten,
Jetzt überleg dir doch mal, was für eine Größe sinnvoll wäre.
Ich kommentiere das auch mal aus, wenn ihr dem nicht sagt,
dass er sich mal sinnvolle Größen überlegen soll,
dann sieht die Anwendung so aus.
Hier ist meine Anwendung. Kann man die sehen, ja,
ne? Genau. Jetzt muss ich die von Hand großziehen,
damit man überhaupt mal irgendwas sieht. Irgendwie nicht so sinnvoll. Das heißt also,
dieses Pack sorgt dafür, dass der J-Film quasi dieser Komponente sagt,
was ist eigentlich eine sinnvolle Größe für dich,
dass auch diese Komponente das fragt, dass er das diese fragt und diese fragt.
Und die können es alle beantworten,
weil ich ja hier zum Beispiel gesagt habe,
ich erwarte so 40 Zeichen, das System weiß,
wie groß der Fond ist, rechnet da dann irgendwas aus.
Das System weiß, wie viel Platz die Sebattens brauchen und
so weiter. Das kann also alles im Hintergrund passieren,
teilweise anhand dieser Layout managen
Gut, das ist also ganz wichtig. Und das ist
noch ganz wichtig, das vergisst man auch gerne.
Wie kann ich das denn am besten demonstrieren? Also,
wenn ich das Programm starte, wo ist meine Konsole?
Ich habe sie vorhin geschlossen. Schon, ey. Ja
, genau. Ihr seht hier so einen roten Stockbutton.
Der rote Stoppbutton ist da, solange das System läuft.
Wenn ich irgendwann sage, ich bin zufrieden, ich habe genug mit Gleitkommissaren gerechnet.
Dann beendet sich das System und dann ist auch dieser Stoppbaden weg.
Wenn ich jetzt aber diese Zeile auskommentiere und ich rede gleich
noch ein bisschen über die Zeilung.
Dann verschwindet dieser Stopper nicht. Das heißt, ich habe
das Fenster geschlossen, das Fenster ist jetzt weg und sieht es nicht mehr.
Aber das System an sich läuft noch. Also selbst wenn Equips jetzt nicht laufen würde,
ich könnte dann in eine Konsole gehen und mit Taskmanager anzeigen lassen,
da würde stehen, das System läuft noch.
Das ist irgendwie nicht so sinnvoll. Also macht man normalerweise Folgendes,
dass man bei dem J-Frame da quasi den Hauptteil der Anwendung darstellt,
also das Fenster, was geöffnet wird,
wenn man die Anwendung halt normal startet,
wir haben das Hauptfenster der Anwendung eben,
dass man da sagt, lieber J-Frame,
wenn ein Benutzer oben rechts auf dieses X klickt,
also auf dieses X, dann möchte ich,
dass die Virtual Machine von Java komplett heruntergefahren wird.
Das System soll beendet werden. Auch dazu erzähle ich mal ganz gerne eine Anekdote.
Wir hatten mal im SE1-Übungsbetrieb irgendwann ein relativ neues Projekt,
was sich schnell noch zusammengefrickelt hatte, wo ich das hier vergessen hatte.
Und das hat zu Hause bei mir wunderbar funktioniert.
Und in den Übungen gab es super viele Probleme,
weil die Studenten in Bluejay, die probieren kurz was aus,
starten das System aus, macht nicht 100 Prozent das,
was ich will, ändern irgendwas, starten das System,
haben natürlich auch immer dieses Fenster mit dem X zugeklickt,
aber das System lief im Hintergrund weiter.
Und irgendwann waren dann so 30, 40,
50 Instanzen dieses Systems liefen dann gleichzeitig.
Und irgendwann sind die Rechner dann daran
quasi zugrunde gegangen
Weil da 50 Warteschleifen quasi gleichzeitig im Hintergrund liefen und die wurden irgendwann unerträglich langsam.
Das war mir ziemlich peinlich und das lag also nur daran,
dass ich diese Zeile vergessen hatte.
Ja. Okay. Gut, ich starte mal wieder das
System. Ach ne, es ist ja noch gestartet.
Darüber hatten wir schon geredet. Okay. Ja,
das ist im Prinzip schon alles Interessante aus dieser UI-Klasse.
Also, welche UI-Komponenten brauche ich? Ich muss
sie erzeugen und ich muss sie irgendwie sinnvoll ineinander reinstecken.
Und am Ende muss ich sagen, jetzt will ich auch mal was sehen.
Ja, das ist eigentlich so die Hauptaufgabe dieser UI-Klasse.
Okay, dann gibt es eben noch so ein paar Ghetter,
dass man von außen an diese ganzen Komponenten rankommt.
Warum brauchen wir das
Weil wir uns jetzt noch gar nicht darum gekümmert haben,
was da eigentlich passieren wird und irgendwelche Buttons gedrückt werden.
Und dafür gibt es diese Werkzeugklasse. Okay, schauen wir
uns jetzt mal diese Werkzeugklasse an. Steht ja auch im
Kommentar, kümmert sich hauptsächlich um die Vertratung der Listende.
Es gibt eine Abhängigkeit zwischen Werkzeug und UI und die ist auch
immer so und wir schreiben das quasi per Konvention so vor.
Das Werkzeug kennt UI. Und nicht andersrum. Die UIs,
also erstmal sozusagen losgelöst von dem Werkzeug, wenn man so will.
Also ich könnte irgendeinem Programmierer diese Klasse in die Hand geben.
Er könnte damit alleine was anfangen,
er könnte schon so ein bisschen designen und sagen, ah,
ich hätte hier gerne andere Farben oder ich will irgendwie die Buttons größer haben oder ich will nicht,
dass das oben ist und dass unten so eine genau andersrum.
Ich will vielleicht noch irgendwie einen kleinen Hilfstext hier einblenden oder so.
Das kann man alles mit dieser einen Klasse machen,
ohne andere Klassen anfassen zu müssen. Aber andersrum,
wenn ich jetzt sage, ich will jetzt irgendwie bestimmt können,
was sollte passieren, wenn solche Buttons gedrückt werden.
Dafür brauche ich eben Zugriffe auf diese Bands. Ich muss also
irgendwie von dieser Werkzeugklasse auf Zugriff auf diese Swing-Komponenten haben,
um da irgendwelche Listen daran anhängen zu können.
Okay. Gut. Ja, also diese Zahl,
die ich hier oben eingebe, was weiß ich,
0,5 oder so, die wird sich in dem Werkzeug hier gemerkt,
das ist quasi die zuletzt eingegebene Zahl.
Am Anfang ist das null. Und jetzt ist es
zum Beispiel
Okay. So, jetzt schauen wir uns also an,
wie wird so eine, so ein Werkzeug sinnvoll initialisiert?
Das Werkzeug, er stellt sich erst mal selber diese UI,
ja, auch das ist einfach in unseren Standardkonventionen so drin.
Man kann das theoretisch auch anders machen,
dass man es hier reinreicht, ob er der Einfachheit habe,
erzeugt er sich das einfach selbst.
Gut, das ist der eine Schritt. Und jetzt müssen noch diese Listen
da angemeldet werden und auch das mache ich gerne in eigenen Methoden,
das ist irgendwie nicht alles so ein Durcheinander ist im Konstruktor,
also Erzeugung der UI und Listen da registrieren sind zwei wichtige Schritte.
Gut. So, jetzt sieht man auch,
warum wir Zugriff auf die UI brauchen
Weil ich jetzt dieser UI sage, ich brauche Zugriff auf
deinen Konvertieren-Button. Also gib mir mal quasi diesen Button,
den will ich haben. Ich will was mit dem machen
. Und was will ich mit diesem Button machen?
Ich will einen Actionlisten hinzufügen. Nur wenn das jetzt,
wenn wir das System selber programmiert hätten, letzte Woche,
dann hätten wir es nicht Ad-Actionlistener genannt, sondern füge Beobachter hinzu.
Das ist einfach nur eine andere Vokabel. Oder registriere Beobachter,
wir haben es letzte Woche genannt, ich glaube,
füge Beobachter hinzu. Was erwartet dieses Actionlistener? Wird das
irgendwie eingeblendet, wenn ich mit der Maus drüber gehe?
Ja, genau. Ihr seht das also im Kasten rechts
oben. Es erwartet einen Actionlistener L. Nur der Name L
ist ja völlig egal. Ich muss also ein Actionlistener reintun
und ich habe der Einfachheit halber einfach mal mich selber übergeben
Wie kann das sein, dass ein Gleitkomma-Werkzeug sich selber übergeben
kann an einer Stelle, wo ein Actionlistener erwartet wird?
Das ist ja vom Typsystem kann das eigentlich nicht sein.
Oder ein Gleitkomma-Werkzeug und ein Actionlistener sind doch zwei völlig verschiedene Typen.
Ja. Sie implementiert Actionlisten, das kann man hier lesen.
Ich hätte vielleicht ein bisschen weiter scrollen müssen.
Da steht's. Gleitkummer-Werkzeug implementiert das Interface-Actionlistener. Das heißt,
ich kann das Gleitkomma-Werkzeug überall dort angeben, wo ein Actionlistener erwartet wird.
Und wie sieht dieses Interface aus? Ich habe ja
den Quelltext dabei.
Was ist ein Actionlistener
Kommt ja jetzt bekannt vor. Es ist so ein
super einfaches Interface, genau wie beim Beobachter.
Ein Actionlister ist im Prinzip einfach nur ein Beobachter.
Und wie nennen wir diese Operation? Wir nennen sie nicht,
reagiere auf Änderungen, sondern wir nennen sie Action performed.
Einfach nur eine andere Vokabel. Und da wird ja noch
ein Parameter übergeben, wo man einfach gewisse Dinge abfragen kann,
werden wir uns mal gleich angucken, warum das sinnvoll ist.
Okay. Das heißt also, diese Methode,
Action performt, muss in meinem Glattgemeinwerkzeug irgendwo drin sein,
sonst würde sich ja Eclipse beschweren.
Schauen wir mal, wo ist sie denn?
Hier ist sie ja. Ja, seht ihr sie?
Hier habe ich sie implementiert. Okay, und alles,
was hier passiert ist, dass ich eine Methode aufrufe,
die heißt Verarbeiter-Eingabe. Die gucken wir uns an,
die ist, glaube ich, direkt darunter,
ja genau
Das Spannende ist jetzt aber folgendes, ich habe das gar nicht so betont.
Diese Methode Action performt wird aus meinem eigenen Code nirgendwo auf, nirgendwo aufgerufen.
Ihr werdet hier nirgendwo in dieser Klasse einen Aufruf finden, wiss.action performt oder so.
Sondern diese Methode wird dann aufgerufen von dem Swing Framework,
was ja irgendwie aus, weiß ich nicht, Mitte der 90er geschrieben wurde.
Ja, da hat man sich also irgendwann darauf geeinigt, wir besetzen dieses Interface
Action Listener in die Welt und da kannst du 10,
15, 20 Jahre später jemand herkommen,
dieses Interface implementieren und wir werden dann diesen Code aufrufen,
den Code, den es jetzt noch gar nicht gibt,
der Code,
der in der Zukunft geschrieben wird,
wenn der Knopf gedrückt wurde
Ziemlich spannendes Konzept, ja. Weil sonst, wenn das nicht so wäre,
müsst ihr ja quasi ja für jede Anwendung, die ich schreibe,
müsste ich dann jetzt in den Quelltext von Swing reingehen und sagen,
wenn der Knopf gedrückt wurde,
ruf mal bitte die Methode aus der Klasse auf.
Das wäre ja furchtbar. Das ist also eine sehr schöne,
ja, anschaulicher Vorteil dieser Entkopplung von Klassen,
dass ich sage, die Klasse Jay-Button muss überhaupt nicht wissen,
dass es diese Klasse Glattkommer-Werkzeug gibt.
Sie weiß einfach nur, es gibt ein Action-Listner und ich sage diesem Action-Listner,
ich wurde gedrückt, mach was mit dieser Information.
Okay. Das ist also wirklich toll,
muss man sich einfach mal
klar machen
Gut, also dieses Verarbeiten eingab mit, dass Scholdon letzten Endes aufgehoben werden.
Warum ich das jetzt in eine eigene Hilfsmethode getan habe,
werdet ihr gleich sehen, die wird hier noch ein bisschen länger werden.
Okay, wir sind Exception-Handling, kommen wir mal ein bisschen zur Wiederholung machen.
Was mache ich also hier? Auch hier greift die Werkzeugklasse
wieder auf die UI-Klasse. Ich sagte UI-Klasse, ich muss
mal kurz an deine Eingabe rankommen, also quasi hier dran.
Das ist also eine, ja, diese Komponente,
wo der Text drin ist und dann sage ich,
gib mir doch mal bitte den Text.
Dann habe ich irgendwie so einen String an der Hand,
mit dem ich was machen kann.
Ich weiß jetzt, was der Benutzer eingegeben hat.
Ich will ja an die Informationen irgendwie rankommen.
Und jetzt rufe ich hier so eine kleine Hilfsmethode auf,
jetzt soll ich mal ganz kurz,
man kann die Oma so nicht nur Zahlen eingehen,
sondern auch irgendwelche Summen
Diesen String 1 plus 2 plus 3 stecke ich einfach in
diese Funktion rein und dann kommt die Zahl 6 zurück.
Das müsst ihr mir jetzt einfach glauben,
wenn es euch interessiert, schaut euch den Fettext an.
Ist nicht besonders spannend, der zerhackt quasi einfach nur den
String an den Pluszeiten und addiert dann die einzelnen Apparaten.
Da kann man sich angucken, wenn man will, aber es ist jetzt nicht zwingend Spezifisches.
Okay, und dann packe ich das wieder,
ja, ich verpacke das dann in so einen Typ,
ich habe das gar nicht gesagt, den habe ich auch selber geschrieben.
Das ist quasi ein Double eingepackt in einer Klasse mit schönen,
sinnvollen Operationen, die einem zum Beispiel sagt, hey,
gib mir doch mal diese schöne String-Repräsentation zurück,
dass das nicht alles hier in dieser Swing-Klasse steht,
das will ich nicht.
Ich will, dass diese beiden Swing-Klassen sich hauptsächlich oder
nur um Zwingen kümmern
Okay. Jetzt kann es natürlich passieren, dass jemand sich oben vertut,
also dass er irgendwie auf der Tastatur ausrutscht oder so.
Falls das passieren sollte,
dann wird irgendwo in dieser Methode eine Number-Format-Acception geschmissen und ihr wisst ja,
was passiert, wenn in einem Tribuck eine Acception geschmissen wird,
dann ladent man in dem zugehörigen Catchblock und dann wird einfach nur wieder auf null die Zahl gesetzt.
Deswegen seht ihr jetzt hier wieder die Zahlen null. Vielleicht wäre es sinnvoller,
da irgendwie ein Fenster aufzumachen mit einer Fehlermeldung oder so.
Ich war da wohl ein bisschen faul. Okay,
jetzt habe ich also irgendwie intern rumgerechnet,
ich habe mir diesen Text geholt,
ich habe daraus ein Double gemacht,
aber ich habe das jetzt noch gar nicht quasi hier unten
reingesteckt,
das muss ich auch noch machen
Das passiert dann hier in dieser Methode, die ich hier aufrufe.
Also ich sorge dafür, dass diese Anzeige aktualisiert wird,
ich sorge dafür, dass diese Anzeige aktualisiert wird.
Jetzt kommen wieder zwei interessante Swing, spezifische Sachen.
Hier sage ich, dem Frame, es könnte sein,
dass sich in dieser Text-Area so massive Änderungen am Inhalt ergeben haben,
dass es vielleicht sinnvoll wäre,
dass du jetzt mal wieder deine Größe anpasst.
Das werdet ihr in euren eigenen Applikationen so gut wie nie machen.
Ich wollte das nur mal demonstrieren, dass man das
auch zwischendurch machen kann und nicht nur am Anfang.
Okay, das ist eine Zeile, die für die Benutzbarkeit
extrem toll ist. Ich markiere die einmal,
ich kommentiere die einmal aus
Also ich gebe jetzt zum Beispiel um was ein,
1 plus 2 plus 3, drücke diesen Knopf,
achtet mal noch oft auf diesen Cursor, der hier blinkt,
bitte, ich drücke jetzt diesen Knopf und der Cursor ist weg.
Das heißt, wenn ich jetzt noch was eingebe,
plus zum Beispiel, 4, 5, 6,
7, passiert jetzt nichts mehr,
weil der Fokus des Fensters ist jetzt bei diesen Button,
das heißt,
der Button kriegt jetzt diese ganzen Knopfdrücke und weiß überhaupt nicht,
was er damit anfangen soll.
Also das heißt, der Benutzer muss jetzt wieder hier reinklicken
und kann dann weiter eingehen plus 4, plus 5, plus 6.
Das ist ja irgendwie nicht so schön. Also wäre es eigentlich ganz sinnvoll,
jedes Mal, wenn dieser Button gedrückt wird oder irgendeiner,
der bei uns ist, ist eigentlich egal,
dass ich dann sage, ich will,
dass die Eingabe wieder den Fokus des Fensters bekommt.
Ich zeige euch nochmal kurz den Unterschied,
ich starte das System nochmal
Sage 1 plus 2 plus 3, der Coser blinkt hier.
Und wenn ich jetzt einmal drücke,
blinkt der Coser weiter und ich kann sofort weiter eingehen.
Das ist extrem schön für den Benutzer.
Request, Fokus in Window. Okay. Ja, hier
passiert nichts Spannendes. Ich sage einfach diesen eingepackten Dabe,
gib mir doch mal dieses interne Format zurück.
Da kommt also dieser String zurück und gib mir mal den
exakten Dezimal Wert zurück. Da kommt eben dieser String quasi
zurück. Ja, das ist jetzt nichts Spannendes.
Okay. Jetzt gibt es hier unten noch zwei Hilfsmethoden.
Die werden wir aufrufen, wenn wir uns um diese Knöpfe kümmern.
Und das können wir jetzt im Prinzip im Prinzip
eigentlich auch machen
So, es sei denn, ihr habt noch Fragen.
Ich gehe nochmal zu der interessanten Stelle. Also ich habe
hier oben gesagt, das Gleitkummer-Werkzeug ist ein Action-Missender.
Ich habe das Gleitkummer-Werkzeug hier angemeldet als Action-Lüss. Nach dem Motto,
lieber Button, falls du irgendwann mal gedrückt werden solltest,
sag doch mal bitte mir Bescheid.
Und welche Methode wird aufgerufen, wenn der Button gedrückt wird?
Diese Methode wird dann aufgerufen und ich leite dann einfach nur weiter an Verarbeitereingabe.
Aber das ist eigentlich so der Kern dieses Lissener-Konzepts.
Vielleicht mache ich einmal ganz kurz Vorbild,
dass das alles einmal sichtbar ist auf dem ganzen Bildschirm.
Also das ist relevant, das ist relevant und das ist relevant.
Gibt es dazu noch Fragen? Ist da irgendwas noch nicht
so 100 Prozent klar
Wie das mit dem Anmelden der Listen da funktioniert.
Nö. Okay. Dann mache ich einfach weiter,
solange ihr keine Fragen habt, mache ich einfach Faltung.
Genau. Was passiert eigentlich, wenn ich die anderen Buttons drücke?
Also ich gebe noch mal hier was anderes ein.
42 habe ich heute noch nicht eingegeben. Okay. Ja,
wenn ich die anderen Buttons drücke, passiert überhaupt nichts.
Das heißt, wir können uns jetzt vorstellen,
was wird im Hintergrund passieren? Im Hintergrund,
wenn ich auf diesen Partner drücke, wird der Minus-Button sagen,
ich gehe mal über die Liste aller meiner Action-Listen und
ich werde an jedem Action das noch sagen,
hey,
es ist was passiert,
ruf mal
dieses Action performt auf
Die Liste ist aber leer. Das heißt, diese Schleife
wird ziemlich schnell vorbei sein. Gut, das heißt,
es kriegt einfach keiner mit, dass hier was Interessantes passiert.
Das ist doch schade. Stellt euch vor, es drückt
hier mal auf den Knopf und keiner kriegt es mit.
Gut. Was muss ich jetzt tun, damit ich es
mitkriege? Dass zum Beispiel auf diesen Knopf gedrückt wird.
Ich habe mal eine Idee. Ich will benachrichtigt werden,
wenn jemand auf den Knopf drückt. Zwei Leute melden sich,
warten mal so ein bisschen, dass dann noch mehr Leute
die Idee haben, drei Leute haben eine Idee, vier.
Der fünfte kriegt den Zuschlag. Du bist,
glaube ich,
der fünfte
Wir werden einfach bereit. Wir wollen uns diesen Backen holen,
ne? Ganz, ganz gucken, wie der Button heißt.
Vorgänger-Button. Den, ne? Okay. Mhm. Genau
. Okay. Jetzt kriege ich also Bescheid, wenn dieser
Knopf gedrückt wurde. Das versuche ich mal. Das heißt,
wenn ich jetzt hier raufdrücke auf diesen Button,
Passiert exakt dasselbe, als würde ich auf diesen Band drücken.
Und diese Bands unterscheiden sich jetzt also in ihrer Funktionalität überhaupt nicht.
Ich habe ja jeweils gesagt, sag mir bitte Bescheid,
wenn der gedrückt wurde. Sag mir bitte Bescheid,
wenn dieser andere Knopf gedrückt wurde. Das heißt,
beide Buttons werden, ja, völlig unabhängig voneinander,
wenn sie gedrückt werden, mir Bescheid sagen.
Das heißt, es wird diese Methode aufgerufen und
in dieser Methode werde ich diese Methode aufrufen.
Das wäre irgendwie nicht so sinnvoll, dass ich in beiden Fällen
dasselbe tue. Wie könnte ich denn da jetzt unterscheiden?
Hast du eine Idee? Oder du denkst noch nach
Ja. Also du würdest statt Wiss was anderes übergeben wollen,
da kommen wir später noch zu, jetzt haben wir eine andere Idee.
Überall, die Bands sind voll geheilt, die wieder fachlos hier ist.
Überall aufgebaut, es gibt ein paar Grauen, daran halten wir.
Wenn Assistent haltet, ist der Verarbeiten, Verantwortung,
wie ich, wie mein Bruder,
wie er die vierte Tat auch
Die ich halt auf meinem Foto verändere.
Genau, sehr schön. Ich versuche nochmal ganz kurz zusammenfassen,
was du gesagt hast, war alles, richtig?
Wir können ja einfach in dieser Methode Action performen,
dieses Event fragen, wer hat euch denn ausgelöst?
War es der Konvertiere-Button, der dich ausgelöst hat?
War es dieser Button? Dann sollst du nach wie vor
dieses Verarbeitereinkommen machen. Während wenn es dieser Button war,
dann sollst du diese Methode aufrufen,
die irgendwo ganz unten in der Klasse war, Sätze, Vorgänger.
Das kann man einfach ganz stumpf mit einem IF machen.
Warum nicht? IF kennen wir schon seit Woche 1, SE1.
Es ist immer wieder nützlich. Also, Event. Wie
heißt denn diese Methode, mit der ich anschauen kann,
wo das herkommt? Ah, get source.
Source heißt also wie Ursprung oder Quelle, wo kommt das
Event her
Ja, und jetzt vergleiche ich das einfach. Ist es
ui.getconvertiere-Button? So, und wenn es der Button ist,
dann würde ich das machen, was ich vorher auch gemacht habe.
Ansonsten. Ja, ach, ich will das nicht
mehrfach abfragen, die Zahlen sind noch so.
Ich tue es mal eine eigene Variante kurz, ja.
Finde ich irgendwie persönlich hübscher. So. You I get Vorgängerbutton
. Wenn also der Vorgänger der Auslöser dieses Events ist.
Wie heißt die Methode? Gucke ich mal
ganz kurz
Sätze Vorgänge. So, ne? Tja. Das probieren
wir einmal ganz kurz. Kleine, inkrementelle Schritte hier.
Also, 0,1. So. Und das ist jetzt ja sogar fachlich
ganz spannend. Was ist denn der Vorgänger von 0,1?
Ich bin ja letztes Jahr so ein bisschen durcheinander gekommen.
Also man kann sich einfach überlegen,
wie weit ist denn diese Zahl von der 0,1 weg?
Sie ist ja zu groß. Sie ist ja irgendwie um fünf an
dieser Stelle zu groß. Das ist diese Stelle ungefähr hier.
Kann man sich das merken, da wo dieses V ist von Java?
Ist das um fünf zu groß? Und wenn ich jetzt
diesen Button drücke, sieht man, Jetzt steht hier eine Eins.
Ich müsste also jetzt noch neun drauf addieren quasi oder acht,
zwei, sechs, sechs, sechs, sieben und so,
ja, aber ungefähr neun an der Stelle, um zur Eins zu kommen.
Das heißt also, diese Zahl,
wenn man sich mal optisch vorstellt, hier ist die Eins,
die 0,1, ja, dann ist diese Zahl,
die er wählt, ein bisschen zu groß, aber die Zahl,
die zu klein ist, ist ungefähr doppelt so weit weg,
ja,
so ungefähr so ist das Verhältnis.
Ja, man kann sich also entscheiden,
will ich ein bisschen zu viel haben oder doppelt so viel zu wenig?
Und da sagt der Computer natürlich, dann nehme ich lieber
ein bisschen zu viel. Das kann man also hier ganz nett sehen,
warum er das aufrundet,
statt abrundet,
Ich glaube, das ist der eine, der weggekommen ist.
Das wird schon besonders, wenn man viele Papiere ausbaut,
hat es jeder bekannt. Ja, du fragst,
ob man das mit dem Switch machen kann.
Ich befürchte, dass es nicht gehen wird,
weil Switches nur funktionieren über primitive Typen und über Strings.
Und über ihn namens, die kennt ihr aber nicht.
Aber ich kann nicht sozusagen sagen, ich habe eine Objektreferenz und
ich will sie gegen zehn andere Objektreferenzen mit dem Switch vergleichen.
Das geht leider nicht im Genre. In JavaScript geht es
. Aber das ist eine andere Programmiersprache. Hat nur zugänglich
dieselben vier Buchstaben am Anfang. Okay. Genau,
aber du kommst schon in die richtige Richtung.
Diese langen EFLs-Ketten sind ja irgendwie nicht so schön.
Aber wir programmieren das jetzt noch einmal ganz kurz zu Ende.
Wir wollen das also auch für den dritten Button noch haben
Das ist jetzt ja keine schwarze Magie. Nachfolger-Button.
So. Und da sage ich dann eben Sätze, Nachfolger.
Genau. Okay, machen wir das nochmal ganz kurz.
Also mit diesem Minus komme ich in immer kleinere Regionen,
sehr schön und mit dem Plus.
Oh, wow. Wieso passiert jetzt nichts?
Wir haben uns gar nicht eines mit dem Arm gemeldet.
Ah, danke. Wir haben den Knopf noch nicht als Wissen angemeldet.
Toll. Hier, ne? Ich finde das immer super,
dass die Leute Quelltext, die backen könnte,
gar nicht sichtbar ist
Also, Wahnsinn. Nachfolger. Okay. Neuer Test.
Genau. Ah ja. Sehr schön. Und jetzt hier
wird es wieder größer. Ja. Und was ich noch...
Was ich noch ganz kurz demonstrieren wollte, ist Folgendes.
Ich habe den Button eigentlich nur deswegen eingebaut,
weil mich irgendwann mal interessiert hat, was ist eigentlich die kleinste Double-Zahl,
die es gibt?
Also, es gibt natürlich minus unendlich und alles.
Aber wenn ich jetzt von null quasi ausgehe,
was ist dann die nächstgrößere Zahl
Quasi die kleinste, positive Zahl, die es gibt.
Das ist ja quasi der Nachfolger von der Null.
Und das ist auch der Grund, warum ich gesagt habe,
dass Swing ab und zu mal dieses Fenster größer machen soll.
Ihr könnt euch ja so vorstellen, zwei hoch minus 1022
müsste ja ungefähr 10 hoch minus 300 oder so sein.
Okay. Aber das Lustige ist,
dass diese Zahl enorm viele Ziffern hat.
Ja. Könnt ihr euch vielleicht mal überlegen, woran das liegt.
Es ist einfach eine Eigenschaft von Float und Table.
Hier seht ihr
das 10 hoch minus
Wenn das Fenster jetzt, wenn ich ihm nicht gesagt hätte,
mach dich mal größer,
dann hätte er irgendwie das hier angezeigt und dann hätte ich diese relevante Information,
dass es 10 hoch minus 324 ist, gar nicht gesehen,
habe ich gedacht, ach so, die kleinste ist halt,
es gibt jetzt irgendwie 4,9.
Ja, das wäre irgendwie nicht so sinnvoll gewesen, fachlich.
Ja. Okay, oh, ich habe nur noch 5
Minuten, da muss ich jetzt mal ein bisschen priorisieren.
Wir machen vielleicht noch, ja, die eine Sache ist wichtig,
die machen wir. Also. Dieser Punkt,
der gerade von einem Kommilitonen angesprochen wurde, das ist,
stell dir mal vor, wir haben irgendwie 10 Buttons,
dann hat man so eine lange Leiste von EFLs,
ist ja irgendwie nicht so hübsch,
kann man da nicht was anderes machen
Komisch ist ja, dass wir hier in allen drei Fällen uns selber als Listener anmelden.
Jetzt hatten wir ja schon letzte Woche gesehen,
bei diesen Iteratoren, dass man Klassen in Klassen schachteln kann.
Das heißt, man könnte sich überlegen,
kann ich nicht für den Konvertieren-Button eine eigene Listener-Klasse schreiben,
für diesen Button eine eigene Listener-Klasse.
Und für diesen Button eine eigene Listener-Klasse. Und dann ist eben nicht
ein Listener-Objekt, was von drei verschiedenen Buttons befeuert wird,
sondern jeder Button hat sein eigenes Wissener-Objekt.
Das heißt also, wenn dieses Listener-Objekt angestoßen wird,
weiß es alles Glas, kann nur von dem Button kommen,
wenn dieses Listener-Objekt angestoßen wird, weiß es ist alles klar,
es kann nur von dem Button kommen.
Das wäre, glaube ich,
deutlich einfacher
Zumindest, was heißt einfach? Es ist mehr Quelltext,
aber wir brauchen das Impfen nicht mehr.
Ich zeige euch mal, wie das geht. Machen Sie
mal wieder privat, das ist ja Implementation zu teilen.
Nennen wir das mal konvertiere, listener. So ähnlich wie gesagt,
mit dem Iterator, da gehen wir es ja auch.
Da haben wir sie. Was soll passieren, wenn
der konvertiere Button gedrückt wird? Verarbeitereingabe soll dann passieren,
ne? Verarbeite Eingabe. So. Und dieses Event brauche ich
noch nicht mehr. Ich habe immer so eine Namenskonvention,
Parameter, die ich nicht brauche, nenne ich Ignor,
dass sich niemand darüber wundert,
dass sich den Parametern nicht benutze.
Okay. Und solche Klassen kann ich auch
schreiben für Vorgänger und Nachfolger
Ich kopiere mir das einmal ganz kurz, 1,
2, 3. Das hier ist der Vorgängerlistener. Gänge,
alles in na, das hier ist der Nachfolgerlistener.
Und was soll da jeweils passieren? Sätze, Vorgänger, ne?
Sätze, Vorgänger. Und hier soll passieren, Sätze,
Nachfolger, Sorgen. Ich benutze diese Klassen aber noch nicht.
Clips warnt mich erzählt, dass ich diese Klassen gar nicht benutze.
Stimmt, die muss ich jetzt ja hier benutzen.
Was muss ich denn da jetzt reinschreiben, wenn ich nicht sagen will,
das Gleitkomma-Werkzeug an sich soll der Listener sein, This,
sondern ich brauche ein Exemplar von Konvertiererlistener.
Wie kriege ich ein Exemplar der Klasse Convertiererlistener
Ich habe eine Klasse und ich brauche ein Exemplar von, ja.
Genau. Von der Tiere lassen wir. So,
das kann ich ja unten genauso machen. New Nachfolge,
nee, Entschuldigung, Vorgänger. Vorgänger, das ist immer.
Und Jugendnachfolgerlisten. Und jetzt können wir ihn ein bisschen aufräumen.
Jetzt kann ich sagen, ich brauche das hier nicht mehr.
Das Werkzeug an sich will gar nicht mehr befeuert werden von
diesen Events. Ich habe jetzt diese eigenen Wissen dafür.
Und dann sage ich hier oben natürlich auch,
ich implementiere jetzt nicht mehr
das Interface
Das heißt, es ist klar, Gummerwerkzeug kümmert sich jetzt eben,
wie gesagt, nicht mehr selber drum,
sondern erzeugt sich diese drei Objekte dieser speziellen Listener-Klassen.
Toll. Müssen wir ausprobieren, ob das funktioniert?
Gehen wir wieder irgendwas ein? Jo, minus, scheint zu funktionieren.
Gut, plus funktioniert auch immer noch, ne?
Das ist doch nicht schlecht. Okay. Jetzt haben wir
noch drei Minuten. Was mache ich in drei Minuten mit euch?
Diese Listener-Klassen, ja, wo brauche ich die eigentlich?
Also zum Beispiel diese Klasse brauche ich genau hier an dieser
einen Stelle,
Und diese Klasse brauche ich genau hier an dieser einen Stelle.
Es gibt keine anderen Stellen, wo ich diese Klasse brauche.
Wenn ich suche nach New konvertiere, müssen,
dann werde ich nur diese eine Stelle finden.
Und da haben sich die Java-Sprachdesigner irgendwann überlegt,
schon ein paar Jahre her, wäre es nicht ganz nett,
wenn man die Definition dieser Klasse an die Stelle verlagern könnte,
wo ich sie brauche, wo ich sie instanzieren will.
Kann man machen. Ja, ich mache das jetzt mal
anhand des Kommentarelisten als Beispiel. Also wir nehmen mal an,
es gibt diesen Konvertierelisten da gar nicht, ja.
Sonntag sieht jetzt wie folgt aus. Ich sage New Actionlisten
, ne
Klammer auf, Klammer zu. Klammer auf, Klammer zu
. Formatieren. Und so. So. Einmal Handtuch,
wer findet, dass das komisch aussieht? Ja,
das ist sehr merkwürdig, weil hier werden so viele Konzepte durcheinandergewürfelt.
Also, noch mal kurz erklärt. Dieses Ad-Action-Lisner erwartet eine
Referenz vom Typ Action-Lisnder. In diesem Fall habe ich einfach
eine Klasse erzeugt, die ich vorher weiter oben definiert habe.
Und hier sage ich, Ich brauche dieser Klasse eigentlich gar keinen Namen zu geben.
Also das hier ist der Rumpf der Klasse. Wenn ihr
euch diesen Rumpf anguckt, dann sieht er überhaupt nicht anders aus,
als sie rum, für die ihr hier seht.
Geschweifte Klammer auf, dann kommen hier so ein paar Methoden,
geschweifte Klammer zu. Das ist der Rumpf der Klasse.
Jetzt würde man normalerweise über den Rumpf, der Klasse,
würde man den Kopf der Klasse erwarten, wo dann steht,
Klaas, sowieso Listener, Implements, Actionlistener.
Das sparen wir uns jetzt. Wir sagen einfach nur,
wir nennen das Interface und schreiben dahinter Klammer auf,
Klammer zu, das braucht man einfach.
Und schreiben direkt das New davor. So isoliert sich das irgendwie merkwürdig aus,
weil wir ja gelernt haben, man kann doch von Interface,
also man kann hier schreiben, New Interface, das geht nicht.
Aber was man machen kann, ist zu sagen,
ich brauche eine Klasse, die dieses Interface implementiert,
das ist der Rumpf der Klasse und ich möchte,
dass du von dieser Klasse in ein Exemplar erzeugst
Jetzt habe ich vergessen, in Action performt, was zu machen.
Was muss da getan werden für Arbeitereingaben? Für Arbeitereingabe.
So. Und das da zur Folge, dass ich diese Klasse,
Entschuldigung, diese Klasse nicht mehr brauche, kann ich also löschen.
Und genau dasselbe mache ich jetzt auch mal mit den beiden,
einfach so zum grünen Abschluss.
Machen wir das einmal hier. Geht ein bisschen kürzer,
wenn ich sage, New AL, Eclipse ist ja immer ziemlich schlau.
Dann muss hier gesagt werden, Sätze, Vorgänger.
Hops. So. Und hier genauso New AL.
Und da sage ich dann Sätze
Nachfolger. Und jetzt kann ich wieder diesen ganzen Klaladderatsch
hier löschen. Nur jetzt hat man den Vorteil,
dass zumindest die Anmeldung dieser drei Listener auf eine Bildschirmseite passt,
das ist doch nicht schlecht.
Okay. Gibt es noch Fragen zu Actionlisten an?
Ja, Zeit verging schon wieder viel zu schnell.
Ich freue mich auf nächste Woche