11

OK、この問題は私のリーグ外です。ファイルをJTableにドロップし、JTableの行をドラッグして並べ替えることができるGUIウィジェットをswingで実装しようとしています。VLCのプレイリストまたはiTunesのプレイリストを考えてみてください。

OS(Explorer、Finderなど)からファイルをドロップしても問題なく動作しましたが、ファイルが入った後、テーブルの行を再配置するのに不可能な時間があります。問題は、追加するときにカスタムTransferHandlerをテーブルにドラッグすると、テーブルからのドラッグは即座に強制終了されます。次にいくつかのサンプルコードを示します。

import javax.swing.*;

public class TableTest
{
    public static void main (String [] argv)
    {
        // setup table data
        String [] columns = new String [] {"Foo", "Bar", "Baz", "Quux"};
        String [][] data = new String [][] {{"A", "B", "C", "D"},
                        {"1", "2", "3", "4"},
                        {"i", "ii", "iii", "iv"}};
        // create table
        JTable table = new JTable(data, columns);

        // set up drag and drop
        table.setDragEnabled(true);
        table.setDropMode(DropMode.INSERT_ROWS);
        table.setFillsViewportHeight(true);
        TransferHandler dnd = new TransferHandler() {
            // here be code to handle drops, and one would
            // presume drag exporting, too
        };
        table.setTransferHandler(dnd);
        JScrollPane scroll = new JScrollPane(table);

        // create and show window
        JFrame window = new JFrame();
        window.getContentPane().add(scroll);
        window.pack();
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        window.setVisible(true);
    }
}

このコードをそのまま実行すると、テーブルでドラッグを開始できないことがわかります。テーブルでsetTransferHandler()の呼び出しをコメントアウトすると、ドラッグが機能します(つまり、テーブル行のドラッグを開始すると、次のようになります。 Xは、そこにドロップできないことを示す円カーソルを出力します)。しかし、TransferHandlerがテーブルに設定されるとすぐに、行をドラッグできなくなります。問題はTransferHandlerにある必要がありますが、徹底的にトラブルシューティングしてデバッグし、テーブルにTransferHandlerがあるとドラッグが開始されないことを確認しました。私は何が間違っているのですか?

4

4 に答える 4

6

私は同じ問題を抱えていました.TransferHandlerのカスタム実装とは何の関係もありません. TransferHandler を置き換えるときは、デフォルトの DragSource を取得して、ドラッグ ジェスチャを認識するように指示する必要もあります。DragGestureEvent.startDrag() メソッドに渡す必要があるため、独自の Transferable を実装する必要がある場合もあります。

    table.setTransferHandler(new MyTransferHandler());
    table.setDragEnabled(true);
    DragSource source = DragSource.getDefaultDragSource();
    source.createDefaultDragGestureRecognizer(table, DnDConstants.ACTION_COPY, new DragGestureListener() {

        @Override
        public void dragGestureRecognized(DragGestureEvent dge) {
            //grab the selected files from the table model
            ArrayList<File> files = new ArrayList<File>();
            for (int row : table.getSelectedRows()) {
                files.add((File) dm.getValueAt(row, 1));
            }

            //FileTransferable is a custom Transferable implementation
            Transferable transferable = new FileTransferable(files); 

            //and this is the magic right here
            dge.startDrag(null,transferable);
        }
    });
于 2010-03-03T23:35:54.973 に答える
3

TransferHandlerを正しく使用しているようには見えません。こちらのチュートリアルをお読みください。

こちらのTransferHandlerドキュメントを参照してください。空のコンストラクターは、TransferHandlerのサブクラスの外部で使用するためのものではないようです。

また、Swingコンポーネントで提供される標準のTransferHandlerで提供される機能は実装していません。ここでDnDチュートリアルからの抜粋を参照してください(私の太字):

注:カスタムTransferHandlerをSwingコンポーネントにインストールすると、デフォルトのサポートが置き換えられます。たとえば、JTextFieldのTransferHandlerを色のみを処理するものに置き換えると、テキストのインポートとエクスポートをサポートする機能が無効になります。 デフォルトのTransferHandler(たとえば、テキストを処理するもの)を置き換える必要がある場合は、テキストのインポートおよびエクスポート機能を再実装する必要があります。これは、Swingが提供するものほど広範囲である必要はありません。アプリケーションのニーズに応じて、StringFlavorデータフレーバーをサポートするのと同じくらい簡単にすることができます。

于 2009-04-07T19:16:18.797 に答える
3

問題は、空の TransferHandler が実際に DnD イベントの発生を妨げていることだと思います。ここに関連する可能性のあるサンプルがあります。

http://www.java2s.com/Code/Java/Swing-JFC/ExtendedDnDDragandDropDemo.htm

于 2009-04-07T19:26:01.363 に答える
1

何が起こっているのかを詳しく知りたくなかったので、興味のないメソッドを古い TransferHandler に委譲しました。

tree.setDragEnabled(true);
tree.setDropMode(DropMode.XXXX);
tree.setTransferHandler(new MyTransferHandler(tree.getTransferHandler());

標準のセットアップから始めますが、古い TransferHandler をカスタム TransferHandler に渡します。

private class MyTransferHandler extends TransferHandler {
  private TransferHandler delegate;

  public MyTransferHandler(TransferHandler delegate) {
    this.delegate = delegate;
  }

  public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) {
    return delegate.canImport(comp, transferFlavors);
  }

  public boolean canImport(TransferSupport support) {
    return true;
  }

  protected Transferable createTransferable(JComponent c) {
    try {
      Method method = delegate.getClass().getDeclaredMethod("createTransferable", JComponent.class);
      method.setAccessible(true);
      return (Transferable) method.invoke(delegate, c);
    } catch (Exception e) {
      return super.createTransferable(c);
    }
  }

  public void exportAsDrag(JComponent comp, InputEvent event, int action) {
    delegate.exportAsDrag(comp, event, action);
  }

  protected void exportDone(JComponent source, Transferable data, int action) {
    try {
      Method method = delegate.getClass().getDeclaredMethod("exportDone", JComponent.class, Transferable.class,
          int.class);
      method.setAccessible(true);
      method.invoke(delegate, source, data, action);
    } catch (Exception e) {
      super.exportDone(source, data, action);
    }
  }

  public int getSourceActions(JComponent c) {
    return delegate.getSourceActions(c);
  }

  public Icon getVisualRepresentation(Transferable t) {
    return delegate.getVisualRepresentation(t);
  }

  public boolean importData(JComponent comp, Transferable t) {
    return delegate.importData(comp, t);
  }

  public boolean importData(TransferHandler.TransferSupport support) {
    return delegate.importData(support);
  }
}

1 つの落とし穴は、createTransferable(JComponent) および exportDone(JComponent, Transferable, int) メソッドが保護されているため、これらのメソッドに委譲するためにリフレクションを実行する必要があることです。このリフレクション委任を行わなかった場合、戦略は機能しませんでした。この委任ドラッグ アンド ドロップを行うと、DragSource を変更したり、新しい Transferable を作成したりすることなく、期待どおりに機能しました。

于 2010-12-22T13:29:28.797 に答える