JavaTM 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 の JavaBeansTM プロパティ処理を通じて提示される。提示されたフレーバは、application/x-java-jvm-local-objectref; class=java.awt.Color である。転送される値は getColor によって決定される
| Color 型の挿入を受け入れる。データは、Beans のプロパティ処理から 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: |
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 はサポートされません。次のコーディングにより、「テキスト」のプロパティ (文字列
) でドラッグ&ドロップをサポートする 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
クラス内部の package private の入れ子クラス内にあります。
以下の package private クラスが、デフォルトのサポートを作成するために 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
の Beans サポートを使用し、カラーに関するプロパティをバインドする。マウスリスナーが、マウスで押したものを TransferHandler
上の exportAsDrag
メソッドにバインドするプレビュー領域に追加される
TransferHandler のアクションは UI で登録することになった
この変更に関連するバグ追跡レポート: 4460011
ドラッグ&ドロップを実装するために、
Action
クラスでバインディングを提供して、データのコピーとペーストをサポートしていました。Action
がTransferHandler
で自動的にインストールされなくなったため、Look & Feel などのコードでこれらのAction
をオーバーライドするには、UI を通してこれらのアクションをインストールする必要があります。TransferHandler
のgetCutAction
、getCopyAction
、およびgetPasteAction
の各メソッドは、public private から public に変更されました。DropTarget を無効にする機能
この変更に関連するバグ追跡レポート: 4485914
ドラッグ&ドロップを実装すると、
JComponent
にTransferHandler
がインストールされている場合、JComponent にDropTarget
が追加されます。手動でDropTarget
を追加しているアプリケーションは、これによって影響を受ける可能性があります。そのため、suppressSwingDropSupport
というシステムプロパティが追加されました。JComponent
のsetTransferHandler(TransferHandler)
メソッドとgetTransferHandler
メソッドを使って、このプロパティを有効にしたり無効にしたりできます。
JTextComponent で選択したテキストをドロップするとテキストが壊れる
この問題に関連するバグレポート: 4513715
テキストを選択し、同じテキストコンポーネントの選択領域の中にドラッグ&ドロップすると、選択したテキストが壊れ、何もペーストされません。リリース 1.4.1 ではこのバグは修正されました。
コンポーネントから出るときキャレットの復元エラーが発生する
この問題に関連するバグレポート: 4513720
組み込みのドロップサポートにより、Swing テキストコンポーネントは、ドラッグ&ドロップのドラッグオーバーに反応して、
Caret
を可視に設定し、そのキャレットを使って潜在的な挿入ポイントを示します。ドラッグがコンポーネントの外に出ると、Caret
の可視性は元の状態に復元されます。ところが、Caret
で使用するvisible
プロパティは、これ 1 つで通常の「可視」という意味と点滅状態との両方を表すため、Caret の可視性は正しく復元されないことがあります。RTFEditorKit の設定された JEditorPane に対するカット、コピー、ドラッグが無効になった
この問題に関連するバグレポート: 4513638
JEditorPane
にRTFEditorKit
を設定するには、明示的にsetEditorKit
を使用する方法や、content-type
にtext/rtf
を指定する方法があります。このようにして設定された RTFEditorKit を使用するとき、カット、コピー、およびドラッグは動作しなくなりました。リリース 1.4 にあったこのバグは、リリース 1.4.1 で修正されました。