Programmering

Opprett brukergrensesnitt på klientsiden i HTML, del 1

Denne måneden skal jeg tilbake til programmering en stund. Jeg trenger hvile fra rare på Talkback-diskusjonen i forrige måneds spalte. Jeg har tenkt å skrive mer om teorispørsmål i fremtiden, men ikke de neste par månedene.

Jeg trenger å gjøre en avklaring fra forrige måneds kolonne. Mange tolket kommentarene mine om brukergrensesnitt som fortaler for tunge gjenstander med milliarder gjengivelsesmetoder i dem. Det var ikke det jeg hadde i tankene. Det er mange levedyktige måter å lage brukergrensesnitt (UI) uten å avsløre implementeringsdetaljer. Gang of Four Builder og Visitor mønstre kommer umiddelbart til å tenke på. En enkel tegn deg selv() metoden kan åpenbart ikke fungere på annet enn de mest enkle objektene, og å ha 50 drawYourselfInThisFormat () og drawYourselfInThatFormat () metoder er en meningsløs oppskrift på uhåndterlig kode. Mange tror imidlertid at jeg går inn for den tilnærmingen, så jeg beklager hvis jeg ga det inntrykket.

Siden jeg har sett mye misforståelse angående UI-problemet, vil jeg planlegge å vise deg noen få implementeringer av objektorienterte (OO) UI-bygningsmetoder i fremtidige kolonner. Jeg presenterte en slik løsning i JavaWorld for noen år siden (se Ressurser), men jeg har bygget bedre systemer i de mellomliggende årene. Denne nåværende kolonnen presenterer et stykke av et av disse brukergrensesnittene: en infrastrukturklasse jeg har brukt til å bygge brukergrensesnitt på klientsiden på en OO-måte. Det er ikke i og for seg en løsning på UI-problemet, men det er en nyttig byggestein.

Siden kodeprøvene er ganske store, deler jeg presentasjonen i to biter. Denne måneden er dokumentasjon og søknadskode; neste måned er kildekoden.

Les hele "Create Client-Side User Interfaces in HTML" -serien:

  • Del 1: Gjør JEditorPane nyttig (oktober 2003)
  • Del 2: HTMLPane-kildene (november 2003)

Bruke HTML på klientsiden

HTML er en fantastisk ting. Den lar deg legge ut kompliserte brukergrensesnitt med et minimum av oppstyr; det gjør en god jobb med å skille UI-struktur og layout fra forretningslogikk; det er lett å skrive; og det er enkelt å vedlikeholde. Abstract Window Toolkit (AWT) / Swing layout er derimot irriterende vanskelig å bruke. Du må endre (og kompilere) koden for å endre utseendet på skjermene dine, og koden for et trivielt oppsett er i seg selv ikke viktig, og strekker seg til mange sider. Ville det ikke vært fint om du kunne spesifisere hele brukergrensesnittet på klientsiden i HTML?

(Jeg vet at noen av dere vil svare på det foregående spørsmålet med et oppsiktsvekkende "Nei, det ville ikke være fint!" dialogboksen "-modus. På den annen side kan mange applikasjoner utnytte HTML effektivt i minst en del av brukergrensesnittet - for rapportrapporter om ikke annet. Du kan ikke kaste babyen ut med badevannet.)

Swing's JEditorPane klasse ser ut til å være et svar på HTML-layoutproblemet. Det forstår HTML-input etter en mote. For eksempel viser følgende kode en ramme som viser litt enkel HTML-tekst:

JFrame hovedramme = ny JFrame (); JEditorPane-rute = ny JEditorPane (); pane.setContentType ("text / html"); pane.setEditable (false); pane.setText ("" + "" + "" + "" + "HalloVerden"+" "+" "); main_frame.setContentPane (rute); main_frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); main_frame.pack (); main_frame.show (); 

Jeg sier "etter en mote" fordi JEditorPane er ikke spesielt god til å håndtere kompleks HTML. Det gjør ikke en god jobb med nestede tabeller, og det gjør ikke Cascading Style Sheets (CSS) veldig bra. (Jeg har blitt fortalt at mange av disse problemene vil bli løst i Java 1.5-utgivelsen neste år, men foreløpig må vi alle tåle dem.) Til slutt, JEditorPane gjør ikke en spesielt god jobb med å legge ut ting som radioknapper. De er ikke riktig justert med tekstbaselinjen, og de viser alltid en grå bakgrunn, slik at de ikke fungerer bra hvis du endrer sidens bakgrunnsfarge (med en stil på tag, for eksempel).

Alle disse feilene er irriterende, men show-stopper-problemet med JEditorPane er at den fungerer som en tekstkontroll, ikke som et layoutanlegg. Du kan spesifisere en HTML i inngangen, for eksempel, men skjemaet sendes til en webserver når du trykker på Send-knappen. For å være nyttig for å spesifisere et brukergrensesnitt på klientsiden, vil du at skjemadataene skal gå tilbake til programmet som viste skjemaet, ikke til en ekstern server. Du trenger også en beleilig måte å legge til egendefinerte koder for ikke-standard input eller visningsformål eller å gi plassholdere for standard sving JKomponenter du vil bruke på skjemaet. (JEditorPane lar deg gjøre dette, men mekanismen er langt fra praktisk.) Til slutt må du håndtere ting som en Avbryt-knapp, som ikke finnes i HTML.

Heldigvis kan de mest alvorlige av de ovennevnte problemene løses ved hjelp av tilpasningsfasiliteter innebygd JEditorPane seg selv. Å fikse disse problemene innebærer imidlertid en viss kompromiss. For eksempel kan du håndtere problemet med Avbryt-knappen ved å implementere en JavaScript-tolk og støtte ved trykk attributt, men det er veldig mye arbeid. På samme måte er det veldig vanskelig å gjøre med den eksisterende parseren å gi ekte tilpasset tag-støtte (hvor du kan behandle alt som kommer mellom en start- og slutt-tag). Du kan erstatte JEditorPaneer parser med en bedre, men det er også mye arbeid. Jeg valgte enklere løsninger som gjorde jobben. Jeg la nok funksjonalitet i klassen min til at jeg kunne bruke den til å bygge et brukergrensesnitt for programmet jeg skrev, men ga ikke en "perfekt" løsning. Problemet jeg løste var: gi en måte å spesifisere et brukergrensesnitt i HTML. Jeg løste ikke problemet: gi en måte å vise all mulig HTML i en applikasjon på klientsiden. De HTMLPane klasse jeg presenterer i denne artikkelen, løser spesifiser-a-UI-i-HTML-problemet pent.

Bruke HTMLPane

Min HTML-inngangsklasse bare på klientsiden, HTMLPane, er en JEditorPane derivat som løser problemene som ble diskutert tidligere. Oppføring 1 viser hvordan du bruker en HTMLPane. Jeg opprettet en enkel JDialog derivat kalt HtmlDialog der du kan spesifisere dialogboksoppsett som HTML. De HtmlDialog er et trivielt eksempel på fasademønsteret. Det gjør bare det rote arbeidet som er nødvendig for å sette en HTMLPane inn i en dialogboks og vise den.

De HtmlDialog.Test klasse (oppføring 1, linje 134) gir et enkelt eksempel på hvordan du bruker HtmlDialog. Det skaper en stort sett tom hovedramme (Eieren). Ved å bruke kode som kodebiten gjengitt nedenfor, hoved() skaper en HtmlDialog objekt hvis innhold er spesifisert i den CLASSPATH-relative filen com / holub / ui / HTML / test / okay.html (Oppføring 2). Strengen "Test HtmlDialog" vises i tittellinjen. Endelig, hoved() dukker opp dialogen ved å ringe d.popup (), som ikke kommer tilbake før brukeren lukker dialogen:

// Vis okay.html-filen i en dialogboks som har// tittelen "Test HtmlDialog".// HtmlDialog dialog = ny HtmlDialog (owning_frame, "com / holub / ui / HTML / test / okay.html", "Test HtmlDialog"); // Åpne dialogboksen og vent til brukeren avviser den.// dialog.popup (); // Skriv ut "skjemadata" som brukeren skrev inn.// System.out.println ("hidden =" + dialog.data (). GetProperty ("hidden") + "user-input" + dialog.data (). GetProperty ("user-input")); 

Skjemadata (teksten brukeren skrev inn i en element eller tilsvarende), er tilgjengelig via HtmlDialogs data() metode, som returnerer a java.util.Eiendommer objekt som inneholder nøkkel- / verdipar som representerer skjemadataene. Ovennevnte kall til dialog.data (). getProperty ("skjult") returnerer strengen "skjulte feltdata". De dialog.data (). getProperty ("brukerinngang") samtale returnerer det brukeren skrev inn i inndatafeltet.

Det meste av arbeidet som er involvert i å sette i gang det innkapslede HTMLPane skjer i HtmlDialog konstruktør (oppføring 1, linje 46). Konstruktøren setter først opp en ActionListener som håndterer Send-knappen på skjemaet. Denne observatøren lukker den nåværende dialogboksen og kopierer skjemadata fra HTMLPane til data forekomstvariabel. Konstruktøren henter deretter inndatafilen fra CLASSPATH, og laster deretter HTML-en i HTMLPane ved hjelp av setText (). (Det er også en setPage (URL) metoden, men du trenger en URL for den absolutte banen til filen hvis du brukte den. Jeg ønsket at HTML-filnavnet skulle være relativt CLASSPATH.)

Avbryt behandling behandles i popup () (linje 121), som antar at det ble trykket på en Avbryt-knapp hvis det finnes en Avbryt-tast i de innsendte skjemadataene. (Mer om hvordan disse dataene kommer inn i Eiendommer objekt i et øyeblikk.)

$config[zx-auto] not found$config[zx-overlay] not found