Java 2 Platform, Standard Edition, v 1.4 のリリースでは、Swing にアプリケーション間でのデータ転送のサポートが加わりました。ドラッグ&ドロップ操作はデータ転送の要求であり、グラフィカルポインティングデバイスを使用したジェスチャーで指定します。コピーやペーストは、多くの場合、キーボードによってデータ転送が指定されます。データ転送には、次の 2 つの形式があります。
各 Swing コンポーネントの状態はデータモデルの定義とは独立しているため、データ自体の詳細部分を気にすることなく、コンポーネント間でのデータ移動のメカニズムを実装することが簡単でした。データ転送は事実上、あるモデルから別のモデルへの部分転送です。(カット、コピー、ペーストの場合は、モデルとクリップボード間でデータが転送される。)データ転送をサポートするため、次の変更が行われました。
Component | ドラッグのサポート | ドロップのサポート |
---|---|---|
JColorChooser |
はい | はい |
JEditorPane |
はい | はい |
JFileChooser |
はい | いいえ |
JFormattedTextField |
はい | はい |
JLabel |
ここを参照 | ここを参照 |
JList |
はい | いいえ |
JPasswordField |
いいえ | はい |
JTable |
はい | いいえ |
JTextArea |
はい | はい |
JTextField |
はい | はい |
JTextPane |
はい | はい |
JTree |
はい | いいえ |
このドキュメントには次のセクションがあります。
データ転送の基本は、データをコンポーネントへ、またはコンポーネントから転送する処理のサポートです。コンポーネントでこの機能が利用可能な場合は、ドラッグ&ドロップの管理メカニズムが自動的に提供されます。さらに、カット、コピー、ペーストのサポートも自動的に提供されます。この実装でもっとも重要な点は、TransferHandler
新規クラスの実装です。JComponent
プロパティーメソッド、setTransferHandler
および getTransferHandler
で、JComponent
を拡張するすべてのコンポーネントに対するデータ転送メカニズムのエントリポイントが提供されます。
null
以外の TransferHandler
がインストールされているときに、各コンポーネントに対してサポートされる「カット」、「コピー」、「ペースト」、および「ドロップ」の範囲を次の表に示します。このサポートは、Look & Feel コードによって有効になります。最初はドラッグのサポートが無効にされていますが、コンポーネント上で setDragEnabled(true)
を呼び出して有効にすることができます。コンポーネントにこのようなメソッドがない場合は、なんらかのジェスチャーをバインドして、ドラッグを有効にできます。
TransferHandler
のデフォルトの実装をインストールします。デフォルトの Swing サポートがあるコンポーネントでは、transferHandler
プロパティーの値が null
であるか、または UIResource
インタフェースによってマークされている場合は、TransferHandler
が ComponentUI
によってインストールされます。ComponentUI
にインストールされたデフォルトの TransferHandler
実装は、開発者がデフォルトの TransferHandler
をオーバーライドできるようにして、UIResource
インタフェースによってマークされます。次の表に提供されるサポートを示します。
Component | エクスポート (ドラッグ、カット、コピー) | インポート (ドロップ、ペースト) |
---|---|---|
JColorChooser |
選択したカラーが、TransferHandler の JavaBeans プロパティー処理を通じて提示される。提示されたフレーバは、application/x-java-jvm-local-objectref; class=java.awt.Color である。転送される値は getColor によって決定される。 |
Color 型の挿入を受け入れる。データは、Bean のプロパティー処理から setColor を使用してインポートされる。class=java.awt.Color または java.awt.Color のサブクラスを持つすべてのフレーバが受け入れられる。 |
JEditorPane |
1.4: JEditorPane の content-type が text/plain である場合、選択したテキストは、EditorKit の write メソッドを通じて text/plain として表示される。content-type が OTHER である場合は、getSelectedText メソッドを使って text/plain として、および、EditorKit の write メソッドを使って OTHER としてエクスポートされる。
1.4.1: 選択したテキストで |
1.4: text/plain 型の挿入および getContentType から返された現在の型をすべて受け入れる。現在の型 (text/plain も含む) に一致する型が見つかると、EditorKit の read メソッドを使ってインポートされる。それ以外の場合は、コンポーネントの replaceSelection メソッドを通して text/plain がインポートされる。ペースト: 選択している内容があれば、それが置換される。ドロップ: キャレットの位置にデータが挿入される。
1.4.1: |
JFileChooser |
ネイティブのファイルチューザと同じ方法で選択範囲が提示される。 | インポートは受け入れられない。マウスがリスト上に移動すると、カーソルの下のファイルやディレクトリが強調表示されて、潜在的なドロップポイントが示される。「デフォルトのドロップのサポート」を参照。 |
JFormattedTextField |
選択したテキストが text/plain として提示される。 |
text/plain 型の挿入を受け入れる。ペースト: 選択している内容があれば、それが置換される。何も選択していない場合は、キャレットの位置にデータが挿入される。ドロップ: キャレットの位置にデータが挿入される。ペーストとドロップは、キーボードからの入力時と同じコードパスを採用するので、コードの検証が保存される。 |
JList |
1 項目が選択された場合は、text/plain として提示される。複数の項目が選択された場合は、text/html として提示される。text/html の形式は、<UL> タグのあとに、それぞれが <LI> タグで始まる選択したリスト項目が続く。 |
インポートは受け入れられない。マウスがリスト上に移動すると、カーソルの下のリスト項目が強調表示されて、潜在的なドロップポイントが示される。「デフォルトのドロップのサポート」を参照。 |
JPasswordField |
セキュリティー上の理由から、カット、コピー、およびドラッグはサポートされない。 | text/plain 型の挿入を受け入れる。ペースト: 選択している内容があれば、それが置換される。何も選択していない場合は、キャレットの位置にデータが挿入される。ドロップ: キャレットの位置にデータが挿入される。 |
JTable |
1 項目が選択された場合は、text/plain として提示される。複数の項目が選択された場合は、text/html として提示される。text/html の形式は、<TABLE> タグのあとに各行には <TR> タグ、各セルには <TD> タグが続く。 |
インポートは受け入れられない。マウスが表の上に移動すると、カーソルの下のセルが強調表示されて、潜在的なドロップポイントが示される。「デフォルトのドロップのサポート」を参照。 |
JTextArea |
選択したテキストが text/plain として提示される。 |
text/plain 型の挿入を受け入れる。ペースト: 選択している内容があれば、それが置換される。何も選択していない場合は、キャレットの位置にデータが挿入される。ドロップ: キャレットの位置にデータが挿入される。 |
JTextField |
選択したテキストが text/plain として提示される。 |
text/plain 型の挿入を受け入れる。ペースト: 選択している内容があれば、それが置換される。何も選択していない場合は、キャレットの位置にデータが挿入される。ドロップ: キャレットの位置にデータが挿入される。 |
JTextPane |
JEditorPane と同じ。 |
JEditorPane と同じ。 |
JTree |
1 項目が選択された場合は、text/plain として提示される。複数の項目が選択された場合は、text/html として提示される。text/html の形式は、JList に使用される形式と似た、ネストされたリストである。 |
インポートは受け入れられない。マウスが表の上に移動すると、カーソルの下のツリーノードが強調表示されて、潜在的なドロップポイントが示される。「デフォルトのドロップのサポート」を参照。 |
JLabel
へのサポート追加の例特に指定しないかぎり、JLabel
コンポーネントで DnD はサポートされません。次のコーディングにより、「テキスト」のプロパティー (String
) でドラッグ&ドロップをサポートする JLabel
が作成されます。
JLabel componentType = new JLabel(); componentType.setTransferHandler(new TransferHandler("text")); MouseListener ml = new MouseAdapter() { public void mousePressed(MouseEvent e) { JComponent c = (JComponent)e.getSource(); TransferHandler th = c.getTransferHandler(); th.exportAsDrag(c, e, TransferHandler.COPY); } }; componentType.addMouseListener(ml);
JTextField
と JLabel
を使用してドラッグ&ドロップを実装した小さな例も含めてあります。テキストフィールドに値を入力し、テキストを強調表示したあとに、テキストフィールドの上にマウスボタンを置いて下に押さえ、ピクセルをドラッグすることができます。アイコンはカーソルの下に表示されます。JLabel
の上のアイコンを解放して、テキストが「Drop Here」テキストに置き換わったことを確認してください。ドロップすると同時に、ソースのテキストフィールドからテキストが削除されます。ドラッグ&ドロップのデフォルトの動作は MOVE
です。この動作を COPY
に変更するには、テキストを選択するときに Ctrl
キーを押します。Windows では、アイコン内にプラス記号が表示されます。テキストがターゲット上に貼り付けられても、ソース内のテキストはそのまま残ります。同様に、JLabel
からテキストフィールドへドラッグすることもできます。JLabel
にはコピーおよびペーストのバインドがなく、この機能をサポートするために必要なフォーカスを取得することができないことに留意してください。
JLabelDragNDrop.java のここの例を参照してください。
テキストフィールドなどのコンポーネントは、選択範囲をサポートします。この種のコンポーネントの場合、ドラッグ操作は通常、既存の選択範囲をマウスでドラッグすることで開始されます。この型のコンポーネントのコントローラがこの状態を認識することができ、ドラッグを開始します。選択範囲のないコンポーネントでは、Swing がドラッグを自動的に開始できませんが、JLabel
の例にあるようにドラッグが試行されると、ドラッグのメカニズムを処理することはできます。
このレベルのドラッグサポートで、Swing の開発者は、実行したい転送を表現する TransferHandler
の実装、および Swing コンポーネントでのプロパティーの設定に集中することができます。これで、アプリケーション内でドラッグをサポートしようとする Swing 開発者の負担が軽減されます。
現在は、ドラッグのさまざまな視覚上の表現方法 (API 内の Icon
への参照) を調査中です。今後の進展に注意していてください。
サポートのもっとも単純なレベルは、開発者がデフォルトのサポートが有効にされるのを望んでいることを示すフラグの設定です。ドラッグのデフォルトのサポートを提示するコンポーネントについては、「DnD をサポートするコンポーネント」の表のエクスポートの欄に説明がありますが、要約すると、setDragEnabled
および getDragEnabled
を直接実装する以下のクラスがあります。JColorChooser
、JFileChooser
、JList
、JTable
、JTree
、および JTextComponent
。ドラッグのジェスチャーは、選択範囲の上でマウスの左ボタンを押して、いくつかのピクセルをドラッグすることと定義されます。そのため、dragEnabled
プロパティーを true
に設定すると、マウスの動作に関して微妙な効果があります。
ドラッグがコンポーネント上で有効にされると、対応する ComponentUI
サブクラス内の Swing コントローラがドラッグのジェスチャーの検索を開始し、transferHandler
プロパティーが null
であるか、UIResource
インタフェースによってマークされていると、デフォルトの実装がインストールされます。Swing によって提供された実装が UIResource
インタフェースでマークされるので、開発者は、デフォルトの TransferHandler
プロパティーをカスタムの実装で置き換えて、新しい TransferHandler
を挿入することができます。ドラッグのジェスチャーが認識されると、ドラッグメカニズムを開始する TransferHandler
上で exportAsDrag
メソッドが呼び出されます。実際の転送は java.awt.dnd
メカニズムによって処理され、開発者にとってこれ以上の労力は必要ありません。
Swing に提供されるドラッグのサポートは、TransferHandler.exportAsDrag
メソッドによって起動します。これによって、次のように簡単にドラッグのサポートを追加することができます。
setTransferHandler
メソッドを呼び出して (ドラッグの対象がある場合)、TransferHandler
の実装をインストールする。exportAsDrag
メソッドを呼び出す。これを行うシナリオには、次のようなものがあります。
MouseListener
を追加して、次にコンポーネント上で getTransferHandler
を呼び出し、ドラッグのジェスチャーが検出されると exportAsDrag
を呼び出す。JLabel の例を参照。processMouseEvent
メソッドを再実装し、ドラッグのジェスチャーが検出されたときに ComponentUI 変数上で exportAsDrag
メソッドを呼び出す。そうでないときは、スーパークラスの動作を実行する。exportAsDrag
を呼び出すようにする。exportAsDrag
メソッドが TransferHandler
上で呼び出されると、Swing 提供の機能によってドラッグが処理されます。このメソッドが呼び出される場合は、有効なドラッグジェスチャーが認識されたとみなされます。このメソッドでは、次の手順が実行されます。
DragSource
および DragListener
の Swing 実装を使用して、データ転送オブジェクトとして createTransferable
から返された Transferable
実装を使用するドラッグを開始する。exportDone
メソッドが TransferHandler
上で呼び出される。MOVE
などのいくつかの操作の場合は、ソースからデータを削除することが必要な場合もある。たとえば、テキストベースのコンポーネントでのデフォルトの動作は、標準的なドラッグに MOVE
の動作が実装される (ドロップに続いて、選択したテキストはソースコンポーネントから削除される)。テキストをドラッグ用に選択するときに Ctrl キーを押し下げると、この動作をオーバーライドできる。Windows では、小さなプラス記号の付いたドラッグアイコンによって、コピー動作が視覚的に示される。ドロップを取り扱うプライマリサポートは、ペースト操作、つまり TransferHandler
の importData
メソッドでの場合と同じです。コンポーネントへのデータ挿入のセマンティクスは、通常、ツールキットのレベルに比べてアプリケーションレベルでの意味のほうが多くなっています。アプリケーションのユーザーは、Swing ツールキットにとってまったく未知のコンポーネント上ですべての種類の Transferable
実装をドロップできます。デフォルトの TransferHandler
が不十分な場合は、意味の多いインポートのセマンティクスで TransferHandler
を提供するのが Swing 開発者の責任です。
ただし、ドロップの操作はペーストと多少違います。
ドロップのサポートのアプリケーションへの追加で Swing 開発者を支援するために、Swing によって、Swing コンポーネント上で TransferHandler
プロパティーを使用する DropTarget
の実装が提供されます。null
以外の値の TransferHandler
プロパティーがあるコンポーネントでは、dropTarget
プロパティーの値が null
であるか、または UIResource
インタフェースの存在によってマークされていれば、ドロップターゲットが ComponentUI
によってインストールされます。ComponentUI
にインストールされたデフォルトの DropTarget
実装は、開発者がデフォルトの DropTarget
をオーバーライドできるようにして、UIResource
インタフェースによってマークされます。
ドロップの完全な実装をデフォルトで提供するコンポーネントは、「DnD をサポートするコンポーネント」表のインポート欄に示されています。ドロップを一部だけサポートしているコンポーネントは 4 つあります。JFileChooser
、JList
、JTable
、および JTree
には、潜在的な挿入ポイントを示す DropTarget
がデフォルトでインストールされています。ただし、データのインポートを完全にサポートするには、開発者がカスタムの TransferHandler
を作成してインストールする必要があります。
DropTarget がうまく動作する実装では、ドロップを実行するために JComponent
で transferHandler
プロパティーが使用されています。transferHandler
プロパティーが設定され、dropTarget
プロパティーが null
の場合に、Swing の開発者は、ドロップを TransferHandler
にリンクさせる単純な DropTarget
実装を自動的に取得します。
カット、コピー、およびペースト操作は、通常はキーボードから起動されるため、マウスを使用せずにより有用なデータ転送を実行します。これらの操作は、ドラッグ&ドロップのサポートと同じ TransferHandler
サービスを使用できます。これによってデータ転送の使い易さが向上し、Swing で実際のクリップボード間とのデータ転送ができない場合であっても、このような操作のためのキーボードバインドを Swing で提供できるようになります。クリップボード用のキーボードバインドは、インストールされている現在の Look & Feel 機能に依存しています。
ドラッグ&ドロップと同様に、クリップボードによる転送は、選択範囲をサポートするコンポーネントにとってもっとも役に立ちます。「DnD をサポートするコンポーネント」表のエクスポート欄に示したコンポーネントのリストには、コンポーネントの入力マップ内のキーボードバインドに関する LAF に依存するセットに加えて、コンポーネントのアクションマップ内にカット、コピー、およびペーストのアクションがあります。Swing でこれらのバインドが提供されるので、開発者は、現在の Look & Feel の追跡とバインドの変更をしないで済みます。
カット、コピー、およびペーストがうまく動作する実装では、転送を実行するために JComponent
で transferHandler
プロパティーが使用されています。transferHandler
プロパティーが JComponent
上に設定されていると、現在インストールされているアクションが何もなければ、Clipboard
と TransferHandler
間の転送にリンクする単純な Action
実装が、コンポーネントのアクションマップ内の cut
、copy
、および paste
キーの下にインストールされます。
注:次の説明は、非公開の実装の詳細についてと、変更の主題についてです。この情報は、ソースコードにアクセスして、特に興味をお持ちの方々に対してだけ提供します。
TransferHandler
が JComponent
にインストールされている場合、Look & Feel は、次の TransferHandler
メソッドを使ったカット、コピー、およびペースト処理を有効にします。
TransferHandler.exportAsDrag
にバインドした場合は、ドラッグサポートも入手できます。この処理は、TransferHandler
クラス内部のパッケージ専用のネストされたクラス内にあります。
次のパッケージ専用のクラスが、デフォルトのサポートを作成するために javax.swing.plaf.basic
パッケージに追加されました。
BasicTransferable
Transferable
実装の基本。BasicDropTargetListener
BasicDragGestureRecognizer
DnD をサポートする各 ComponentUI
クラスには、追加のネストされたクラスがあります。
BasicTreeUI
:
TreeTransferHandler
TreeTransferable
TreeDragGestureRecognizer
JTree.setDragEnabled
によって有効にされる、ツリードラッグジェスチャーの認識。TreeDropHandler
BasicListUI
、BasicTableUI
、および BasicTextUI
はすべて、BasicTreeUI
と似たパターンを持っています。
BasicFileChooserUI
FileTransferHandler
があり、ファイル転送で使用されるフレーバで ListTransferable
を拡張する FileTransferable
を作成する。BasicColorChooserUI
TransferHandler
の Bean サポートを使用し、カラーに関するプロパティーをバインドする。マウスリスナーが、マウスで押したものを TransferHandler
上の exportAsDrag
メソッドにバインドするプレビュー領域に追加される。この変更に関連するバグ追跡レポート: 4460011.
ドラッグ&ドロップを実装するために、Action
クラスでバインディングを提供して、データのコピーとペーストをサポートしていました。Action
が TransferHandler
で自動的にインストールされなくなったため、Look & Feel などのコードでこれらの Action
をオーバーライドするには、UI を通してこれらのアクションをインストールする必要があります。TransferHandler
の getCutAction
、 getCopyAction
、および getPasteAction
の各メソッドは、package-private から public に変更されました。
この変更に関連するバグ追跡レポート: 4485914.
ドラッグ&ドロップを実装すると、JComponent
に TransferHandler
がインストールされている場合、JComponent に DropTarget
が追加されます。手動で DropTarget
を追加しているアプリケーションは、これによって影響を受ける可能性があります。そのため、suppressSwingDropSupport
というシステムプロパティーが追加されました。JComponent
の setTransferHandler(TransferHandler)
メソッドと getTransferHandler
メソッドを使って、このプロパティーを有効にしたり無効にしたりできます。
この変更に対応するバグ追跡レポートは、4513715 です。
テキストを選択し、同じテキストコンポーネントの選択領域の中にドラッグ&ドロップすると、選択したテキストが壊れ、何もペーストされません。リリース 1.4.1 ではこのバグは修正されました。
この変更に対応するバグ追跡レポートは、4513720 です。
組み込みのドロップサポートにより、Swing テキストコンポーネントは、ドラッグ&ドロップのドラッグオーバーに反応して、Caret
を可視に設定し、そのキャレットを使って潜在的な挿入ポイントを示します。ドラッグがコンポーネントの外に出ると、Caret
の可視性は元の状態に復元されます。ところが、Caret
で使用する visible
プロパティーは、これ 1 つで通常の「可視」という意味と点滅状態との両方を表すため、Caret の可視性は正しく復元されないことがあります。
この変更に対応するバグ追跡レポートは、4513638 です。
setEditorKit
を使用たり content-type
に text/rtf
を設定したりして JEditorPane
に明示的に設定された RTFEditorKit
を使用するときに、カット、コピー、およびドラッグは動作しなくなりました。このバグはリリース 1.4 で報告されましたが、1.4.1 では修正されました。