Swing Drag&Drop einzelner Zellen in einer JTable

Status
Nicht offen für weitere Antworten.

Bieger

Mitglied
Langsam verzweifle ich mit dem Drag&Drop.

Folgende Anforderungen: Es sollen einzelne Zellen in einer JTable per D&D verschoben werden können.

Also habe ich eine JTable, bei der wird folgendes zur Initiallisierung aufgerufen:

Java:
            setDragEnabled( true );
            setDropMode( DropMode.USE_SELECTION );
            setTransferHandler( handler );
            setDefaultRenderer( DataUnit.class, new DataUnitRenderer() );
            setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
            setCellSelectionEnabled( true );
            setAutoResizeMode( JTable.AUTO_RESIZE_OFF );
            getTableHeader().setResizingAllowed( false );
            getTableHeader().setReorderingAllowed( false );

handler ist mein TransferHandler, zu dem komme ich gleich. DataUnit ist die Klasse der Objekte, die in der JTable zu liegen kommen, die haben einen eigenen Renderer. Da diese Elemente alle gleiche Größe haben und sich die Zellen nicht in der Größe ändern sollen, wird das in den letzten drei Zeilen auch so festgenagelt.

Mein TransferHandler sieht nun so aus:

Java:
        public int getSourceActions( JComponent c ) {
            return DnDConstants.ACTION_MOVE;
        }

Nur Move, denn ich will die Objekte VERSCHIEBEN, nicht kopieren, aber das ist schon das erste, das nicht funktioniert. Beim Drop bleibt nämlich die SourceUnit einfach liegen, ich habe jetzt zweimal das identische Objekt in der JTable.

Java:
        public Transferable createTransferable( JComponent comp ) {
           // kommt weiter unten (warum, wird im Text erklärt)
        }

Das erzeugt eine Wrapper-Klasse um meine eigentliche DataUnit, aber die DataUnit das Transferable-Interface implementieren zu lassen hat genauso gut funktioniert.

Java:
        public boolean canImport( TransferHandler.TransferSupport support ){
            return support.isDataFlavorSupported( DataUnit.flavor );
        }

canImport ist soweit klar.

Jetzt wird es wieder spannend.

Java:
        public boolean importData( TransferHandler.TransferSupport support ) {
            // TEIL 1
            JTable table = (JTable)support.getComponent();
            DefaultTableModel model = (DefaultTableModel)table.getModel();
            JTable.DropLocation location = (JTable.DropLocation)support.getDropLocation();

            int row = location.getRow();
            int col = location.getColumn();

            // TEIL 2
            DataUnit data = (DataUnit)support.getTransferable().getTransferData( DataUnit.flavor );

            // TEIL 3
            Object prevObj = model.getValueAt( row, col );
            if ( (prevObj!=null) && (prevObj instanceof DataUnit) )
                ((DataUnit)prevObj).combine( data );
            else
                model.setValueAt( data, row, col );

            return true;
        }

Da drin passiert nun folgendes: Ich besorge mir erstmal den Ort des Drop (Teil 1), dann das Objekt, das verschoben werden soll (Teil 2) und im Teil 3 besorge ich mir das was in der Drop-Location liegt und falls da was ist, kombiniere ich das mit dem was fallengelassen wird. Ansonsten wird einfach das Objekt dort abgelegt.

Mein Problem: Obwohl ich als SourceAction ausdrücklich nur MOVE zulasse, wird die Zelle am Ausgangspunkt des D&D nicht geleert. Um das zu gewährleisten habe ich folgendes gemacht:

Java:
        public Transferable createTransferable( JComponent comp ) {
            ...
            Object obj = table.getModel().getValueAt( row, col );
            table.getModel().setValueAt( null, row, col );
            ...
            return (Transferable)obj;
        }

D.h. beim Aufnehmen wird die Quell-Zelle geleert. Das sieht zwar auf den ersten Blick ok aus, aber wenn der Drag abgebrochen wird, ist das Objekt weg. Wenn der D&D außerhalb der JTable endet, dann genauso.

Deswegen meine Frage: Hat jemand ein Beispiel, wie D&D von Zellen in einer JTable richtig implementiert werden? Ich suche mir seit Tagen die Finger wund, ich finde nichts brauchbares. Oder kann mir bitte jemand unter die Arme greifen und ein paar Tips geben?

Das zweite Problem stelle ich erstmal zurück. Es geht dabei darum, daß während des Drags kein Symbol angezeigt wird und ich habe nicht herausgefunden, wie ich es anstelle, daß man eine visuelle Rückmeldung bekommt, daß gerade ein D&D in Aktion ist.
 

Ebenius

Top Contributor
Hier ist ein Beispiel für eine Liste. Lässt sich mit einfachen Anpassungen für die JTable nutzbar machen. Wichtig ist, dass Du ein TableModel brauchst, das auch wirklich Zeilen entfernen/hinzufügen kann. Auf keinen Fall darfst Du Änderungen am Modell machen, bevor eingefügt wird; also keine Änderungen in [c]createTransferable(...)[/c].

Hilft Dir das weiter?

Ebenius
 

Bieger

Mitglied
Auf keinen Fall darfst Du Änderungen am Modell machen, bevor eingefügt wird; also keine Änderungen in [c]createTransferable(...)[/c].

Ja, das dachte ich mir auch. Der von mir zitierte Quelltext basiert auf einem Beispiel, das ich nach längerer Suche gefunden und ausgebaut habe, aber mir kam das auch schon spanisch vor, weil das meiner Meinung nach die Zuständigkeiten verletzt.

Hilft Dir das weiter?

Ebenius

Ich werde mir dein Beispiel morgen früh reinziehen, jetzt mache ich erstmal Feierabend :)

Danke!
 

Bieger

Mitglied
Wichtig ist, dass Du ein TableModel brauchst, das auch wirklich Zeilen entfernen/hinzufügen kann.

Moin Ebenius :)

Also, ich habe mir dein Beispiel genauer angesehen. Deine Bemerkung, daß ich ein TableModel bräuchte, das Zellen einfügen/entfernen könne, habe ich nicht verstanden.

Wenn ich dein Beispiel richtig sehe, passiert beim Drop überhaupt nichts "automagisch" (wovon ich bisher immer ausgegangen war), sondern man muß tatsächlich im TransferHandler.importData() die Quelle löschen und an der Drop-Location einfügen. Verstehe ich das so richtig? Ich dachte bisher, wenn die SourceAction MOVE ist, wird das Löschen automatisch richtig von der DnD-API übernommen.

Falls das bis hierher richtig war: Was mache ich dann aber, wenn ich ein visuelles Feedback beim Move haben möchte? Anders gesagt: wenn der Benutzer die Zelle anfaßt, soll er sie auch optisch an der Maus kleben haben und die Quell-Zelle soll natürlich leer sein. Dann müßte ich doch dann im TransferHandler.createTransferable(), also das was im Moment des Aufnehmens aufgerufen wird, die Quell-Zelle löschen. Das habe ich ja probiert, aber das führt zu jeder Menge Probleme.
 

Ebenius

Top Contributor
Deine Bemerkung, daß ich ein TableModel bräuchte, das Zellen einfügen/entfernen könne, habe ich nicht verstanden.
Sollen die Zeilen denn wirklich entfernt werden, oder werden die nur geleert? Im letzteren Fall geht es mit jedem TableModel. Wenn die Zeilen wirklich entfernt werden sollen (so, dass die darunter liegenden Zeilen nach oben rutschen), dann musst Du einen konkreten TableModel-Typ kennen, das Interface [c]TableModel[/c] bietet keine Methoden zum Entfernen und Hinzufügen von Zeilen an.

Wenn ich dein Beispiel richtig sehe, passiert beim Drop überhaupt nichts "automagisch" (wovon ich bisher immer ausgegangen war),[...]
Alles was beim DnD automatisch passiert wird vom TransferHandler gemacht. Eine JTable hat einen Standard-TransferHandler. Wenn Du selber einen setzt, dann muss der halt alles können. Die verschiedenen Actions (MOVE/COPY/...) dienen als Hinweis für den TransferHandler, was er denn zu tun hat.

Sun Java™ Tutorials: Drag and Drop and Data Transfer:
The Java™ Tutorials hat gesagt.:
As mentioned previously, the default Swing transfer handlers, such as those used by text components and the color chooser, provide the support considered to be most useful for both importing and exporting of data. However list, table, and tree do not support drop by default. The reason for this is that there is no all-purpose way to handle a drop on these components. For example, what does it mean to drop on a particular node of a JTree? Does it replace the node, insert below it, or insert as a child of that node? Also, we do not know what type of model is behind the tree — it might not be mutable.

While Swing cannot provide a default implementation for these components, the framework for drop is there. You need only to provide a custom TransferHandler that manages the actual import of data.

[...] sondern man muß tatsächlich im TransferHandler.importData() die Quelle löschen und an der Drop-Location einfügen. Verstehe ich das so richtig?
Fast. Die Zeilen entfernst Du in der exportDone(...)-Methode des TransferHandlers. Wenn diese Methode aufgerufen wird, dann ist der Transfer abgeschlossen. Du musst dabei beachten: [c]exportData(...)[/c] und [c]exportDone(...)[/c] gehören der Quellkomponente und werden auf deren TransferHandler aufgerufen. [c]import...[/c] gehört der Zielkomponente und wird auf deren TransferHandler aufgerufen.

Folgendes Beispiel ist das List-Beispiel von oben auf die JTable übertragen. Wenn Du die gerade exportierten Zeilen gesondert in der JTable markieren willst, dann kann man das zum Beispiel über die Selektionsfarben machen, siehe Zeile 269 ff:

Java:
/* (@)JTableDnDFun.java */

/* Copyright 2009 Sebastian Haufe

 * Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       [url]http://www.apache.org/licenses/LICENSE-2.0[/url]

 * Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License. */

package com.ebenius;

import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.InputEvent;
import java.io.IOException;
import java.util.Arrays;
import java.util.Stack;

import javax.swing.*;
import javax.swing.border.BevelBorder;
import javax.swing.border.SoftBevelBorder;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;

/**
 * Test application for table DnD.
 * 
 * @author Sebastian Haufe
 */
public class JTableDnDFun {

  /**
   * Model bound data flavor.
   * 
   * @author Sebastian Haufe
   */
  static class TableMoveDataFlavor extends DataFlavor {

    private final DefaultTableModel model;

    public TableMoveDataFlavor(DefaultTableModel model) {
      super(TableMoveTransferData.class, "Table Data");
      this.model = model;
    }

    public DefaultTableModel getModel() {
      return model;
    }

    @Override
    public int hashCode() {
      final int prime = 31;
      int result = super.hashCode();
      result = prime * result + ((model == null) ? 0 : model.hashCode());
      return result;
    }

    @Override
    public boolean equals(DataFlavor that) {
      if (this == that) {
        return true;
      }
      if (!super.equals(that) || getClass() != that.getClass()) {
        return false;
      }
      return match(model, that);
    }

    /**
     * Tests whether the given data flavor is a {@link TableMoveDataFlavor}
     * and matches the given model.
     * 
     * @param model the model
     * @param flavor the flavor
     * @return {@code true} if matches
     */
    public static boolean match(DefaultTableModel model, DataFlavor flavor) {
      return flavor instanceof TableMoveDataFlavor
            && ((TableMoveDataFlavor) flavor).getModel() == model;
    }
  }

  /**
   * Model bound and index based transfer data.
   * 
   * @author Sebastian Haufe
   */
  private static class TableMoveTransferData {

    private final DefaultTableModel model;
    private final int[] indices;

    TableMoveTransferData(DefaultTableModel model, int[] indices) {
      this.model = model;
      this.indices = indices;
    }

    int[] getIndices() {
      return indices;
    }

    public DefaultTableModel getModel() {
      return model;
    }
  }

  /**
   * Model bound transferable implementation.
   * 
   * @author Sebastian Haufe
   */
  static class TableMoveTransferable implements Transferable {

    private final TableMoveTransferData data;

    public TableMoveTransferable(TableMoveTransferData data) {
      this.data = data;
    }

    public DataFlavor[] getTransferDataFlavors() {
      return new DataFlavor[] { new TableMoveDataFlavor(data.getModel()) };
    }

    public boolean isDataFlavorSupported(DataFlavor flavor) {
      return TableMoveDataFlavor.match(data.getModel(), flavor);
    }

    public Object getTransferData(DataFlavor flavor)
          throws UnsupportedFlavorException, IOException {
      if (!isDataFlavorSupported(flavor)) {
        throw new UnsupportedFlavorException(flavor);
      }
      return data;
    }
  }

  /**
   * Table transfer handler.
   * 
   * @author Sebastian Haufe
   */
  static class TableMoveTransferHandler extends TransferHandler {

    /** Serial version UID */
    private static final long serialVersionUID = 6703461043403098490L;
    private Color restoreForeground;
    private Color restoreBackground;

    @Override
    public int getSourceActions(JComponent c) {
      final JTable table = (JTable) c;
      return table.getModel() instanceof DefaultTableModel ? MOVE : NONE;
    }

    @Override
    public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) {
      if (!(comp instanceof JTable)
            || !(((JTable) comp).getModel() instanceof DefaultTableModel)) {
        return false;
      }

      final DefaultTableModel model =
            (DefaultTableModel) ((JTable) comp).getModel();
      for (DataFlavor f : transferFlavors) {
        if (TableMoveDataFlavor.match(model, f)) {
          return true;
        }
      }
      return false;
    }

    @Override
    protected Transferable createTransferable(JComponent c) {
      final JTable table = (JTable) c;
      final int[] rows = table.getSelectedRows();
      for (int i = 0; i < rows.length; i++) {
        rows[i] = table.convertRowIndexToModel(rows[i]);
      }
      return new TableMoveTransferable(new TableMoveTransferData(
            (DefaultTableModel) table.getModel(), rows));
    }

    @Override
    public boolean importData(TransferHandler.TransferSupport info) {
      final Component comp = info.getComponent();
      if (!info.isDrop() || !(comp instanceof JTable)) {
        return false;
      }
      final JTable table = (JTable) comp;
      final TableModel tm = table.getModel();
      if (!(tm instanceof DefaultTableModel)) {
        return false;
      }

      final DefaultTableModel tableModel = (DefaultTableModel) tm;
      final DataFlavor flavor = new TableMoveDataFlavor(tableModel);
      if (!info.isDataFlavorSupported(flavor)) {
        return false;
      }

      final Transferable transferable = info.getTransferable();
      try {
        final TableMoveTransferData data =
              (TableMoveTransferData) transferable.getTransferData(flavor);

        // get the initial insertion index
        final JTable.DropLocation dropLocation = table.getDropLocation();
        int insertAt = table.convertRowIndexToModel(dropLocation.getRow());

        // get the indices sorted (we use them in reverse order, below)
        final int[] rows = data.getIndices();
        Arrays.sort(rows);

        // remove old elements from model, store them on stack
        final Stack<Object[]> elements = new Stack<Object[]>();
        int shift = 0;
        for (int i = rows.length - 1; i >= 0; i--) {
          final int rowIndex = rows[i];
          if (rowIndex < insertAt) {
            shift--;
          }
          final int columnCount = tableModel.getColumnCount();
          final Object[] rowData = new Object[columnCount];
          for (int colIndex = 0; colIndex < columnCount; colIndex++) {
            rowData[colIndex] = tableModel.getValueAt(rowIndex, colIndex);
          }
          tableModel.removeRow(rowIndex);
          elements.push(rowData);
        }
        insertAt += shift;

        // insert stored elements from stack to model
        final ListSelectionModel sm = table.getSelectionModel();
        try {
          sm.setValueIsAdjusting(true);
          sm.clearSelection();
          final int anchor = insertAt;
          while (!elements.isEmpty()) {
            tableModel.insertRow(insertAt, elements.pop());
            sm.addSelectionInterval(insertAt, insertAt++);
          }
          final int lead = insertAt - 1;
          if (!sm.isSelectionEmpty()) {
            sm.setAnchorSelectionIndex(anchor);
            sm.setLeadSelectionIndex(lead);
          }
        } finally {
          sm.setValueIsAdjusting(false);
        }
        return true;
      } catch (UnsupportedFlavorException ex) {
        return false;
      } catch (IOException ex) {
        // FIXME: Logging
        return false;
      }
    }

    @Override
    protected void exportDone(JComponent source, Transferable data, int action) {
      super.exportDone(source, data, action);
      if (source instanceof JTable) {
        final JTable table = (JTable) source;
        table.setSelectionForeground(restoreForeground);
        table.setSelectionBackground(restoreBackground);
      }
    }

    @Override
    public void exportAsDrag(JComponent comp, InputEvent e, int action) {
      if (comp instanceof JTable) {
        final JTable table = (JTable) comp;
        restoreForeground = table.getSelectionForeground();
        restoreBackground = table.getSelectionBackground();
        table.setSelectionForeground(Color.GRAY);
        table.setSelectionBackground(Color.GRAY);
      }
      super.exportAsDrag(comp, e, action);
    }
  }

  // -------------------------------------------------------------------------
  // Program Entry Point
  // -------------------------------------------------------------------------

  /**
   * Test main method.
   * 
   * @param args ignored
   */
  public static void main(String[] args) {
    final DefaultTableModel lm1 = new DefaultTableModel(0, 1);
    final DefaultTableModel lm2 = new DefaultTableModel(0, 1);
    for (Object o : new Object[] { "A", "B", "C", "D", "E", "F", "G", "H" }) {
      final Object[] row = new Object[] { o };
      lm1.addRow(row);
      lm2.addRow(row);
    }
    final JComponent sp1 = createTableAndScrollPane(lm1);
    final JComponent sp2 = createTableAndScrollPane(lm2);
    final JComponent sp3 = createTableAndScrollPane(lm2);

    final JPanel indiPanel = new JPanel(new BorderLayout(6, 6));
    indiPanel.add(sp1, BorderLayout.CENTER);
    indiPanel.setBorder(BorderFactory.createTitledBorder(new SoftBevelBorder(
          BevelBorder.LOWERED), "Independent Model"));

    final JPanel sharedPanel = new JPanel(new GridLayout(1, 0, 6, 6));
    sharedPanel.add(sp2);
    sharedPanel.add(sp3);
    sharedPanel.setBorder(BorderFactory.createTitledBorder(
          new SoftBevelBorder(BevelBorder.LOWERED), "Shared Model"));

    final JPanel contentPane = new JPanel(new BorderLayout(6, 6));
    contentPane.add(indiPanel, BorderLayout.LINE_START);
    contentPane.add(sharedPanel, BorderLayout.CENTER);

    final JFrame f = new JFrame("Test Frame: RobotTest"); //$NON-NLS-1$
    f.setContentPane(contentPane);
    f.pack();
    f.setLocationRelativeTo(null);
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.setVisible(true);
  }

  private static JScrollPane createTableAndScrollPane(DefaultTableModel model) {
    final JTable table = new JTable(model);
    table.setDragEnabled(true);
    table.setDropMode(DropMode.INSERT);
    table.setTransferHandler(new TableMoveTransferHandler());
    final JScrollPane sp = new JScrollPane(table);
    return sp;
  }
}
Du könntest Dir alternativ zum Ändern der Selektionsfarben auch eigene CellRenderer implementieren, die den Status der gerade verschobenen Zellen von Deiner JTable(-Ableitung) abfragen und anders darstellen. In jedem Fall: Verändere nicht das Modell der Quellkomponente, bevor der Transfer abgeschlossen ist!

Ebenius
 
Zuletzt bearbeitet:

Bieger

Mitglied
Sollen die Zeilen denn wirklich entfernt werden, oder werden die nur geleert? Im letzteren Fall geht es mit jedem TableModel.

Nein, das hatte ich unklar beschrieben, die Zellen sollen nicht entfernt werden, nur der Inhalt. Im Prinzip soll das so aussehen wie ein (variables) Schachbrett, auf dem man die Zelleninhalte per D&D hin und her verschieben kann.

Vielen herzlichen Dank für dein Beispiel, das hat mir wirklich sehr geholfen! :toll:

Du könntest Dir alternativ zum Ändern der Selektionsfarben auch eigene CellRenderer implementieren, die den Status der gerade verschobenen Zellen von Deiner JTable(-Ableitung) abfragen und anders darstellen. In jedem Fall: Verändere nicht das Modell der Quellkomponente, bevor der Transfer abgeschlossen ist!

Ebenius

Einen eigenen CellRenderer habe ich schon, weil in den Zellen relativ aufwendige Statuskärtchen dargestellt werden müssen, die man eben auf diesem "Schachbrett" verschieben können soll.

In diesem Zusammenhang noch eine Frage: Kannst Du mir verraten, wie man es anstellt, daß ein selbst definierbares Image während des Drags angezeigt wird? Anstelle oder zusätzlich zum Mauszeiger.
 

Bieger

Mitglied
In diesem Zusammenhang noch eine Frage: Kannst Du mir verraten, wie man es anstellt, daß ein selbst definierbares Image während des Drags angezeigt wird? Anstelle oder zusätzlich zum Mauszeiger.

Anmerkung: Die Methode TransferHandler.getVisualRepresentation() wird nicht aufgerufen, was ich aber erwartet hätte. Deswegen meine Frage.
 

Ebenius

Top Contributor
Anmerkung: Die Methode TransferHandler.getVisualRepresentation() wird nicht aufgerufen, was ich aber erwartet hätte. Deswegen meine Frage.
An der Stelle fehlt mir der Einblick. Ich kann aber (als Benutzer) auf riesige halbtransparente Bilder, die ich an der Maus mit mir rumschiebe, sehr gut verzichten. Dass es nicht funktioniert wusste ich, warum das so ist, weiß ich nicht. :)

Smile and wave.

Ebenius
 

André Uhres

Top Contributor
Bei TransferHandler.getVisualRepresentation() sucht man nach einer kompletten Lösung, die auch noch zwischen zwei Anwendungen funktioniert. Solange das nicht geht, wird die Methode nicht funktionieren. Derweil kann man Drag Bilder für die eigene Anwendung selbst implementieren indem man Glasspane benutzt.
 

Bieger

Mitglied
Ich kann aber (als Benutzer) auf riesige halbtransparente Bilder, die ich an der Maus mit mir rumschiebe, sehr gut verzichten.

Naja, ich nicht. Oder besser gesagt: Die Anwender, die damit mal arbeiten sollen, können nicht darauf verzichten, eine deutliche visuelle Rückmeldung zu bekommen, daß sie gerade einen Drag durchführen. So wie es jetzt ist, sieht man nämlich nur mit der Lupe an dem kleinen Rechteck unter der Maus, daß ein Drag stattfindet. Das ist für die Zielgruppe, für die ich das Programm schreibe keine Option. Und ehrlich gesagt für mich auch nicht, denn ich bin deutlich bessere GUIs von meinem Mac gewohnt.

Ich mußte schon andere Kröten bei diesem Projekt schlucken, z.B. daß es anscheinend nicht möglich ist in einer JTable Zellen zu verbinden, um z.B. einen über mehrere Spalten reichenden TableHeader zu realisieren. Und nun auch noch das. Irgendwann muß ich mich noch rechtfertigen, warum ich überhaupt Java dazu genommen habe *grrr* Ich bin zwar kein Java-Anfänger, aber mit GUI und Swing hatte ich bisher nicht so viel Erfahrung, nur die Erlebnisse die ich bisher damit hatte, sind eher negativ gefärbt.

Danke an André Uhres, ich werde mir das als Schmankerl ganz zu Projektende aufheben, falls dann noch Zeit übrig sein sollte. Vorausgesetzt man nimmt mir einen Drag ohne visuelle Rückmeldung ab :-D
 

André Uhres

Top Contributor
Ich hab mal auf die Schnelle ein Beispiel zusammengestrickt (Quellcode im jar). Es nutzt die DropTarget#dragOver Methode um das Bild synchron zu zeichnen. Es kann übrigens auch mehrere zusammenhängende Zellen einer Zeile verschieben:
 
Zuletzt bearbeitet:

Firestorm87

Bekanntes Mitglied
Danke, das Beispiel ist gelungen und lässt sich nach dem aufdröseln in mehrere externe klassen auch gut nachvollziehen...
 

André Uhres

Top Contributor
Danke, das Beispiel ist gelungen und lässt sich nach dem aufdröseln in mehrere externe Klassen auch gut nachvollziehen...

Ich bin froh, dass du es nützlich findest. Das "aufdröseln in mehrere externe Klassen" ist ja auch kein Problem, denn "DragDropJTableCellContents.java" hat außer drei sehr kleinen anonymen Klassen eh keine inneren Klassen (auch wenn sie alle in einer Datei stehen, sind sie in Wirklichkeit keine "inneren" Klassen).
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
J Drag und drop aus einer JTable - bitte um Unterstützung AWT, Swing, JavaFX & SWT 2
G JPanel per Drag and Drop JButtons und Bilder ablegen AWT, Swing, JavaFX & SWT 1
AmsananKING ListView Drag And Drop AWT, Swing, JavaFX & SWT 0
AmsananKING Drag And Drop Filenames Inside A Listview AWT, Swing, JavaFX & SWT 1
DonBronson Java Graphics bewegbar machen (Drag&Drop) AWT, Swing, JavaFX & SWT 3
M Polygon per Drag&Drop verschieben AWT, Swing, JavaFX & SWT 26
Z Swing Drag and Drop mit einem JButton AWT, Swing, JavaFX & SWT 1
N Drag and Drop Fenster AWT, Swing, JavaFX & SWT 11
F Drag&Drop mit Transparenter Farbe bei PNG AWT, Swing, JavaFX & SWT 0
D JavaFX Pane per Drag&Drop bewegen? AWT, Swing, JavaFX & SWT 2
L JavaFX Drag and Drop funktioniert nicht AWT, Swing, JavaFX & SWT 3
J Drag and Drop von eigenen Objekten AWT, Swing, JavaFX & SWT 3
J Drag and Drop eines Buttons AWT, Swing, JavaFX & SWT 0
T Swing Drag and Drop für JComponents AWT, Swing, JavaFX & SWT 1
Z Swing Drag&Drop zwischen JTable und JTree AWT, Swing, JavaFX & SWT 4
F Drag und Drop AWT, Swing, JavaFX & SWT 0
L JavaFX JavaFX Chart Drag and Drop AWT, Swing, JavaFX & SWT 3
D JavaFX Drag&Drop mehrerer TreeViews oder TableViews AWT, Swing, JavaFX & SWT 1
P Drag & Drop zwischen Panels AWT, Swing, JavaFX & SWT 0
U Drag and Drop mit imageview AWT, Swing, JavaFX & SWT 0
U Drag and Drop imageviews AWT, Swing, JavaFX & SWT 8
D SteelSeries in Netbeans als Drag-and-Drop einbinden AWT, Swing, JavaFX & SWT 0
C JTable Drag and Drop von Zeilen innerhalb einer Table AWT, Swing, JavaFX & SWT 2
S Swing Update eine JTabelle nach einer Drag&Drop Operation AWT, Swing, JavaFX & SWT 0
S Swing Suche Drag & Drop Beispiele AWT, Swing, JavaFX & SWT 1
A Drag and Drop mit JAVAFX- Scenebuilder AWT, Swing, JavaFX & SWT 1
R Performance Drag and Drop & Timer AWT, Swing, JavaFX & SWT 3
R Drag and Drop Problem auf Jpanel AWT, Swing, JavaFX & SWT 2
N Swing JTable und Drag und Drop AWT, Swing, JavaFX & SWT 2
A Drag and Drop eigener Objekte AWT, Swing, JavaFX & SWT 7
C Drag and Drop (inventar) AWT, Swing, JavaFX & SWT 15
F Swing Drag and Drop in JTree aus verschiedenen Listen AWT, Swing, JavaFX & SWT 6
T Swing JButton per Drag&Drop verschieben AWT, Swing, JavaFX & SWT 5
Iron Monkey JFileChooser - Drag and Drop AWT, Swing, JavaFX & SWT 5
Iron Monkey Nach Drag & Drop die Datei auf Komponent darstellen AWT, Swing, JavaFX & SWT 2
M AWT Drag n Drop-Support für Component AWT, Swing, JavaFX & SWT 5
HaukeG Swing Drag & Drop in verschiedenen Varianten AWT, Swing, JavaFX & SWT 4
S Swing Drag&Drop mit TransferHandler und JPanels AWT, Swing, JavaFX & SWT 8
C Swing Simulation von Drag and Drop Events AWT, Swing, JavaFX & SWT 3
H Swing "Drag and Drop" eines JComponent über ein JPanel AWT, Swing, JavaFX & SWT 2
R Drag 'n Drop AWT, Swing, JavaFX & SWT 3
S Selektion bei Drag&Drop AWT, Swing, JavaFX & SWT 4
C Swing Drag and Drop mit Objekten in einem Fenster. AWT, Swing, JavaFX & SWT 9
T SWT Drag&Drop: Eclipse FileTransfer mit Icons AWT, Swing, JavaFX & SWT 14
F Drag & Drop durch Verbindungslinien AWT, Swing, JavaFX & SWT 10
T Swing Drag and Drop - JLabels tauschen statt überschreiben AWT, Swing, JavaFX & SWT 11
S Drag and Drop über 2 Panels AWT, Swing, JavaFX & SWT 2
K JButtons innerhalb eines JPanels verschieben (DRAG&DROP) AWT, Swing, JavaFX & SWT 5
B Drag and Drop AWT, Swing, JavaFX & SWT 6
K Drag and Drop Workbench AWT, Swing, JavaFX & SWT 2
P SWT Eclipse Draw2D Drag and Drop (ruckelt) AWT, Swing, JavaFX & SWT 4
F SWT Drag and Drop im TreeViewer AWT, Swing, JavaFX & SWT 4
B Swing Drag&Drop mit Feedback (Image am Mauszeiger) AWT, Swing, JavaFX & SWT 7
Spin JFrame/ Frame Drag and Drop AWT, Swing, JavaFX & SWT 13
A TransferHandler & Drag n' Drop AWT, Swing, JavaFX & SWT 2
R Drag an Drop JTable Zelle AWT, Swing, JavaFX & SWT 6
D Drag & Drop - node.isRoot AWT, Swing, JavaFX & SWT 3
E Swing Drag n Drop Verschieben von Labels o.ä. AWT, Swing, JavaFX & SWT 10
E Swing Beim Drag & Drop, Drag verbieten?! AWT, Swing, JavaFX & SWT 2
E JTree Autoscroll bei Drag and Drop AWT, Swing, JavaFX & SWT 4
F Swing Problem mit Drag&Drop in JTable AWT, Swing, JavaFX & SWT 4
C keine weiteren Events während Drag&Drop Operation möglich? AWT, Swing, JavaFX & SWT 5
E Drag&Drop zwischen 2 Listen AWT, Swing, JavaFX & SWT 5
0 Swing Drag n' Drop Bug wenn Source und Target gleiche Komponente? AWT, Swing, JavaFX & SWT 4
C Drag and Drop JPanel auf JPanel nach drop erneut verschieben? AWT, Swing, JavaFX & SWT 3
M Swing JTable Drag'n'Drop von Dateien AWT, Swing, JavaFX & SWT 3
M Drag and Drop: Quellfenster AWT, Swing, JavaFX & SWT 2
M Buttons per Drag & Drop im GridBagLayout verschieben AWT, Swing, JavaFX & SWT 6
M Swing JList > Drag & Drop AWT, Swing, JavaFX & SWT 2
C Drag an Drop vom JTree zur JTable AWT, Swing, JavaFX & SWT 4
Z Drag and Drop auf Application AWT, Swing, JavaFX & SWT 3
G Drag and Drop JTree to Canvas AWT, Swing, JavaFX & SWT 7
H Drag&Drop von JComponents AWT, Swing, JavaFX & SWT 6
G JTable drag and drop AWT, Swing, JavaFX & SWT 4
H Drag&Drop mit GWT AWT, Swing, JavaFX & SWT 8
A Swing Drag and Drop TreeNode User Object AWT, Swing, JavaFX & SWT 3
P JList: Reihenfolge der Elemente per Drag'n'Drop ändern. AWT, Swing, JavaFX & SWT 9
K Swing Wie ändere ich die default action für Drag&Drop AWT, Swing, JavaFX & SWT 6
R JLayeredPane - Drag&Drop - mouseDragged AWT, Swing, JavaFX & SWT 6
C JTable mit RowSorter und Drag & Drop: Zeile verschieben AWT, Swing, JavaFX & SWT 4
V SWT TreeViewer Drag'n'Drop LocalSelectionTransfer AWT, Swing, JavaFX & SWT 10
R Swing JLayeredPane - Drag&Drop Positionen vertauschen AWT, Swing, JavaFX & SWT 3
F Drag & Drop mit eigenen Komponenten AWT, Swing, JavaFX & SWT 2
B SWT - Drag & Drop innerhalb einer Table AWT, Swing, JavaFX & SWT 3
S Drag'n'Drop AWT, Swing, JavaFX & SWT 8
E Drag&Drop JTable; Renderer füllt alle Zellen AWT, Swing, JavaFX & SWT 10
M Drag & Drop in Swing (createTransferable) AWT, Swing, JavaFX & SWT 6
T Drag Quelle beim Drop AWT, Swing, JavaFX & SWT 6
A Drag & Drop von Zeilen innerhalb einer Tabelle AWT, Swing, JavaFX & SWT 2
E Drag & Drop von jTree in JList AWT, Swing, JavaFX & SWT 5
P Dateien per Drag&Drop ins Java-Fenster ziehen AWT, Swing, JavaFX & SWT 8
G JTree Node ggf. aufklappen bei Drag & Drop? AWT, Swing, JavaFX & SWT 7
J Drag'n Drop imm selben Frame unterbinden AWT, Swing, JavaFX & SWT 3
S Table Row per Drag and Drop in andere Table schieben? AWT, Swing, JavaFX & SWT 14
X wiedermal Drag n Drop AWT, Swing, JavaFX & SWT 2
P Drag & Drop AWT, Swing, JavaFX & SWT 2
X Drag and Drop AWT, Swing, JavaFX & SWT 2
F Drag&Drop Jlist -> JList AWT, Swing, JavaFX & SWT 3
G Drag and Drop mal wieder? AWT, Swing, JavaFX & SWT 2
G Drag And Drop von Component (List, Tree) zum Desktop AWT, Swing, JavaFX & SWT 2

Ähnliche Java Themen

Neue Themen


Oben