![]() |
Start på kapittel om grafiske brukergrensesnitt |
Av tekstkomponenter har vi blant annet tekstfelter og tekstområder. Men
det finnes også andre tekstkomponenter med mer spesialiserte egenskaper.
All felles funksjonalitet for tekstkomponenter finnes i den abstrakte klassen
JTextComponent
som er direkte subklasse til
JComponent
. I denne finner vi blant annet metodene
getText
og getSelectedText
, som altså kan brukes
på alle tekstkomponenter. Den første returnerer all tekst som er lagt inn i
tekstkomponenten, mens den andre returnerer den teksten som er merket.
Klassene JTextField
og
JTextArea
er direkte subklasser til
JTextComponent
. En tredje subklasse er
JEditorPane
som kan brukes til å vise html-filer. En liten
orientering om bruken av denne finner du i notatet
Bruk av JEditorPane
.
Som spesialtype til JTextField
finner vi subklassen
JPasswordField
som er beregnet for sikker innlesing av passord.
Vi finner også subklassen JFormattedTextField
. En orientering
om bruken av denne finner du i notatet
Bruk av formatterte tekstfelter.
Vi vet at en
JTextArea
til forskjell fra
JTextField
kan inneholde flere linjer tekst. Den vanligste bruken
av JTextArea
er for utskrift av tekst, men det kan også brukes
til innlesing av tekst som går over flere linjer. Til forskjell fra
JTextField
blir det imidlertid ikke generert noen
ActionEvent
når vi trykker retur-tasten mens markøren står i en
JTextArea
. Innlesing må derfor foretas på en mer indirekte måte,
for eksempel ved å klikke på en knapp utenfor tekstområdet. På denne måten
blir det gjort i eksemplet nedenfor. Vanligvis pleier vi å utstyre tekstområder
med skrollefelter ved at vi plasserer dem i en
JScrollPane
.
Dersom vi på et tekstområde bruker metoden
public void setLineWrap( boolean linjeskift )
med parameter lik true
, så vil det bli automatisk linjeskifte
hver gang en linje er for lang til å få plass innenfor tekstområdets bredde.
Et eventuelt horisontalt skrollefelt vil da bli fjernet. Men for å unngå at
ord blir delt ved linjeskiftene, bør vi da også for tekstområdet gjøre et kall
på metoden
public void setWrapStyleWord( boolean heleOrd )
med parameter lik true
.
Programmet
TextAreaFrame.java
som
er gjengitt nedenfor plasserer to tekstområder i et vindu som vist på
følgende bilde.
Programmet er som det du kan finne i Fig. 14.47 i 9. utgave av læreboka
til Deitel & Deitel. De tre skjermkomponentene blir plassert i en
container av type Box
. Den har layout av type
BoxLayout
. Det innebærer at komponentene plasseres i én
rad, enten horisontalt eller vertikalt. I eksemplet er det horisontal
plassering. Du kan finne nærmere beskrivelse av Box
-containere
og BoxLayout
i notatet
BoxLayout
.
Programmet virker på den måten at når det blir klikket på knappen mellom
de to tekstområdene, så blir eventuell merket tekst i det første
tekstområdet lest inn og satt som tekst i det andre tekstområdet.
Driverklasse for programmet finnes i fila
TextAreaDemo.java
.
1 import java.awt.event.ActionListener; 2 import java.awt.event.ActionEvent; 3 import javax.swing.Box; 4 import javax.swing.JFrame; 5 import javax.swing.JTextArea; 6 import javax.swing.JButton; 7 import javax.swing.JScrollPane; 8 import java.awt.BorderLayout; 9 10 //Copying selected text from one textarea to another. 11 public class TextAreaFrame extends JFrame 12 { 13 private JTextArea textArea1; // displays demo string 14 private JTextArea textArea2; // highlighted text is copied here 15 private JButton copyJButton; // initiates copying of text 16 17 public TextAreaFrame() 18 { 19 super( "TextArea Demo" ); 20 Box box = Box.createHorizontalBox(); // create box 21 String demo = "This is a demo string to\n" + 22 "illustrate copying text\nfrom one textarea to \n" + 23 "another textarea using an\nexternal event\n"; 24 25 textArea1 = new JTextArea( demo, 10, 15 ); 26 box.add( new JScrollPane( textArea1 ) ); 27 28 copyJButton = new JButton( "Copy >>>" ); 29 box.add( copyJButton ); 30 copyJButton.addActionListener( 31 32 new ActionListener() // anonymous inner class 33 { 34 // set text in textArea2 to selected text from textArea1 35 public void actionPerformed( ActionEvent event ) 36 { 37 textArea2.setText( textArea1.getSelectedText() ); 38 } 39 } // end anonymous inner class 40 ); // end call to addActionListener 41 42 textArea2 = new JTextArea( 10, 15 ); // create second textarea 43 textArea2.setEditable( false ); // disable editing 44 box.add( new JScrollPane( textArea2 ) ); 45 46 getContentPane().add(box, BorderLayout.CENTER); //add box to frame 47 } // end TextAreaFrame constructor 48 } // end class TextAreaFrame
Klassen
JPasswordField
er subklasse til JTextField
og er spesielt laget for sikker innlesing av passord.
Av sikkerhetsgrunner viser den ikke hvilke tegn brukeren skriver i skrivefeltet, men viser isteden
et ekkotegn, slik som en stjerne '*'
. (Hvilket tegn det skal være kan vi selv bestemme
ved bruk av metoden
setEchoChar(char c)
Programeksemplet nedenfor viser det tegnet
som er forhåndssatt.) Som et annet sikkerhetstiltak lagrer
et passordfelt sin input i en
char
-array istedenfor i en String
.
Metoden getText
er for et passordfelt markert som foreldet. Isteden skal metoden
getPassword
brukes for innlesing. Den returnerer
char
-arrayen med tegnene
som brukeren har skrevet i passordfeltet (men som altså bare vises med et ekkotegn på skjermen).
Som et ytterligere sikkerhetstiltak anbefales det at så snart som innlesing av passord og testing
på gyldigheten av dette er unnagjort, så fylles den array som er brukt ved innlesingen med nulltegn.
Programeksemplet nedenfor viser hvordan dette kan gjøres.
Eksemplet er hentet fra The Java Tutorials. Hele programmet ligger i fila
PasswordDemo.java
.
Når det blir kjørt, får vi fram følgende programvindu:
I vinduet er det skrevet inn et passord. Vinduet viser hva som er forhåndssatt som ekkotegn. For å få lest inn og testet passordet for gyldighet, kan man enten trykke Enter-tast eller klikke på OK-knappen. Er det galt passord, vises følgende meldingsboks:
Ved riktig passord vises isteden denne meldingsboksen:
For dette eksemplets vedkommende kan man få opplysninger om riktig passord ved å klikke på Help-knappen. Da blir følgende meldingsboks vist:
Riktig passord kan man for øvrig finne ved å lese koden nedenfor.
Vi skal se litt nærmere på noe av koden for programmet. Aller først ser vi på hvordan
innlesing og testing på gyldighet av passord er utført. Selve innlesingen skjer i
actionPerformed
-metoden:
65 char[] input = passwordField.getPassword();
Innlest array blir sendt til metoden isPasswordCorrect
. Denne inneholder
det korrekte passordet og sjekker det mot det den får tilsendt. Til dette brukes
klassemetoden equals
fra Arrays
-klassen. Merk at dette er ikke
det samme som equals
-metoden til String
-klassen! Det som gjøres, er å
sjekke om to arrayer har samme innhold. Klassen Arrays
i pakken
java.util
inneholder et stort antall
klassemetoder for å utføre standardoperasjoner på arrayer. I dette programmet brukes også dens
fill
-metode for å fylle med 0
-tegn de arrayene som ble brukt ved
innlesingen. Det skjer uavhengig av om riktig eller galt passord er lest inn.
Programmet inneholder enkelte andre detaljer som du kanskje ikke er kjent med fra tidligere.
Vi skal se på noen av dem. Først ser vi på hvordan både passordfeltet og OK-knappen er tilordnet
samme reaksjonsmåte for det lytteobjektet som de to komponentene har felles med Help-knappen
(og som for øvrig er det panelet som alt sammen ligger i, og
som er tilordnet som contentPane for vinduet). Dette er gjort ved at både passordfeltet og OK-knappen
er tilordnet samme identifiserende String
-konstant OK
:
13 private static String OK = "ok"; ... ... 25 passwordField.setActionCommand(OK); ... 48 okButton.setActionCommand(OK);
Det ActionEvent
-objekt som er parameter til actionPerformed
-metoden
vil inneholde den identifiserende streng som er tilordnet komponenten der hendelsen ble
generert. I actionPerformed
-metoden blir identifiserende streng hentet ut
og sammenliknet med den som er tilordnet passordfelt og OK-knapp:
61 String cmd = e.getActionCommand(); 62 63 if (OK.equals(cmd)) //Kilde til hendelsen er passordfeltet eller OK-knappen
Etter at passord er lest inn og sjekket for gyldighet, gjøres det kall på passordfeltets
metode selectAll
, samt på programmets metode resetFocus
:
82 passwordField.selectAll(); 83 resetFocus();
selectAll
er en fellesmetode for alle tekstkomponenter. Den har som
virkning at hele teksten som komponenten inneholder blir valgt og dermed markert, slik vi
i dette tilfelle ser på følgende bilde:
Programmets metode resetFocus
, som også blir kalt opp når programmet starter opp,
gjør kall på passordfeltets metode requestFocusInWindow
. Den sørger for at passordfeltet
får fokus på den måte at markøren plasserer seg i passordfeltet, slik at det er klart til å skrive
noe i det.
1 /* 2 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc. All rights reserved. 3 */ 4 5 import javax.swing.*; 6 import java.awt.*; 7 import java.awt.event.*; 8 import java.util.Arrays; 9 10 /* PasswordDemo.java requires no other files. */ 11 public class PasswordDemo extends JPanel implements ActionListener 12 { 13 private static String OK = "ok"; 14 private static String HELP = "help"; 15 private JFrame controllingFrame; //needed for dialogs 16 private JPasswordField passwordField; 17 18 public PasswordDemo(JFrame f) 19 { 20 //Use the default FlowLayout. 21 controllingFrame = f; 22 23 //Create everything. 24 passwordField = new JPasswordField(10); 25 passwordField.setActionCommand(OK); 26 passwordField.addActionListener(this); 27 28 JLabel label = new JLabel("Enter the password: "); 29 label.setLabelFor(passwordField); 30 31 JComponent buttonPane = createButtonPanel(); 32 33 //Lay out everything. 34 JPanel textPane = new JPanel(new FlowLayout(FlowLayout.TRAILING)); 35 textPane.add(label); 36 textPane.add(passwordField); 37 38 add(textPane); 39 add(buttonPane); 40 } 41 42 protected JComponent createButtonPanel() 43 { 44 JPanel p = new JPanel(new GridLayout(0, 1)); 45 JButton okButton = new JButton("OK"); 46 JButton helpButton = new JButton("Help"); 47 48 okButton.setActionCommand(OK); 49 helpButton.setActionCommand(HELP); 50 okButton.addActionListener(this); 51 helpButton.addActionListener(this); 52 53 p.add(okButton); 54 p.add(helpButton); 55 56 return p; 57 } 58 59 public void actionPerformed(ActionEvent e) 60 { 61 String cmd = e.getActionCommand(); 62 63 if (OK.equals(cmd)) 64 { //Process the password. 65 char[] input = passwordField.getPassword(); 66 if (isPasswordCorrect(input)) 67 { 68 JOptionPane.showMessageDialog(controllingFrame, 69 "Success! You typed the right password."); 70 } 71 else 72 { 73 JOptionPane.showMessageDialog(controllingFrame, 74 "Invalid password. Try again.", 75 "Error Message", 76 JOptionPane.ERROR_MESSAGE); 77 } 78 79 //Zero out the possible password, for security. 80 Arrays.fill(input, '0'); 81 82 passwordField.selectAll(); 83 resetFocus(); 84 } 85 else 86 { //The user has asked for help. 87 JOptionPane.showMessageDialog(controllingFrame, 88 "You can get the password by searching this example's\n" 89 + "source code for the string \"correctPassword\".\n" 90 + "Or look at the section How to Use Password Fields in\n" 91 + "the components section of The Java Tutorial."); 92 } 93 } 94 95 /** 96 * Checks the passed-in array against the correct password. 97 * After this method returns, you should invoke eraseArray 98 * on the passed-in array. 99 */ 100 private static boolean isPasswordCorrect(char[] input) 101 { 102 boolean isCorrect = true; 103 char[] correctPassword = {'b', 'u', 'g', 'a', 'b', 'o', 'o'}; 104 105 if (input.length != correctPassword.length) 106 { 107 isCorrect = false; 108 } 109 else 110 { 111 isCorrect = Arrays.equals(input, correctPassword); 112 } 113 114 //Zero out the password. 115 Arrays.fill(correctPassword, '0'); 116 117 return isCorrect; 118 } 119 120 //Must be called from the event dispatch thread. 121 protected void resetFocus() 122 { 123 passwordField.requestFocusInWindow(); 124 } 125 126 /** 127 * Create the GUI and show it. For thread safety, 128 * this method should be invoked from the 129 * event dispatch thread. 130 */ 131 private static void createAndShowGUI() 132 { 133 //Create and set up the window. 134 JFrame frame = new JFrame("PasswordDemo"); 135 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 136 137 //Create and set up the content pane. 138 final PasswordDemo newContentPane = new PasswordDemo(frame); 139 newContentPane.setOpaque(true); //content panes must be opaque 140 frame.setContentPane(newContentPane); 141 142 //Make sure the focus goes to the right component 143 //whenever the frame is initially given the focus. 144 frame.addWindowListener(new WindowAdapter() 145 { 146 147 public void windowActivated(WindowEvent e) 148 { 149 newContentPane.resetFocus(); 150 } 151 }); 152 153 //Display the window. 154 frame.pack(); 155 frame.setVisible(true); 156 } 157 158 public static void main(String[] args) 159 { 160 //Schedule a job for the event dispatch thread: 161 //creating and showing this application's GUI. 162 SwingUtilities.invokeLater(new Runnable() { 163 164 public void run() { 165 //Turn off metal's use of bold fonts 166 UIManager.put("swing.boldMetal", Boolean.FALSE); 167 createAndShowGUI(); 168 } 169 }); 170 } 171 }
Copyright © Kjetil Grønning, revidert av Eva Hadler Vihovde 2014
![]() |
Start på kapittel om grafiske brukergrensesnitt |