Der folgende Artikel baut auf dem vorigen Artikel zur TextPane Editierbarkeit und Sichtbarkeit auf und ergänzt ihn. Die Steuerung funktioniert bislang nur über die Buttons am oberen Rand der Form und ich möchte die Steuerung nun über die Tastatur ergänzen.
Hierzu sind lediglich ein paar zusätzliche Programmzeilen notwendig, aber Ihr solltet ein paar Stolperfallen vermeiden.
Im Initialisierungsteil der Form lege ich fest, auf welche Tasteneingaben das Programm reagieren soll. Wir haben 4 Buttons und daher lege ich 4 Tastenkombinationen zur Steuerung fest: Control-L, Control-S, Control-E und Control-W. Diese Tastenkombinationen werden intern registriert, wobei ich an dieser Stelle die gewünschten Aktionen noch nicht festlege (Zeilen 45-58 im Quelltext), sondern nur den Namen der auszuführenden Aktion nenne.
Was nach einem Tastendruck auf die Tastenkombination geschehen soll, regele ich mit den Aktionen („Action“) in den Zeilen 158-181 im Sourcecode.
Die letzte Programmanpassung betrifft die Methode „setKeyBinding“, welche die Verbindung zwischen dem Actionlistener und der Form herstellt (Zeilen 183-186). So sieht das fertige Programm in Aktion aus:
Spätestens an dieser Stelle solltet Ihr stutzen und sagen: „warum wähle ich Control-W und nicht Control-V als Steuerzeichen für Sichtbarkeit“? Die Antwort ist sehr einfach: viele Java-Komponenten reagieren bereits auf Steuerzeichen und die Tastenkombination Control-V ist für die Funktion „einfügen“ reserviert. Wenn Ihr also Control-V wählt wird das Programm nicht die „toggleVisible-Methode“ ausführen, sondern einen Text aus der Zwischenablage in die JTextPane einfügen.
Damit Ihr schnell einen Überblick über die reservierten Tastenkombinationen erhaltet könnt Ihr ein kleines Programm namens „KeyBindings.java“ ausführen und Euch Gewissheit verschaffen. In der Rubrik „Allgemeines“ findet Ihr dazu den Sourcecode und die Beschreibung des Programms A20 Key Bindings.
Hier nun die Quellcodes des Programms und der Form, Ihr benötigt intelliJ IDEA zur Nachbearbeitung:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
/* * Herkunft/Origin: http://java-crypto.bplaced.net/ * Programmierer/Programmer: Michael Fehr * Copyright/Copyright: frei verwendbares Programm (Public Domain) * Copyright: This is free and unencumbered software released into the public domain. * Lizenttext/Licence: <http://unlicense.org> * getestet mit/tested with: Java Runtime Environment 11.0.5 x64 * verwendete IDE/used IDE: intelliJ IDEA 2019.3.1 * Datum/Date (dd.mm.jjjj): 19.01.2020 * Funktion: TextPane Key Binding = * ermoeglicht eine Tastatursteuerung * Function: TextPane Key Binding = * activates some editing tasks via keyboard * * Hinweis/Notice * Sie benoetigen intelliJ um das Programm uebersetzen und ausfuehren zu koennen * You need intelliJ to build and run the program */ import javax.swing.*; import javax.swing.text.BadLocationException; import javax.swing.text.DefaultStyledDocument; import javax.swing.text.StyleContext; import javax.swing.text.StyledDocument; import javax.swing.text.rtf.RTFEditorKit; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.io.*; public class TextPane extends JFrame { private JPanel panelMain; private JPanel panelButtons; private JButton buttonLoad; private JScrollPane scrollPane; private JTextPane textPane; private JButton buttonSave; private JButton buttonEdit; private JButton buttonVisible; public TextPane() { textPane.setContentType("text/rtf"); textPane.setEditorKit(new RTFEditorKit()); scrollPane.setBorder(BorderFactory.createLineBorder(Color.BLACK)); // eventuell prüfen vorhandener "eingebauter bindings mit KeyBindings.java KeyStroke bindingKey; bindingKey = KeyStroke.getKeyStroke("control E"); // editable setKeyBinding(panelMain, bindingKey, "editableAction", textPaneEditableAction); // ACHTUNG: control V ist in JTextPane für einfügen reserviert ! bindingKey = KeyStroke.getKeyStroke("control W"); // visible setKeyBinding(panelMain, bindingKey, "visibleAction", textPaneVisibleAction); bindingKey = KeyStroke.getKeyStroke("control L"); // load setKeyBinding(panelMain, bindingKey, "loadAction", buttonLoadAction); bindingKey = KeyStroke.getKeyStroke("control S"); // save setKeyBinding(panelMain, bindingKey, "saveAction", buttonSaveAction); buttonLoad.setMnemonic(KeyEvent.VK_L); buttonEdit.setMnemonic(KeyEvent.VK_E); buttonVisible.setMnemonic(KeyEvent.VK_W); buttonSave.setMnemonic(KeyEvent.VK_S); buttonLoad.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent actionEvent) { loadRtf("textpane_rtf.rtf"); textPane.getCaret().setSelectionVisible(true); textPane.requestFocus(); } }); buttonSave.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent actionEvent) { saveRtf("textpane_rtf.rtf"); textPane.requestFocus(); } }); buttonEdit.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent actionEvent) { toggleEditable(); } }); buttonVisible.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent actionEvent) { toggleVisible(); } }); } public static void main(String[] args) { JFrame frame = new JFrame(); frame.setContentPane(new TextPane().panelMain); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setTitle("TextPane Key Binding"); frame.setSize(500, 300); frame.setVisible(true); } public void loadRtf(String filename) { RTFEditorKit RTF_KIT = new RTFEditorKit(); textPane.setContentType("text/rtf"); InputStream inputStream; try { inputStream = new FileInputStream(filename); final DefaultStyledDocument styledDocument = new DefaultStyledDocument(new StyleContext()); RTF_KIT.read(inputStream, styledDocument, 0); textPane.setDocument(styledDocument); // delete added last line String content = textPane.getDocument().getText(0, textPane.getDocument().getLength()); int lastLineBreak = content.lastIndexOf('\n'); textPane.getDocument().remove(lastLineBreak, textPane.getDocument().getLength() - lastLineBreak); } catch (IOException | BadLocationException e) { e.printStackTrace(); } textPane.setEditable(false); scrollPane.setBorder(BorderFactory.createLineBorder(Color.RED)); textPane.setVisible(true); textPane.requestFocus(); } public void saveRtf(String filename) { try { FileOutputStream fos = new FileOutputStream(filename); RTFEditorKit kit = (RTFEditorKit) textPane.getEditorKit(); StyledDocument doc = textPane.getStyledDocument(); int len = doc.getLength(); kit.write(fos, doc, 0, len); fos.close(); } catch (IOException | BadLocationException e) { e.printStackTrace(); } textPane.requestFocus(); } private void toggleEditable(){ textPane.getCaret().setSelectionVisible(true); textPane.setEditable(!textPane.isEditable()); if (textPane.isEditable() == true) { scrollPane.setBorder(BorderFactory.createLineBorder(Color.BLACK)); } else { scrollPane.setBorder(BorderFactory.createLineBorder(Color.RED)); } textPane.requestFocus(); } private void toggleVisible(){ textPane.getCaret().setSelectionVisible(true); textPane.setVisible(!textPane.isVisible()); textPane.requestFocus(); } Action buttonLoadAction = new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { buttonLoad.doClick(); } }; Action buttonSaveAction = new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { buttonSave.doClick(); } }; Action textPaneVisibleAction = new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { toggleVisible(); } }; Action textPaneEditableAction = new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { toggleEditable(); } }; private void setKeyBinding(JPanel rootPanel, KeyStroke key, String actionName, Action action) { rootPanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(key, actionName); rootPanel.getActionMap().put(actionName, action); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
<?xml version="1.0" encoding="UTF-8"?> <form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="TextPane"> <grid id="27dc6" binding="panelMain" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> <margin top="10" left="10" bottom="10" right="10"/> <constraints> <xy x="20" y="20" width="500" height="400"/> </constraints> <properties/> <border type="none"/> <children> <grid id="69623" binding="panelButtons" layout-manager="GridLayoutManager" row-count="1" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> <margin top="0" left="0" bottom="0" right="0"/> <constraints> <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/> </constraints> <properties/> <border type="none"/> <children> <component id="b1559" class="javax.swing.JButton" binding="buttonLoad"> <constraints> <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/> </constraints> <properties> <actionCommand value="load"/> <label value="load"/> <text value="load"/> </properties> </component> <component id="1e556" class="javax.swing.JButton" binding="buttonSave"> <constraints> <grid row="0" column="3" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/> </constraints> <properties> <label value="save"/> <text value="save"/> </properties> </component> <component id="ee5d5" class="javax.swing.JButton" binding="buttonEdit"> <constraints> <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/> </constraints> <properties> <actionCommand value="editable"/> <label value="editable"/> <text value="editable"/> </properties> </component> <component id="cab99" class="javax.swing.JButton" binding="buttonVisible"> <constraints> <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/> </constraints> <properties> <actionCommand value="visible w"/> <label value="visible w"/> <text value="visible w"/> </properties> </component> </children> </grid> <scrollpane id="5bf0e" binding="scrollPane"> <constraints> <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/> </constraints> <properties/> <border type="none"/> <children> <component id="100bc" class="javax.swing.JTextPane" binding="textPane"> <constraints/> <properties/> </component> </children> </scrollpane> </children> </grid> </form> |
Alle Quellcodes zur JTextPane findet Ihr zum Download in meinem Github-Repository, welches Ihr über diesen Link erreicht: https://github.com/java-crypto/JTextPane. Alle Programme sind unter Java 11 lauffähig (vermutlich auch unter Java 8) und wurden mit intelliJ IDEA entwickelt, welches für das eigene „Spielen“ notwendig ist.
Die Lizenz zum obigen Beispiel findet Ihr auf der eigenen Lizenz-Seite.
Letzte Bearbeitung: 19.01.2020