package javacodebook.gui.focustraversal; import java.awt.*; import java.util.*; /** * @author benjamin_rusch * * Diese Klasse kapselt die FocusReihenfolge eines beliebigen Containers. Ein Objekt * dieser Klasse muss über setFocusTraversalPolicy() an dem Container angemeldet * werden. Die Reihenfolge wird über einen Array von Komponenten definiert, der im * Konstruktor, oder über setOrder() gesetzt werden kann. */ public class FocusTraversalDefinition extends ContainerOrderFocusTraversalPolicy { /** * Array der alle focusierbaren Komponenten in der vorgesehenen * Reihenfolge beinhaltet */ private Component[] componentsInOrder = null; /** * Positionsnummer der focussierten Komponenten */ private int position = 0; /** * Konstruktor von FocusTraversalDefinition, Komponenten in der vorgesehenen * Reihenfolge werden übergeben. */ public FocusTraversalDefinition(Component[] componentsInOrder) { this.setOrder(componentsInOrder); } /** * Reihenfolge kann neu gesetzt werden. */ public void setOrder(Component[] componentsInOrder) { this.componentsInOrder = componentsInOrder; } /** * Methode aus FocusTraversalPolicy, wird hier überschrieben, sie * gibt immer die nächste Komponente in der Focusreihenfolge aus. */ public Component getComponentAfter(Container focusCycleRoot, Component aComponent) { if ((position+1)==componentsInOrder.length) { position=0; } else { position++; } return componentsInOrder[position]; } /** * Methode aus FocusTraversalPolicy, wird hier überschrieben, und gibt immer * in der Focusreihenfolge, die vorherige Komponente an. */ public Component getComponentBefore(Container focusCycleRoot, Component aComponent) { if (position==0) { position=(componentsInOrder.length)-1; } else { position--; } return componentsInOrder[position]; } /** * Methode aus FocusTraversalPolicy, wird hier überschrieben, und gibt die erste * Komponente an, die im Focus steht. */ public Component getFirstComponent(Container focusCycleRoot) { return componentsInOrder[0]; } } --- Neue Klasse --- package javacodebook.gui.focustraversal; import javax.swing.*; import java.awt.event.*; import java.awt.*; /** * @author Benjamin Rusch * * In diesem Frame befinden sich drei Textfelder und ein Button. Die Reihenfolge * in der sie den Focus bekommen, wird in einer extra Klasse gehalten. Drückt man * den Button ändert sich die Reihenfolge. */ public class FocusTraversalFrame extends Frame { private TextField field1 = new TextField(15); private TextField field2 = new TextField(15); private TextField field3 = new TextField(15); private Button changeOrder = new Button("Richtung ändern"); // Wird in unserem Beispiel benötigt, um die Focusreihenfolge zu definieren private Component[] order = new Component[4]; // Da der Button die Focusreihenfolge immer umkehrt, muss der Status gespeichert // werden private boolean reverse = false; // kapselt Information über die Reihenfolge private FocusTraversalDefinition ftd = null; /** * Konstruktor von FocusTraversalFrame. */ public FocusTraversalFrame(String title) { super(title); this.setLayout(new FlowLayout()); // Beim Klicken des Schließen-Buttons vom HauptFenster // wird das Programm beendet. this.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent we) { System.exit(0); } }); // Platzieren der Komponenten this.add(field1); this.add(field2); this.add(field3); this.add(changeOrder); // Listener wird am Button angemeldet. Jedesmal wenn geklickt wird, wird // der Komponenten-Array in entgegengesetzter Reihenfolge bestückt, und der // FocusTraversalPolicy übergeben. changeOrder.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent ae){ if(!reverse) { order[0] = changeOrder; order[1] = field3; order[2] = field2; order[3] = field1; ftd.setOrder(order); reverse=true; } else { ftd.setOrder(getInitialOrder()); reverse=false; } } }); // Hier wird die FocusTraversalPolicy mit vorgegebener Reihenfolge erstellt, // und ans Frame angemeldet. ftd = new FocusTraversalDefinition(getInitialOrder()); this.setFocusTraversalPolicy(ftd); } /** * liefert einen Komponenten-Array, in dem die Komponenten sich in der anfänglichen * Focus-Reihenfolge befinden. */ private Component[] getInitialOrder() { order[0] = field1; order[1] = field2; order[2] = field3; order[3] = changeOrder; return order; } } --- Neue Klasse --- package javacodebook.gui.focustraversal; import javax.swing.*; import java.awt.event.*; import java.awt.*; /** * @author Benjamin Rusch * * In diesem Bespiel wird demonstriert wie man die Fokus-Reihenfolge mit * der jdk1.3 Version ändern konnte. Geht aber nur für Swing, nicht für AWT. */ public class FocusTraversalJFrame extends JFrame { private JButton addButton = new JButton("Hinzufügen"); private JButton deleteButton = new JButton("Löschen"); private JTextField field = new JTextField(15); private JPanel north = new JPanel(); private JTextArea editor = new JTextArea(9,20); private Container content = null; /** * Konstruktor von FocusTraversalJFrame. */ public FocusTraversalJFrame(String title) { super(title); content = this.getContentPane(); // initialen Focus aufs TextFeld setzen addWindowListener(new WindowAdapter() { public void windowOpened(WindowEvent e) { field.requestFocus(); // Focus wird gesetzt } public void windowClosing(WindowEvent e) { System.exit(0); } }); // Anmelden eines ActionListeners an den addButton addButton.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent ae){ editor.append(field.getText()); } }); // Anmelden eines ActionListeners an den deleteButton deleteButton.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent ae){ editor.setText(""); } }); // Über setNextFocusableComponent() kann zu jeder Komponente der // direkte Nachfolger angegeben werden. Wichtig ist hierbei, dass man // den Kreis wieder schließt! addButton.setNextFocusableComponent(deleteButton); deleteButton.setNextFocusableComponent(field); field.setNextFocusableComponent(addButton); /* // Umgekehrte Reihenfolge sähe wie folgt aus: addButton.setNextFocusableComponent(field); field.setNextFocusableComponent(deleteButton); deleteButton.setNextFocusableComponent(addButton); */ // Platzieren der Komponenten north.add(addButton); north.add(deleteButton); north.add(field); content.add(north, BorderLayout.NORTH); content.add(editor); } } --- Neue Klasse --- package javacodebook.gui.focustraversal; /** * @author Benjamin Rusch * In der Starter Klasse mit der main Methode wird das FocusTraversalFrame * erstellt und sichtbar gemacht. */ public class Starter { public static void main(String[] args) { FocusTraversalJFrame ff = new FocusTraversalJFrame("Focusreihenfolge" +"mit Swing bis jdk1.3"); ff.pack(); ff.setVisible(true); FocusTraversalFrame ffNew = new FocusTraversalFrame("Focusreihenfolge" +"ab jdk1.4"); ffNew.pack(); ffNew.setVisible(true); } }