1 Grafiska komponenter, händelsehantering Utformningen av vår applikation har nu nått följande stadie Det som skiljer sig från målet i grafisk hänseende är 1- Knapparna har inga bilder. Knappikoner är en egenskap i respektive JButton-instans. Skapa lämpliga bilder, standardikonerna finns i vissa grafikbibliotek, ex Visual Studio / Common/Graphics/Bitmaps/... Bilderna ska vara i antingen gif, jpg eller png format. Gif formatet är lämpligt för bilder med få färgvariationer, såsom datorskärmbilder. Jpg formatet är lämpligt för bilder med mycket färgvariation. Png formatet är ett relativt nytt format som är lämpligt för de flesta typer av bilder. Alla ritprogram el. motsv. kan däremot inte hantera png. 2- Det finns ingen rullningslist i applikationen. Markera JFramekomponenten i inspectionytan. Välj Add from Palette / Swing / JScrollPane. Scrollpanekomponenten ligger nu i JFramekomponenten. För att fungera på rätt sätt behöver vi bara dra editorpane-objektet in i jscrollpaneobjektet. Kontrollera att jscrollpaneobjektet har rätt layout, CENTER. 1.1 Händelser Till skillnad från tidigare kommer vi att bara skriva programkod som körs då användaren trycker på en knapp. Programkoden som skapats av miljön i main(.. ) och initcomponents() duger bra för att initiera applikationen. Det som händer efter att main, konstruerare och initcomponents() exekverat är att applikationen lyssnar efter händelser i en särskild process. Vi hanterar inte processen själva, utan den ger vår applikation olika systemmeddelanden som sedan översätts till händelser. I grunden är detta en väldigt sammansatt process, men java och NetBeansmiljön gör det lättarbetat och döljer många komplexa detaljer.
1.1.1 Skapa en händelse för en JButton Gå till det grafiska redigeringsläget för formuläret, välj på något sätt knappen Open (inspector, designfönstret eller projektfliken). I fönstret med properties finner du en knapp Events, på samma sätt som den tidigare visade egenskaper för det aktiva openbuttonobjektet, ser vi nu de händelser som är kopplade/aktiverade för openbuttonobjektet. I ursprungsläget är inte händelser kopplade, beskrivet med <none> i listan. Den första händelsen är actionperformed. En Actionhändelse är då användaren vill aktivera knappen. Notera att det finns händelser som mouseclicked och keytyped och liknande; vi har även kunnat använda dessa men då hade vi bara reagerat på ett sätt att aktivera knappen, en knapp/jbutton kan ju aktiveras genom både mellanslagstangenten om den är aktiv, musklick, snabbtangent, och returntangenten om den är Defaultknapp. Istället för att beskriva alla dessa fyra händleser var för sig finns actionperformed som en gemensam beskrivning. JFileChooser - en JFileChooser är en komponent som representerar en standarddialogruta, antingen en Save File.. dialog eller en Open File... dialog. Den är ytterligt lättanvänd, man behöver bara ange om man ska skapa dialogfönstret i läget Open eller Save. I ett lösryckt programkodsavsnitt ser det ut som: JFileChooser myopenfiledialog = new JFileChooser(); int result = myopenfiledialog.showopendialog(this); if ( result == JFileChooser.APPROVE_OPTION ) File f = myopenfiledialog.getselectedfile(); // Öppna filen f och läs dess data // fyll editorpane med texten ur filen. Detta programkodsavsnitt kommer i exemplet att ligga i den metod som NetBeans skapar då vi anger händelsen actionperformed för Open... knappen. rad1 JFileChooser myopenfiledialog = new JFileChooser(); Instansierar dialogrutan; skapar utan att visa den på skärmen. I vårt exempel kommer miljön ha skapat denna sats som ett attribut. myopenfiledialog är namnet vi valt för dialogrutan. int result = myopenfiledialog.showopendialog(this); Anropar metoden showopendialog, argumentet this, betyder i sammanhanget vårt applikationfönster. jfr då this användes för Point klassen, this betydde där den aktuella punkten. För Point klassen kunde this innebära antingen huvudprogrammets punktett eller punkttvå. Startar vi två Java editor applikationer samtidigt, kommer this att avse antingen applikation ett eller applikation två. showopendialog använder this för att lägga sig ovanpå applikationsfönstret.
Heltalet result anger om användaren tryckte på Ok eller stängde fönstret på annat sätt. Ok beskrivs av klassattributet APPROVED_OPTION i klassen JOptionPane. APPROVED_OPTION kallas för en konstant, en heltalskonstant. Vi är egentligen inte intresserade av det faktiska värdet utan använder bara namnet som ledning till vad som händer. if ( result == JFileChooser.APPROVE_OPTION ) Om användaren tryckte Ok så utförs ifsatsens block. Jämför läsbarheten om det inte funnits en konstant definierad if ( result == 0 ) File f = myopenfiledialog.getselectedfile(); Läser av vilken fil som användaren valde. Klassen File används inte för att läsa och skriva till filen utan innehåller endast information om var filen finns, dess namn och vilken storlek den har. Hur vi läser data från filen återkommer vi till inom kort. Se också http://java.sun.com/docs/books/tutorial/uiswing/components/filechooser.html För att skapa en dialogruta för att spara en fil använder vi oss istället av metoden int result = mysavefiledialog.showsavedialog(this); if ( result == JFileChooser.APPROVE_OPTION ) File f = mysavefiledialog.getselectedfile(); Man kan även ange filter för dialogrutorna. I vårt exempel kan det vara användbart att bara visa textfiler med ändelsen.txt i dialogrutorna. Hur det går till visas bland annat under länken ovan.
2 Att läsa från och skriva till filer 2.1 Inläsning Att läsa data eller text från en fil innefattar tre huvudsakliga steg 1- Öppna filen 2- Läs data från filen 3- Stäng filen 1 Vi öppnar textbaserade filer genom att skapa en FileReader kopplad till filen. För rena datafiler använder man ett annat sätt, men det är inte intressant för oss. Efter filen öppnats bestämmer man sig för hur man vill läsa texten i filen. Ett bekvämt sätt är att läsa rad för rad, för det är en BufferedReader utmärkt. 2 Efter att filen öppnats och en lämplig läsare skapats använder man läsaren för att läsa, antingen hela filen, eller de delar man väljer. 3 Då all text är läst från textfilen stänger man de läsare man skapat. Man måste stänga filen eftersom oprativsystemet bara kan ha ett begränsat antal filer öppna samtidigt. Exempel: Att läsa filen "c:\en_textfil.txt", och rad för rad skriva ut filens innehåll på skärmen. import java.io.*; public class MyFileReader public static void main(string [] args) try File myfile = new File("C:\\en_textfil.txt "); FileReader filereader = new FileReader( myfile ); // FileReader läser tecken från en filström // kastar en IOException BufferedReader linereader = new BufferedReader( filereader ); // BufferedReader läser radvis från en Reader (FileReader) // jfr funktionen hos Scanner String textline; while ( (textline=linereader.readline())!= null) // IOException kastas av readline() System.out.println( textline ); linereader.close(); filereader.close(); catch(ioexception ioe) System.out.println("Fel i inläsning "); // slut på main // slut på klass MyFileReader Vi ser direkt en speciell konstruktion med try / catch
try // satser catch (... ) // felhanterande satser Om någon operation kan ha ett oväntat eller onaturligt beteende rapporteras det som ett undantag (exception). Man säger att en metod kastar ett undantag. Ex. om textfilen inte finns går det inte att läsa från den, det hanteras genom att ett undantag kastas. Alla metoder som kastar undantag måste infogas i ett try / catchblock som try objekt.metodsomkastarundantag(); objekt.annanmetodsomkastarundantag(); // och andra satser catch ( UndantagetSomMetodenKastar o ) // o innehåller information som beskriver "felet" Vi behöver inte fördjupa oss i undantag utan bara anamma skrivsättet för att öppna, läsa från och stänga filen, inuti ett try / catchblock. Förändra inte formen på try/catchblocket om du inte vet vad du gör. File myfile = new File("C:\\en_textfil.txt "); FileReader filereader = new FileReader( myfile ); Skapar ett Fileobjekt för filen "c:\en_textfil.txt". Därefter skapas en läsare för filen. Skapandet av läsaren kastar ett undantag om filen inte finns, eller inte kan läsas från av andra anledningar. Ett alternativt skrivsätt utan File-objekt hade varit FileReader filereader = new FileReader("C:\\en_textfil.txt"); Du kan se dessa båda skrivsätt i javadokumentationen http://java.sun.com/j2se/1.5.0/docs/api/java/io/filereader.html#constructor_summary En FileReader är en primitiv textläsare. Vi använder hellre en radbaserad inläsning istället för att läsa tecken för tecken. Det får vi med en BufferedReader BufferedReader linereader = new BufferedReader( filereader ); På samma sätt som System.in är ett bökigt sätt att läsa från tangenbordet; vi tar hjälp av Scanner klassen för att kunna läsa int double osv. så tar vi hjälp av BufferedReader för att läsa radvis. String textline; while ( (textline=linereader.readline())!= null) Whilesatsen uttrycker: läs rad för rad tills filen tagit slut. Filens slut gör att readline() returnerar null, inget objekt. Om man tittar närmare på whilevillkoret ser man att först görs metodanropet till readline(), därefter görs tilldelningen. Tilldelningen utvärderas till raden som lästs. Sist görs jämförelsen med null, som styr while-satsen. Detta är en ganska komplicerad whilesats, men det är det bekvämaste sättet att uttrycka, läs tills filen tagit slut. Vi tappar i läsbarhet, men behöver bara skriva ett sammansatt villkor, för inläsning och jämförelse. Observera att villkoret både läser textraden och därefter kontrollerar om filen tagit slut.
2.2 Skriva till fil Exempel skriva multiplikationstabellen till en fil import java.io.*; public class MyFileWriter public static void main(string [] args) try File myfile = new File("C:\\tabell.txt "); FileWriter filewriter = new FileWriter( myfile ); // FileWriter skriver till en fil // kastar en IOException PrintWriter lineprinter = new PrintWriter( filewriter ); // en PrintWriter fungerar på samma sätt som System.out // System.out.println... skriver till konsolen // lineprinter.println... skriver till filen // Taget från tabellexemplet moment 8 for( int i = 1; i <= 10;i++) // rad i tabellen for( int j = 1; j <= 10;j++) // kolumn // skriv ett tal i tabellen lineprinter.print(""+i*j+"\t"); lineprinter.println(); /// nästa rad i tabellen lineprinter.close(); filewriter.close(); catch(ioexception ioe) System.out.println("Fel i filen"); // slut på main // slut på klass MyFileWriter Att skriva data eller text till en fil innefattar samma tre huvudsakliga steg som vid inläsning 1- Öppna filen 2- Skriv data till filen 3- Stäng filen Om man skulle glömma att stänga filen kan det mycket väl hända att datat aldrig hamnar i filen. PrintWriter lineprinter = new PrintWriter( filewriter ); På samma sätt som vi vill förenkla inläsning vill vi förenkla utskrift. Med PrintWriter kan vi använda exakt de metoder vi anänvder då vi skriver till System.out; System.out är av typen PrintWriter. try/catch blocket måste utförmas på samma sätt som för inläsning. Se videopresentation för hur filhantering infogas i händelser.