Kurt Nørmark ©
Department of Computer Science, Aalborg University, Denmark
September 2001
Abstract Previous lecture Next lecture Index References Contents | Grafiske brugergrænseflader er et væsentligt emne, hvis man ønsker at skriver 'moderne' programmer.
Desværre er dette aspekt af et program også et af de vanskeligste at lave. Der er store forskelle fra
sprog til sprog, og ofte er det endvidere maskinafhængigt, hvordan man angriber programmering af brugergrænsefladen.
Lad os i den forbindelse bemærke, at Java bidrager med en (i princippet) maskin-uafhængig teknik til programering af brugergrænseflader. Her vil vil primært koncentrer os om de væsentligste generelle karakteristika ved objekt-orienteret programmering af brugergrænseflader. Sekundært vil vi se på, hvordan det kan ske i Java. |
Introduktion til grafiske brugergrænseflader |
Oversigt over Java's udvikling af brugergrænseflader Slide Note Contents Index References Speak | Vi giver her en kort oversigt over de versioner, som Java har gennemlevet hvad angår faciliteter til udvikling af grafiske brugergrænseflader |
|
Litteratur om grafiske brugergrænseflader Slide Note Contents Index References Speak | Vi starter med en kort karakterisk af litteraturen, der beskriver hvordan man laver brugergrænseflader i et Java program |
Hvis man læser første udgave af lærebogen 'Java Software Solutions' af Lewis of Loftus er det kapitel 10 som giver en introduktion til grafiske brugergrænseflader Hvis man læser første udgave af lærebogen 'Java Software Solutions' af Lewis of Loftus er det kapitel 10 som giver en introduktion til grafiske brugergrænseflader |
|
Applets |
Introduktion til applets Slide Note Contents Index References Speak | Applets spiller ikke den store rolle på dette kursus. Vi vil dog i denne lektion præsentere nogle eksempler på brugergrænseflader via applets. (Det er naturligvis fristende at bruge denne mulighed for at kunne inkludere brugergrænsefladerne direkte i en Internet browser). Her ser vi først på nogle generelle egenskaber af Java applets |
The concept applet: En applet er et Java program som kan afvikles i en 'Java enabeled' Internet browser | En stor del af den almene interesse for Java stammer fra applet ideen. Moderne Internet browsere indeholder en Java fortolker og et Java bibliotek. Derved bliver det muligt for browseren at udføre et Java program, som kan modtages fra en vilkårlig maskine på nettet. | |
The concept applikation: En applikation er en kontrast til en applet | En applikation er et Java program, som ikke er udviklet med henblik på afvikling i en browser. Langt de fleste programmer, som vi interesserer os for på dette kursus, er applikationer. I denne lektion vil vi dog vise et par applets, først og fremmest fordi vi hermed på en let måde kan inkludere en kørende brugergrænseflade i online versioner af noterne |
Vi vil senere studere de forskellige brugergrænseflade komponenter i Java, og vi vil ved denne lejlighed støde på Applets igen |
|
Applets i denne lektion Slide Note Contents Index References Speak |
|
En applet vises på en HTML side via en særlig applet tag |
Program: En simpel HTML side som indeholder en applet. Længere fremme i denne lektion vil
vi bl.a. studere denne applets. |
|
|
Arkitektur af et program med grafisk brugergrænseflade |
Hvem kalder hvem? Slide Note Contents Index References Speak | Vi vil indledningsvist se på en vigtigt princip, som dukker op i flere sammenhænge når vi arbejder med grafiske brugergrænseflader i Java. |
|
|
Model, syn og inputkontrol Slide Note Contents Index References Speak | Ideerne på denne side kan ledes tilbage til Smalltalk's model, view controller tankegang. |
|
|
Image series: Cyklus i interationen mellem syn, inputkontrol og model. | Cyklus i interationen mellem syn, inputkontrol og model. |
Image no. 1. Brugeren påvirker et element af brugergrænsefladen (synet) | ![]() |
Image no. 2. Der oprettes et eventObjekt som repræsenterer hændelsen | ![]() |
Image no. 3. Hændelsen overføres til en metode i kontrol objektet, som abonnerer på hændelsen | ![]() |
Image no. 4. Metoden i kontrolobjektet aktiverer beregningen i modellen (her programObjektet) | ![]() |
Image no. 5. Programobjektet giver feedback tilbage til synet | ![]() |
Eksempel: Div mod calculator Slide Note Contents Index References Speak | Vi viser allerede nu et principielt og simpelt eksempel på model, view og control klasser. På denne måde bliver diskussionen konkret på et tidligt tidspunkt. Der vil være detaljer, som du ikke forstår på nuværende tidspunkt. Vi vender tilbage til detaljerne i løbet af lektionen. Det vigtigste er for nærværende organiseringen af et program med en grafisk brugergrænseflade i de nævnte tre dele: model, syn og inputkontrol |
Applet. En simpel applet som beregner x div y og x mod y af de to tal x og y i inputfelterne |
Program: Model klassen.
Denne klasse foretager beregningen af kvotient og resten. Endvidere lagrer et objekt af klassen
seneste input og output i instansvariable. Med blåt ser vi det sted, hvor vi registrerer hvilket
objekt som viser resultatet af beregningen. Med rødt ser vi det sted, hvor synet bliver opdateret.
|
|
Program: View klassen.
Denne klasse udvider Applet, som tillader os at afvikle et Java program i en Internet Browser.
Det er en instans af denne klasse som starter programudførelsen, når vi afvikler et Java program
som er en Applet. Vi ser, at der instantieres et model og et inputkontrol objekt (med rødt).
Dernæst laver vi de enkelte dele af den grafiske brugergrænseflade (vist med brunt).
I init metoden associerer vi inputkontrol objektet 'listener' til de to inputfelter (vist med blåt ).
Endelig ser vi, at vi tilføjer de fem grafiske elementer til brugergrænsefladen med add metoden (vist med lilla).
Metoden main (nedtonet med gråt) gør det muligt at køre programmet som en applikation. I en applet bruges main ikke.
|
|
Program: Controller klassen.
Denne klasse implementerer ActionListener interfacet (vist med grønt), som reagerer på 'Return' indtastet i inputfeltet.
Når der via et af de to tekstfelter 'afsendes en tekststreng' ser vi at modelobjektets doCalculate metode
bliver aktiveret på de to tal i inputfelterne (vist med rødt).
|
|
Program: Det samlede Div Mod Calculator program.
| ![]() |
Image series: En typisk interaktion mellem view, model og controller. | En typisk interaktion mellem view, model og controller. |
Image no. 1. Der skabes et view, som i dette tilfælde er en applet | ![]() |
Image no. 2. I dette simple tilfælde skaber view'et model objektet og controller objektet | ![]() |
Image no. 3. View objektet opretter fem brugergrænseflade komponenter | ![]() |
Image no. 4. View objektet sender en besked til dividend om at registrere controller som 'action listener' | ![]() |
Image no. 5. View objektet sender en besked til divisor om at registrere controller som 'action listener' | ![]() |
Image no. 6. View objektet tilføje de fem brugergrænseflade komponenter til sig selv | ![]() |
Image no. 7. Brugeren opererer nu på brugergrænsefladen. Controlleren modtager en actionPerformed besked | ![]() |
Image no. 8. Controlleren sender getDivisor til view objektet, for at trække divisor ud af tekstfelterne | ![]() |
Image no. 9. View objektet udtrækker divisor teksten af divisor objektet. Teksten konverteres til et tal | ![]() |
Image no. 10. Controlleren sender getDividend til view objektet, for at trække dividend ud af tekstfelterne | ![]() |
Image no. 11. View objektet udtrækker dividend teksten af dividend objektet. Teksten konverteres til et tal | ![]() |
Image no. 12. Controlleren sender beskeden doCalculate til model objektet | ![]() |
Image no. 13. Model objektet foretager beregningen af kvotient og rest ved at sende beskeden divMod til sig selv | ![]() |
Image no. 14. Efter at have skabt objektet output sender model objektet beskeden showResult til view objektet | ![]() |
Image no. 15. View objektet sender beskeden setText til quotient for at vise kvotient resultatet | ![]() |
Image no. 16. View objektet sender beskeden setText til rest objektet for at vise rest resultatet | ![]() |
Exercise 12.1. En meget simpel calculator | Ideen med denne opgave er at udvide brugergrænsefladen af programmet, som beregner
kvotienten og resten af to tal. Udvidelsen består i at tilføje en Liste
komponent, hvor man kan angive et par af operationer, som skal udføres på de to tal i inputfelterne.
I den oprindelige version vil applikationen udregne kvotient og rest af tallene.
De nye operationer kan f.eks. være addition og subtraktion, multiplikation og division med videre, samt
naturligvis de oprindelige (vær selv kreativ).
Programmet skal beregne resultatet (de to operationer på de angivne input) når der tastes retur i inputfeltet
eller når der udvælges et element i operationslisten.
Det er en pointe at gennemføre forandringerne af det oprindelige program så både model, syn og input kontrol objektet afspejler den generaliserede dialog. Eksempelvis skal rollerne af output (sum, differens, produkt ...) udskrives korrekt. Det vil være mest oplagt at gennemføre forandringerne inden for AWT. Næste gang vil en af opgaverne gå ud på at ændre løsningen på denne opgave til Swing. Afprøv gerne følgende variationer:
Brug programmet fra noterne på denne fil som udgangspunkt for opgaveløsningen. |
Exercise 12.2. Grafisk brugergrænseflade i projektet | I de fleste projekter vil der være behov for en grafiske brugergrænseflade.
I opfordres til at overveje hvilket behov I har i jeres projekt. Gennemfør nogle
indledende eksperimenter, hvor I programmerer (dele af) en første version af brugergrænsefladen.
Brug denne lejlighed til at få førstehånds erfaring med nogle af de brugergrænseflade Komponenter, som
I ikke indtil nu har haft berøring med. Overvej specielt den overordnede organisering af jeres program i model, view og control objekter. |
|
Ansvarsfordeling i eksemplet Slide Note Contents Index References Speak | Her vil vi fremhæve ansvaret og ansvarsfordelingen mellem model, view og controller objekterne i eksemplet ovenfor |
Vi vil senere (i forbindelse med Observer mønstret) vende tilbage til vores observation om, at modellen har et for stort kendskab til synet Det er kun i eksemplet at synet opretter model og control objekterne. Dette er på ingen måde naturligt, blot behændigt for at få startet det hele op Control objektet har et naturligt behov for at kunne aflæse nogle egenskaber fra synet samt at kanalisere disse over i modellen med henblik på gennemførelse af nogle beregninger |
Brugergrænseflade komponenter i AWT |
Syn i Java: Komponenter Slide Note Contents Index References Speak | En præsentation af en model sker i Java gennem en komponent. En komponent er altså en bestanddel af synet i en brugergrænseflade. Komponenter er begrebsligt organiseret i et klassehierarki. Endvidere indgår komponentobjekterne i et et aggregeringshierarki, med dele og helheder. Det er meget vigtigt at skelne mellem disse to forskellige hierarkier. Vi ser eksempler på begge i det følgende. |
|
|
|
Komponent specialiseringshierarkiet i AWT Slide Note Contents Index References Speak | På denne side viser vi komponent begrebshierarkiet i Java. Dette hierarki viser, hvordan komponent klasserne i Java arver fra hinanden (specialisering) |
Eksempel: Farveblander Slide Note Contents Index References Speak | Vi ser nu på et nyt og lidt mere kompliceret program med en grafisk brugergrænseflade. Her vil vi møde nogle af komponenterne fra hierarkiet ovenfor - men dog langt fra dem alle. |
Applet. Et program som gør det muligt at blande en farve ud fra farvens RGB (røg, grøn, blå) sammensætning. Programmet viser også den hexadecimale streng, som anvendes til angivelse af farver i en Internetbrowser (i HTML) |
|
Aggregering af komponenter i farveblanderen Slide Note Contents Index References Speak | En brugergrænseflade består af en række brugergrænseflade Komponenter (objekter), som indlejres i hinanden. Det er vigtigt ikke at sammenblande komponenternes specialiserings hierarki med aggregeringshierarkiet, som omtales på denne side |
|
Aggregeringen af komponenter i farveblander brugergrænsefladen:
|
Panels Slide Note Contents Index References Speak |
|
Eksempler fra farveblander programmet |
Program: Et specialiseret Panel, som indeholder andre komponenter.
Vi ser at der tilføjes tre primitive brugergrænseflade komponenter (fremhævet med rødt).
Dette er et bidrag til opbygningen af aggregeringshierarkiet af komponenter
|
|
Program: Instantiering og anvendelse af ColorPanel klassen i klassen ColorPresenter.
Vi ser tre instantieringer og tilføjelsen af disse til applet'en.
Dette er endnu et bridrag til opbygningen af aggregeringshierarkiet af komponenter
|
|
|
Scrollbars Slide Note Contents Index References Speak |
|
Eksempler fra farveblander programmet |
Program: Sliders i ColorPanel klassen.
Sliderens maksimum og 'incrementer' bliver sat til konkrete værdier (vist med rødt)
hvorefter slideren bliver tilføjet til panelet (vist med blåt)
|
|
Program: Instantieringen af Scrollbar objekter i ColorPresenter klassen.
|
|
|
Canvas Slide Note Contents Index References Speak |
|
Eksempel fra farveblander programmet |
Program: Klassen ColorBlop er en specialisering af Canvas.
Specialiseringen er meget simpel og ikke særlig illustrativ hvad angår mulighederne for at tegne egne dele af en brugergrænseflade.
Det er paint metoden (vist med blåt) som tegner på selve canvasen
|
|
|
Menu begreber Slide Note Contents Index References Speak | Menuer er, som bekendt, meget nyttige i mange sammenhænge i en grafisk brugergrænseflade. Vi ser her nærmere på selve menubegrebet. På næste side ser vi på menuer i AWT. |
The concept menu: En menu er en brugergrænseflade komponent der tillader os at vælge én ud af flere muligheder, typisk med henblik på igangsætning af en bestemt handling | En menu viser en række muligheder for os, ud fra hvilke man kan vælge en (eller måske flere) muligheder. Efter man har valgt et menupunkt vil det som regel afstedkomme igangsætning af en eller anden handling | |
The concept menu element: Et menu element er en bestanddel af en menu, som kan udvælges | En menu består af såkaldte menu elementer |
|
Med en lineær menu mener vi en menu, hvor menu elementerne blot er ordnet lineært i forhold til hinanden En afsnitsinddeling i en lineær menu (som en vandret streg) gør det muligt på en simpel måde at gruppere menu elementer En hierarkisk menu kan siges at indeholder undermenuer. Vi har dog valgt at formulere det rekursivt ved at lade et menu element være en menu i sig selv. Det rekursive består naturligvis i, at en del af en menu (et menuelement) selv kan være en hel menu I menuer med frit layout er det muligt at organisere menu items i et eller andet todimensionalt mønster |
Menuer i AWT Slide Note Contents Index References Speak | Efter at have set på nogle generelle menu begreber vil vi nu studere Java's menu begreb, som er ganske veludviklet |
Menuer håndteres vidt forskelligt på de forskellige platforme, hvor Java er implementeret. Dette siges at være årsagen til, at menuer ikke arver fra klassen Component |
|
Program: Uddrag af klassen MenuWindow fra The Java Tutorial.
Det viste uddrag er en del af konstruktoren i klassen.
Vi ser først erklæring af en lang række Menu relaterede instansvariable (med brunt).
Dernæst instantieringen af MenuBar og dets tilknytning til denne frame med setMenuBar(mb) (med rødt)
Sidst ser vi instantieringen af menu 1, tilføjelse af denne til menubaren mb, samt tilføjelse af
to MenuItems til menu (med lilla)
|
|
Program: Hele klassen MenuWindow fra The Java Tutorial hvoraf ovenstående er et uddrag.
| ![]() |
|
Andre komponenter Slide Note Contents Index References Speak | Vi har ikke i denne lektion gjort et forsøg på at dække detaljerne i alle Java AWT brugergrænseflade komponenter. Her lister vi dem, vi ikke har dækket |
|
Det skal bemærkes, at menuer ikke er Komponenter, jf. specialiseringshierarkiet af Java komponenter, som vi har set på tidligere |
|
Ansvarsfordeling mellem model, syn og inputkontrol |
Ansvaret for opdatering af brugergrænsefladen Slide Note Contents Index References Speak | Vi vil her studere, hvordan opdateringen af brugergrænsefladen finder sted, når der er sket forandringer i den underliggende model. Vi skal i denne forbindelse have øjnene åbne for, at en model kan præsenteres i to eller flere syn. |
|
Model ansvarlighed for opdatering af brugergrænsefladen udgør den naive løsning på problemet. Hvis der er flere samtidige syn på modellen belaster det den indre programlogik på en meget uheldig måde. Endvidere bliver der for stor viden om brugergrænsefladen i selve modellen, med deraf følgende vanskeligheder, hvis der skal laves forandringer i brugergrænsefladen på et eller andet tidspunkt Det er måske at tage munden lidt fuld, når man siger at brugergrænsefladen opdaterer sig selv. Men vi ønsker at frigøre modellen for ansvaret for den direkte opdatering af brugergrænsefladen, herunder evt. multiple syn på modellen. Modellen skal have så lidt viden om de forskellige syn på modellen, som afspejles af brugergrænsefladen. Hermed bliver det meget lettere at ændre på brugergrænsefladen, når og hvis det bliver nødvendigt |
|
Observer mønstret mellem model og view Slide Note Contents Index References Speak | Vi vender her tilbage til vores første eksempel. I stedet for at lade modellen opdatere synet direkte sender vi nu et update signal til synet, som så indhenter information om ændringen hos modellen. Baseret på denne information opdaterer synet sig selv |
Applet. En simpel applet som beregner x div y og x mod y af de to tal x og y i inputfelterne. Denne brugergrænseflade er identisk med den tidligere viste. Dog er det uderliggende program lidt anderledes, idet det er baseret på observer mønstret |
Program: Model klassen med tilkobling og notification af observer.
Vi ser at nu er klassen en Observable (fremhævet med blåt).
I konstruktoren kobler modelobjektet en observatør på sig selv (vist med rødt).
Lige efter beregningen af kvotient og rest sender dette objekt beskederne setChanged og notifyObservers til sig selv.
Dette afstedkommer, at der afsendes en update besked til alle de observers, som abonnerer på forandringer.
(I de klasser vi viser her, kan vi ikke se det sted update bliver sendt. Det sker i notifyObservers, som jo
er implementeret i Obervable, hvorfra modelklassen DivModCalculator arver).
I dette eksempel er der kun ét objekt, som har gjort dette.
Beskeden getResult bliver sendt af observeren for at finde ud af, hvad der egentlig er sket på model objektet
|
|
Program: View klassen med ny update metode.
Observatøren implementerer nu Interfacet Observer, som har én metode: update (vist med blåt).
Metoden update (vist med lilla) trækker information tilbage fra modellen om forandringerne i dette objekt.
|
|
Program: Controller klassen (uændret).
Controlleren er ikke ændret som følge af indførelse af en observer.
|
|
Image series: En typisk interaktion mellem view, model og controller - her med observer mønstret. | En typisk interaktion mellem view, model og controller - her med observer mønstret. Vi har tidligere set på de samme billeder. De nye elementer, som involverer observer mønstret, er mærket ned 'Ny' i øverste venstre hjørne af billedet |
Image no. 1. Der skabes et view, som i dette tilfælde er en applet | ![]() |
Image no. 2. I dette simple tilfælde skaber view'et model objektet og controller objektet | ![]() |
Image no. 3. Model objektet tilkobler et observer objekt | ![]() |
Image no. 4. View objektet opretter fem brugergrænseflade komponenter | ![]() |
Image no. 5. View objektet sender en besked til dividend om at registrerer controller som 'action listener' | ![]() |
Image no. 6. View objektet sender en besked til divisor om at registrerer controller som 'action listener' | ![]() |
Image no. 7. View objektet tilføje de fem brugergrænseflade komponenter til sig selv | ![]() |
Image no. 8. Brugeren opererer nu på brugergrænsefladen. Controlleren modtager en actionPerformed besked | ![]() |
Image no. 9. Controlleren sender getDivisor til view objektet, for at trække divisor ud af tekstfelterne | ![]() |
Image no. 10. View objektet udtrækker divisor teksten af divisor objektet. Teksten konverteres til et tal | ![]() |
Image no. 11. Controlleren sender getDividend til view objektet, for at trække dividend ud af tekstfelterne | ![]() |
Image no. 12. View objektet udtrækker dividend teksten af dividend objektet. Teksten konverteres til et tal | ![]() |
Image no. 13. Controlleren sender beskeden doCalculate til model objektet | ![]() |
Image no. 14. Model objektet foretager beregningen af kvotient og rest ved at sende beskeden divMod til sig selv | ![]() |
Image no. 15. Modelobjeket sender beskeden setChanged til sig selv | ![]() |
Image no. 16. Modelobjeket sender beskeden notifyObservers til sig selv | ![]() |
Image no. 17. notifyObservers sender update beskeden til de interesserede observers | ![]() |
Image no. 18. View objektet sender getResult beskeden til modellen | ![]() |
Image no. 19. View objektet sender beskeden setText til quotient for at vise kvotient resultatet | ![]() |
Image no. 20. View objektet sender beskeden setText til rest objektet for at vise rest resultatet | ![]() |
|
|
Ansvaret for håndtering af events Slide Note Contents Index References Speak | Når brugeren interagerer med et program sker det gennem et syn. Herved skal modellen ændres, og der vil i de fleste tilfælde ske en opdatering af brugergrænsefladen. Vi vil nu koncentrere os om ansvarsfordelingen når det gælder fortolkning af brugerinput. |
The concept event: Når brugeren interagerer med programmet frembringes en række events, som påvirker programmet | Events er i bred forstand de hændelser, som en programbruger foranlediger når han eller hun anvender programmet. |
|
|
Inputkontrol objektet er associeret til modelobjektet med henblik på opdatering af modellen. Men som vi så i eksemplet tidligere i denne lektion har inputkontrol objektet også kendskab til view objektet med henblik på udtræk af informationer fra brugergrænsefladen. Endvidere abonnererer inputkontrol objektet på hændelser fra komponenter af view objektet, således at metoder i inputkontrol objektet bliver aktiveret når brugeren arbejder på synet |
Ansvaret for placering af komponenter i et syn Slide Note Contents Index References Speak | Hvis man arbejder med en brugergrænseflade, som består af flere komponenter, skal man tage stilling til, hvordan disse komponenter skal placeres i forhold til hinanden i det todimensionale plan. Vi vil her se, hvordan Java løser dette problem på en elegant måde. Løsningen består i at uddelegere ansvaret for placering af komponenter til en såkaldt layout manager. |
|
|
|
|
Oversigt over layout managers i AWT Slide Note Contents Index References Speak | På denne side karakteriseres de enkelte Layout Manager's i Java |
|
|
Box layout i Swing Slide Note Contents Index References Speak |
|
|
|
|
Eksempler på layouts i Java AWT Slide Note Contents Index References Speak | Vi viser her en række eksempler på layouts. Eksemplerne er dels fra Lewis and Loftus (lærebogen) og dels fra farveblander eksemplet ovenfor |
|
|
Layout eksempler fra farveblander programmet: |
Program: Det overordnede layout er et GridLayout (init i klassen ColorPresenter).
|
|
Program: Layoutet i et 'ColorPanel' er et GridBagLayout.
|
|
|
Chapter 12: Grafiske brugergrænseflader i Java, del 1
Course home Author home About producing this web Previous lecture (top) Next lecture (top) Previous lecture (bund) Next lecture (bund)
Generated: March 31, 2008, 12:09:34