Verwandt zu meinem Problem in http://forum.byte-welt.net/java-forum-erste-hilfe-vom-java-welt-kompetenz-zentrum/awt-swing-javafx-swt/15124-drop-inhalt-bearbeiten.html suche ich nach einer Möglichkeit, den originalen Feldinhalt vor dem Einfügen per Drag ‘n’ Drop zu löschen.
Meine Ansätze sehen bisher wie folgt aus:
Testprogramm:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.util.TooManyListenersException;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class DragNDropTest {
private final JFrame frame;
private final JTextField nameField;
private final JTextField addressField;
private final JTextField phoneField;
public DragNDropTest() {
frame = new JFrame();
nameField = new JTextField();
addressField = new JTextField();
phoneField = new JTextField();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
createGUI();
nameField.setText("Irgendein störender alter Namensinhalt.");
addressField.setText("Irgendein störender alter Adressinhalt.");
phoneField.setText("Irgendein störender alter Telefonnummerninhalt.");
}
});
}
private void createGUI() {
frame.setTitle("Wie überschreibe ich bei Drag 'n' Drop?");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(createCenterPart(), BorderLayout.CENTER);
frame.add(createLowerPart(), BorderLayout.SOUTH);
frame.pack();
}
private Component createCenterPart() {
JEditorPane editorPane = new JEditorPane();
editorPane.setEditable(false);
editorPane.setBackground(new Color(0xf0, 0xe6, 0x8c));
editorPane.setContentType("text/html");
editorPane.setCaretPosition(0);
editorPane.setDragEnabled(true);
editorPane.setText("<html><body>"
+ "<p>Peter Müller, Musterweg 17, 12345 Musterstadt, +49 123 456 789 000</p>"
+ "<p>Markus Meier, Mustergasse 3a, 12346 Musterhausen, +49 999 123 456 000</p>"
+ "<p>Stefan Schmidt, Musterstraße 1-3, 12347 Bad Musterlingen, +49 456 123 789 000</p>"
+ "</body></html>");
JScrollPane scroll = new JScrollPane(editorPane);
scroll.setPreferredSize(new Dimension(600, 200));
return scroll;
}
private Component createLowerPart() {
JPanel panel = new JPanel();
panel.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(0, 1, 0, 1);
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.anchor = GridBagConstraints.WEST;
gbc.weighty = 0.0;
gbc.gridy = -1;
{
++gbc.gridy;
gbc.gridx = 0;
gbc.weightx = 0.0;
panel.add(new JLabel("Name"), gbc);
gbc.gridx = 1;
gbc.weightx = 1.0;
addNormalFieldCorrector(nameField);
panel.add(nameField, gbc);
}
{
++gbc.gridy;
gbc.gridx = 0;
gbc.weightx = 0.0;
panel.add(new JLabel("Adresse"), gbc);
gbc.gridx = 1;
gbc.weightx = 1.0;
addNormalFieldCorrector(addressField);
panel.add(addressField, gbc);
}
{
++gbc.gridy;
gbc.gridx = 0;
gbc.weightx = 0.0;
panel.add(new JLabel("Telefon"), gbc);
gbc.gridx = 1;
gbc.weightx = 1.0;
addNormalFieldCorrector(phoneField);
panel.add(phoneField, gbc);
}
return panel;
}
private void addNormalFieldCorrector(final JTextField field) {
try {
field.getDropTarget().addDropTargetListener(
new NormalFieldDropTargetListener(field));
//field.getDropTarget().addDropTargetListener(
// new RemoveAndInsertFieldDropTargetListener(field));
}
catch (TooManyListenersException e1) {
e1.printStackTrace();
}
}
public void setVisual(final boolean visual) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
frame.setVisible(visual);
}
});
}
public static void main(String[] args) {
DragNDropTest demo = new DragNDropTest();
demo.setVisual(true);
}
}
Version 1 (im Programm oben aktiviert): Ein DropTargetListener
der den alten Feldinhalt löscht, falls der neue Feldinhalt dahinter eingefügt wird:
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class NormalFieldDropTargetListener implements DropTargetListener {
private final JTextField field;
//private boolean entered;
private String oldContent;
public NormalFieldDropTargetListener(final JTextField field) {
this.field = field;
}
@Override
public void dragEnter(DropTargetDragEvent dtde) {
//entered = true;
oldContent = field.getText();
}
@Override
public void dragOver(DropTargetDragEvent dtde) {
}
@Override
public void dropActionChanged(DropTargetDragEvent dtde) {
}
@Override
public void dragExit(DropTargetEvent dte) {
//entered = false;
//oldContent = "";
}
@Override
public void drop(DropTargetDropEvent dtde) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
editContent();
}
});
}
private void editContent() {
String text = field.getText();
//System.out.println("text:" + text);
//System.out.println("entered:" + entered); // true
//System.out.println("oldContent:" + oldContent);
/* Alten Inhalt vorn entfernen: */
if (text.startsWith(oldContent)) {
text = text.substring(oldContent.length());
}
/*
* Besser wäre es, den alten Text vorher komplett zu löschen. Aber das
* ist hier nicht gut möglich.
* Man kommt nämlich nicht mit diesen Methoden an die Stelle, wo der
* Mausklick über "unserem" JTextField ausgelöst wurde, der Drop-Text
* aber noch nicht eingefügt wurde.
*
* Löscht man ihn etwa in dragEnter(), wird der Inhalt auch gelöscht,
* wenn dann auf einem anderen Textfeld die Maus losgelassen wird.
*/
text = text.trim();
field.setText(text);
}
}
Version 2 (dafür müssen die auskommentierten Zeilen oben aktiviert und die davor auskommentiert werden): Ein DropTargetListener
der den alten Feldinhalt löscht, sobald der Mousecursor das Feld betritt und ihn wieder einfügt, wenn kein Drop stattfand und das Feld verlassen wurde:
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import javax.swing.JTextField;
public class RemoveAndInsertFieldDropTargetListener implements DropTargetListener {
private final JTextField field;
private boolean inserted;
private String oldContent;
public RemoveAndInsertFieldDropTargetListener(final JTextField field) {
this.field = field;
}
@Override
public void dragEnter(DropTargetDragEvent dtde) {
oldContent = field.getText();
field.setText("");
inserted = false;
}
@Override
public void dragOver(DropTargetDragEvent dtde) {
}
@Override
public void dropActionChanged(DropTargetDragEvent dtde) {
}
@Override
public void dragExit(DropTargetEvent dte) {
if (!inserted) {
field.setText(oldContent);
}
inserted = false;
}
@Override
public void drop(DropTargetDropEvent dtde) {
inserted = true;
}
}
Es gibt aber sicher auch eine natürlichere und elegantere Lösung. Kennt sie jemand?