“Das kann doch nicht so schwer sein!” mag man sich denken und durchforstet stundenlang die Java-Docs. Wieso gibt es keine einfache Methode ein Popup-Menü mit Optionen zum Ausschneiden, Kopieren und Einfügen zu erstellen? Leider hilft auch das, bei vielen anderen Fragen rund um die Java-Programmierung sehr nützliche, Java-Tutorial irgendwie nicht richtig weiter. Eine Google-Suche fördert ausschließlich Code ans Tageslicht, der sofort einen Ehrenplatz im Giftschrank bekommt. Es hilft alles nichts: Man muss eine eigene, möglichst einfache Lösung basteln. Los geht’s!
Ich werde exemplarisch ein Popup-Menü für JTextField
s erstellen. Natürlich kann man die Lösung noch weiter optimieren, sie lässt sich jedoch auch ohne Probleme unverändert verwenden.
Wir machen uns die Tatsache zunutze, dass JTextField
(wie übrigens auch JEditorPane
und JTextArea
) die Klasse JTextComponent
erweitert. Dadurch erben wir direkt die Methoden cut()
, copy()
und paste()
. Wie praktisch 🙂
Außerdem ist natürlich jedes JTextField
auch eine JComponent
und erbt somit die Methode setComponentPopupMenu(JPopupMenu popup)
.
Wenn wir nun also ein geeignetes JPopupMenu
zur Verfügung stellen, welches auf dem entsprechenden JTextField
cut()
/copy()
/paste()
aufruft, haben wir unser Ziel erreicht.
Nichts leichter als das. Als erstes werden wir für jede Aktion den passenden Menü-Eintrag erstellen. Wir benötigen also drei JMenuItem
s.
Zuerst der Menüpunkt zum Ausschneiden:
private static JMenuItem getMntmAusschneiden() {
final JMenuItem mntmAusschneiden = new JMenuItem("Ausschneiden");
mntmAusschneiden.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
((JTextComponent) cutCopyPastePopup.getInvoker()).cut();
}
});
return mntmAusschneiden;
}
Bei cutCopyPastePopup
handelt es sich übrigens um unser JPopupMenu
, welches wir zur besseren Wiederverwendbarkeit als Variable definiert haben. Um eine ClassCastException
zu vermeiden könnte man noch überprüfen, ob getInvoker()
wirklich eine JTextComponent
zurückgibt.
Das Kopieren- und das Einfügen-Menü sind nach dem gleichen Muster aufgebaut:
private static JMenuItem getMntmKopieren() {
JMenuItem mntmKopieren = new JMenuItem("Kopieren");
mntmKopieren.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
((JTextComponent) cutCopyPastePopup.getInvoker()).copy();
}
});
return mntmKopieren;
}
private static JMenuItem getMntmEinfgen() {
JMenuItem mntmEinfgen = new JMenuItem("Einfügen");
mntmEinfgen.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
((JTextComponent) cutCopyPastePopup.getInvoker()).paste();
}
});
return mntmEinfgen;
}
Diese Methoden benutzen wir nun beim Zusammenbau unseres JPopupMenu
s:
public static JPopupMenu buildCutCopyPaste() {
final JPopupMenu popupMenu = new JPopupMenu();
final JMenuItem mntmAusschneiden = getMntmAusschneiden();
final JMenuItem mntmKopieren = getMntmKopieren();
final JMenuItem mntmEinfgen = getMntmEinfgen();
popupMenu.add(mntmAusschneiden);
popupMenu.add(mntmKopieren);
popupMenu.add(mntmEinfgen);
return popupMenu;
}
Vom Prinzip her sind wir hier schon fertig. Wir wollen jedoch das Verhalten des Menüs noch ein klein wenig anpassen. So wäre es schön, wenn die Menüpunkte zum Ausschneiden und Kopieren deaktiviert sind, falls kein Text im entsprechenden JTextField
markiert wurde. Außerdem macht der Menüpunkt Einfügen bei einer leeren Zwischenablage keinen Sinn. Diese Überprüfungen werden wir jedes mal vornehmen, wenn das Menü angezeigt wird. Hierfür benötigen wir noch einen PopupMenuListener
:
popupMenu.addPopupMenuListener(new PopupMenuListener() {
@Override
public void popupMenuCanceled(PopupMenuEvent e) {
// Who cares? We don't, because we don't need it.
}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
// Who cares? We don't, because we don't need it.
}
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
JTextComponent jtc = (JTextComponent) popupMenu.getInvoker();
boolean enableCutCopy =
(jtc.getSelectionEnd() - jtc.getSelectionStart()) > 0;
boolean enablePaste =
Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null) != null;
mntmAusschneiden.setEnabled(enableCutCopy);
mntmKopieren.setEnabled(enableCutCopy);
mntmEinfgen.setEnabled(enablePaste);
}
});
Fertig ist das JPopupMenu
mit Ausschneiden, Kopieren und Einfügen. Viel Spaß damit 🙂
bei mir nimmt der die zeile mit dem jtc.getSelectionEnd() als fehler an wegen dem > und der 0 hab alles ausprobiert ohne lösung
Der Code ist auch nicht vollständig. Das > soll natürlich ein ‘größer’, also > darstellen. Das wurde beim copy/pasten nach WordPress nicht korrekt übernommen. Ich schau mir das Posting nochmal genauer an, um eventuell Fehler auszubügeln. Interesse am funktionierenden Code-Beispiel?