Java-Programmierung mit Netbeans:

Werbung
Java-Programmierung mit Netbeans:
JFrame mit Menü, Info-Dialog, Methoden zum Speichern und Öffnen
Wir schreiben ein Demo-Programm.
1. Start:
New Project / Java Application
Project Name = MenuDemo
Project Location: (Browse) P:\Informatik\Java\Netbeans
Der Haken für Create Main Class bleibt gesetzt! (Finish)
Hauptfenster (JFrame): New File / Swing GUI Forms / JFrame Form,
Class Name = MenuDemoFrame (Finish)
Datei MenuDemo.java bearbeiten: Die bisher noch leere main-Methode muss die main-Methode
von MenuDemoFrame aufrufen, also:
public static void main(String[] args) {
MenuDemoFrame.main(args);
}
MenuDemo.java kann jetzt geschlossen werden. Das Programm muss sich starten lassen und
einen leeres JFrame-Fenster zeigen.
2. Layout-Gestaltung (Design) von MenuDemoFrame:
Die Eigenschaft „title“ wird auf „Menü-Demo“ eingestellt.
Ein JTextArea wird auf dem JFrame platziert (jTextArea1).
Dann wird ein JMenuBar an den oberen Fensterrand gesetzt. Der Menübalken besitzt bereits die
Menüs „File“ und „Edit“. Durch Bearbeiten der Eigenschaften (Properties) werden die Menütexte
auf „Datei“ und „Hilfe“ geändert.
Zuerst erzeugen wir im Menü „Hilfe“ einen Menüpunkt: „Hilfe“ anklicken und mit Kontextmenü
(rechte Maustaste) „Add From Palette / Menu Item“ wählen.
Die Eigenschaften des so erhalten jMenuItem1 werden bearbeitet: Der Text (Registerkarte
„Properties“) soll „Info“ lauten, der Name (Registerkarte „Code“) wird auf jmiInfo geändert.
Auf der Registerkarte „Events“ richten wir eine „actionPerformed“-Methode ein (das geht auch
per Doppelklick auf den im Design dargestellten Menüpunkt). Wir erhalten im Quelltext auf diese
Weise
private void jmiInfoActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
}
3. Info-Dialog:
Für den Info-Dialog erzeugen wir ein neues Fenster, indem
wir erneut New File wählen:
New File / Swing GUI Forms / JDialog Form
Class Name = InfoDialog, Finish
Das Dialogfenster wird ungefähr so gestaltet, wie die
Abbildung zeigt. Eigenschaften vom InfoDialog: „title“ wird
auf „Info“ gesetzt (= Fenstertitel), „resizable“ auf false (d.h.
das Häkchen wird entfernt).
Für den OK-Schalter (jButton1) wird eine actionPerformed-Methode erzeugt. Dann wird der
Quelltext von InfoDialog.java bearbeitet. Zunächst die actionPerformed-Methode:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
dispose(); // schließt das Fenster
}
Die main Methode des Dialogfensters ist überflüssig, sie gibt aber einen Hinweis darauf, wie der
Dialog erzeugt und angezeigt wird. Sie enthält außerdem einen Quelltext für das Beenden der
ganzen Anwendung. Wir löschen diese Methode deshalb erst am Ende von Punkt 4.
Als nächstes wird der Aufruf des Info-Dialogs durch den Menüpunkt des Hauptfensters
implementiert: Die vorbereitete actionPerformed-Methode des Info-Menüpunkts erhält folgendes
Aussehen:
private void jmiInfoActionPerformed(java.awt.event.ActionEvent evt) {
InfoDialog myInfo = new InfoDialog (this, true);
myInfo.setVisible(true);
}
Nun wird der Aufruf des Info-Dialogs durch den entsprechenden Menüpunkt getestet. Wenn es
funktioniert, geht es weiter.
4. Erweiterung des Menüs Datei: Beenden des Programms
Wie im Punkt 2 (Layout) beschrieben wird auch im Menü Datei ein Menüpunkt ergänzt. Erneut
erhalten wir jMenuItem1 und bearbeiten dieses Objekt wie folgt: Der Name wird auf jmiEnde
geändert, der angezeigte Text wird „Beenden“, eine actionPerformed-Methode wird erzeugt:
private void jmiEndeActionPerformed(java.awt.event.ActionEvent evt) {
System.exit(0);
}
Die Methode main im InfoDialog (nicht in MenuDemoFrame!!) jetzt löschen, Programm testen!
5. Erweiterung des Menüs Datei: Speichern des Textes von jTextArea1
Im Menü Datei wird ein weiterer Menüpunkt ergänzt. Der
Name dieser Komponente wird in jmiSpeichUnter umbenannt, der Text wird in „Speichern unter...“ geändert.
Die Abbildung zeigt den Navigator, der bei der DesignAnsicht angezeigt wird (falls nicht: im Netbeans-Fenster
das Menü „Windows“ wählen und dort suchen). Im
Navigator lassen sich manchmal Komponenten gezielter
auswählen, auch hier kann der Menüpunkte
jmiSpeichUnter verschoben werden, falls der neue
Menüpunkt unter jmiEnde geraten ist. Außerdem zeigt
diese Übersicht, dass es wohl sinnvoll ist, jMenu1 und
jMenu2 zu aussagekräftigeren Namen umzubenennen:
jmDatei und jmHilfe wird vorgeschlagen. Dazu wird das
jeweilige Properties-Fenster für diese Komponenten herangezogen, dann sollte es gelingen.
Eine bequemer Weg zur actionPerformed-Methode von jmiSpeichUnter ist der Doppelklick auf
den Eintrag im Navigator, und wir erhalten
private void jmiSpeichUnterActionPerformed(java.awt.event.ActionEvent evt){
// TODO add your handling code here:
}
6. Methode, die einen String speichert
Dieser Methode werden zwei Parameter übergeben: die ausgewählte Datei, in die Daten
gespeichert werden sollen, und der zu speichernde String.
Schreiben Sie zuerst den Rumpf der Methode:
private void speichern(java.io.File datei, String daten) {
}
Der Quelltext muss immer noch fehlerfrei zu compilieren sein! Jetzt fügen Sie zwischen die
geschweiften Klammern die folgende Zeilen ein:
PrintWriter pw;
pw = new PrintWriter(datei);
pw.write(daten);
pw.close();
// AusgabeStream erzeugen
// Daten schreiben
// Schreiben abschließen
Es erscheinen Fehlerhinweise (Glühlampe mit Ausrufezeichen) am linken Editor-Rand: Zunächst
können Sie durch den Klick auf das Lämpchen den Import für die Klasse PrintWriter einrichten.
Das weitere Lämpchen steht für die Meldung unreported exception FileNotFoundException; must be
caught or declared to be thrown.
Grund: Das Programm kann zu einem Fehler führen, wenn die Datei nicht angelegt werden kann.
Netbeans fordert, dass Exceptions (=Ausnahmen, Fehler) vom Programmierer behandelt werden
müssen, damit nicht später der Anwender ratlos vor einem abgestürzten Programm sitzt. Ein Klick
auf die Glühlampe bietet an, eine throws-Anweisung zu ergänzen, diese würde aber nur das
Problem in die Methode verlagern, von der aus wir das Speichern aufrufen wollen. Wir wählen die
Abhilfe Surround Block with try-catch, damit wird der Fehler abgefangen, der Quelltext lautet nun:
private void speichern(java.io.File datei, String daten) {
try {
PrintWriter pw;
pw = new PrintWriter(dateiName);
pw.write(daten);
pw.close();
} catch (FileNotFoundException ex) { // FileNotFoundExceptions abfangen
Logger.getLogger(MenuDemoFrame.class.getName()).log(Level.SEVERE,null, ex);
}
}
Die hier beschriebene Methode kann nur Strings speichern. Für das Speichern anderer Daten
(int, byte, double) informieren Sie sich im Internet oder bei Ihrer Informatik-Lehrkraft.
7. jmiSpeichUnterActionPerformed vervollständigen
Wir benötigen ein Dialogfenster, das uns die Auswahl des Speicherziels und des Dateinamens
ermöglicht. Dieses stellt uns JAVA mit der Klasse JFileChooser zur Verfügung. Instanzen dieser
Klasse besitzen die Methoden showOpenDialog und showSaveDialog, die sich fast nur im
vordefinierten Fenstertitel unterscheiden. Mit dem Schließen des Dialogfensters hat der Anwender
nicht unbedingt eine Datei ausgewählt, er könnte auch die Auswahl abgebrochen haben. Deshalb
geben die show-Methoden einen int-Wert zurück, aus dem hervorgeht, ob der Dialog mit OK
beendet wurde. Der entsprechende int-Wert ist statisch in der Klasse JFileChooser als Konstante
festgelegt, so dass wir den Zahlenwert nicht wissen müssen. Nur bei OK führen wir das Speichern
durch:
private void jmiSpeichUnterActionPerformed(java.awt.event.ActionEvent evt) {
JFileChooser jfc = new JfileChooser();
if (jfc.showSaveDialog(this)==JFileChooser.APPROVE_OPTION) {
speichern(jfc.getSelectedFile(),jTextArea1.getText());
}
}
Jetzt kann ein Text in JTextArea1 geschrieben und dann gespeichert werden (bitte testen!). Beim
Speichern wird nicht gewarnt, wenn eine Datei dieses Namens bereits besteht und daher
überschrieben wird. Wenn Sie diese Warnung wünschen, müssen Sie dafür sorgen, dass nur dann
gespeichert wird, wenn die Datei nicht existiert ODER wenn im Falle der Existenz die Rückfrage
bestätigt wird (hier können Sie sich den Unterschied zwischen | und || deutlich machen!).
Die eine Zeile zum Speichern aus dem letztgenannten Quelltextabschnitt wird durch die folgenden
Zeilen ersetzt:
if (!jfc.getSelectedFile().exists()
|| JOptionPane.showConfirmDialog(this,
"Möchten Sie die vorhandene Datei überschreiben?",
"Datei existiert bereits",
JOptionPane.YES_NO_OPTION)
==JOptionPane.YES_OPTION) {
speichern(jfc.getSelectedFile(), jTextArea1.getText());
}
Ergänzende Information:
JAVA speichert als Standard im UTF-8-Format. Word2003 erkennt die Umlaut-Codierung und bietet das
Öffnen als UTF-8-Text an. Libre-Office4 liest die Umlaute des gespeicherten Textes unter Windows
standardmäßig falsch ein, jedoch kann man beim Öffnen als Dateityp „Text kodiert (*.txt)“ wählen und so
auch UTF-8-kodierten Text fehlerfrei öffnen. Es gibt noch ein weiteres Kompatibilitätsproblem: JAVA
speichert die Zeilenumbrüche durch den Code 10=0x0a (new line "\n") , während Windows üblicherweise
die zwei Codes 13=0x0d und 10=0x0a (return + new line "\r\n") verwendet. Die genannten Word- und
Libre-Office-Versionen stellen die Zeilenumbrüche korrekt dar. Wordpad und der Windows-Editor verhalten
sich unterschiedlich: Wordpad stellt die Umbrüche korrekt dar, aber nicht die Umlaute (dazu fehlen 3 UTF8-Kennbytes am Dateianfang). Der Editor von Windows7 macht es genau umgekehrt, er ignoriert
Zeilenumbrüche, die nicht als 0x0d0a codiert sind, aber er stellt die UTF-8-Umlaute korrekt dar.
Die Verwendung von UTF-8 hat Vorteile: In diesem Format können Sie Texte mit allen Zeichensätzen
speichern, die Ihr System verwalten kann, also auch z.B. chinesische Zeichen, während im WindowsFormat (genauer: windows-1252) nur weniger als 256 verschiedene Zeichen möglich sind.
Der Konstruktor des PrintStreams kann mit Angabe eines Charset (Zeichensatz) verwendet werden, wenn
Windows-Kompatibilität gewünscht wird:
pw = new PrintWriter(datei, "windows-1252")
Windows-Zeilenumbrüche geben Sie dem String durch folgende Formulierung:
jTextArea1.getText().replaceAll("\n","\r\n")
8. Öffnen einer Textdatei
Ergänzen Sie einen Menüpunkt im Menü Datei. Wenn er nicht an oberster Stelle im Menü
erscheint, verschieben Sie ihn dorthin. Nennen Sie die Komponente jmiOeffnen, geben Sie ihr
den Anzeigetext „Öffnen...“. Richten Sie die zugehörige actionPerformed-Methode ein:
private void jmiOeffnenActionPerformed(java.awt.event.ActionEvent evt) {
JFileChooser jfc = new JFileChooser();
if (jfc.showOpenDialog(this)==JFileChooser.APPROVE_OPTION) {
jTextArea1.setText(oeffnen(jfc.getSelectedFile()));
}
}
Natürlich wird für die Methode oeffnen noch ein Fehler angezeigt, diese schreiben wir als
nächstes:
private String oeffnen(java.io.File datei) {
String s = "";
try {
byte[] lesePuffer = new byte[200];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
FileInputStream fis;
fis = new FileInputStream(datei);
int z = fis.read(lesePuffer);
while (z!=-1) {
baos.write(lesePuffer, 0, z);
z = fis.read(lesePuffer);
}
fis.close();
s = baos.toString();
} catch (IOException ex) {
Logger.getLogger(MenuDemoFrame.class.getName()).log(Level.SEVERE,null,ex);
}
return s;
}
Die Methode ist komplizierter als die Speicher-Methode, weil beim Öffnen noch nicht feststeht,
wie viele Zeichen eingelesen werden müssen. Die Daten werden in eine Lesepuffer eingelesen
(Sie können ihn gern auch mehrere Kilobyte groß machen) und von dort in einen
ByteArrayOutputStream geschrieben. z erhält jeweils die Anzahl der eingelesenen Bytes bzw. -1,
wenn das Ende erreicht wurde. Der ByteArrayOutputStream gestattet die einfache Umwandlung
der hinein geschriebenen Daten in einen String.
Da JAVA vom UTF-8-Format ausgeht, werden Umlaute aus einem Text mit Windows-Codierung nicht
korrekt eingelesen. Sie können aber mit baos.toString("windows-1252") einen CharSet-Namen
angeben, um dieses Verhalten zu ändern. Beim eingelesenen String können Sie "\r\n" durch "\n"
ersetzen – testen Sie mal, ob das nötig ist.
9. Verbessern der Fehlerbehandlung
Beim Öffnen einer Datei lässt sich leicht eine FileNotFoundException erzeugen, indem Sie
einen Dateinamen eingeben, der nicht existiert. Netbeans gibt dann die Fehlermeldung im
Ausgabefenster aus – das nützt aber nichts, wenn Sie das Programm ohne Netbeans starten.
Schöner ist also ein Meldungsfenster, ähnlich wie oben bei dem Warnhinweis vor dem
Überschreiben einer bestehenden Datei. Schreiben Sie deshalb folgende Methode:
private void fehlerMelden(Exception e) {
JOptionPane.showMessageDialog(this,
e.getMessage(), "Fehler:",
JOptionPane.ERROR_MESSAGE);
}
Nun können Sie alle Zeilen
Logger.getLogger(MenuDemoFrame.class.getName()).log(Level.SEVERE,null,ex)
ersetzen durch
fehlerMelden(ex);
Wenn alle Logger-Anweisungen ersetzt sind, können Sie ganz oben im Quelltext bei den Importen
aufräumen und unbenutzte Importe über Klick auf ein Warn-Glühbirnchen entfernen.
10. Look & Feel
Dieses Thema ist eigentlich zu umfangreich, um in ein Menü-Demo-Programm aufgenommen zu
werden. Da dieses Programm jedoch viele Features besitzt, die Sie von Windows-Programmen
kennen, wünschen Sie vielleicht das Aussehen des Programms und seiner Dialogfenster im
gewohnten Design (sofern Sie nicht begeisterter Nutzer eines anderen Betriebssystems wie z.B.
Linux sind). Das erreichen Sie ganz einfach, indem Sie in der main-Methode von
JMenuDemoFrame.java das Design von "Nimbus" auf "Windows" setzen (öffnen Sie den
ausgeblendeten Text durch Klick auf das Plus-Zeichen am Rand bei „Look and feel setting
code (optional)“). Für die Weitergabe eines fertigen Programms ist es aber sinnvoller, sich
über die Einrichtung eines zum jeweiligen Betriebssystem passenden Designs zu informieren.
11. Fensterposition
Das Programmfenster erscheint (wie auch der Info-Dialog) bisher stets in der oberen linken
Bildschirmecke, also an der Position (0|0). Dieses Verhalten können Sie durch die Angabe einer
Position ändern, fügen Sie z.B. unmittelbar nach der initComponents(); -Zeile im Konstruktor
die folgende Zeile ein:
setLocation(200,50);
Sie können auch die Bildschirmgröße auslesen, um das Fenster zentral zu positionieren. Das
können Sie z.B. beim Info-Dialog einrichten (aber auch beim Hauptfenster), und zwar wieder
unmittelbar nach dem Aufruf von initComponents();:
Toolkit tk = getToolkit();
setLocation((tk.getScreenSize().width-this.getWidth())/2,
(tk.getScreenSize().height-this.getHeight())/2);
(Für die Klasse Toolkit müssen Sie java.awt.Toolkit importieren).
Sp/2014
Herunterladen