Java 2 Platform, Standard Edition, v 1.4のリリースでは、Swingにアプリケーション間でのデータ転送のサポートが加わりました。ドラッグ・アンド・ドロップ操作はデータ転送の要求であり、グラフィカル・ポインティング・デバイスを使用したジェスチャで指定します。コピーやペーストは、多くの場合、キーボードによってデータ転送が指定されます。データ転送には、次の2つの形式があります。
各Swingコンポーネントの状態はデータ・モデルの定義とは独立しているため、データ自体の詳細部分を気にすることなく、コンポーネント間でのデータ移動のメカニズムを実装することが簡単でした。データ転送は事実上、あるモデルから別のモデルへの部分転送です。(カット、コピー、ペーストの場合は、モデルとクリップボード間でデータが転送される。)データ転送をサポートするため、次の変更が行われました。
コンポーネント | ドラッグのサポート | ドロップのサポート |
---|---|---|
JColorChooser |
はい | はい |
JEditorPane |
はい | はい |
JFileChooser |
はい | いいえ |
JFormattedTextField |
はい | はい |
JLabel |
ここを参照 | ここを参照 |
JList |
はい | いいえ |
JPasswordField |
いいえ | はい |
JTable |
はい | いいえ |
JTextArea |
はい | はい |
JTextField |
はい | はい |
JTextPane |
はい | はい |
JTree |
はい | いいえ |
このドキュメントには次のセクションがあります。
データ転送の基本は、データをコンポーネントへ、またはコンポーネントから転送する処理のサポートです。コンポーネントでこの機能が利用可能な場合は、ドラッグ・アンド・ドロップの管理メカニズムが自動的に提供されます。さらに、カット、コピー、ペーストのサポートも自動的に提供されます。この実装でもっとも重要な点は、TransferHandler
新規クラスの実装です。JComponent
プロパティ・メソッド、setTransferHandler
および getTransferHandler
で、JComponent
を拡張するすべてのコンポーネントに対するデータ転送メカニズムのエントリ・ポイントが提供されます。
null
以外のTransferHandler
がインストールされているときに、各コンポーネントに対してサポートされる「カット」、「コピー」、「ペースト」、および「ドロップ」の範囲を次の表に示します。このサポートは、ルック・アンド・フィールコードによって有効になります。最初はドラッグのサポートが無効にされていますが、コンポーネント上でsetDragEnabled(true)
を呼び出して有効にすることができます。コンポーネントにこのようなメソッドがない場合は、なんらかのジェスチャをバインドして、ドラッグを有効にできます。
TransferHandler
のデフォルトの実装をインストールします。デフォルトのSwingサポートがあるコンポーネントでは、transferHandler
プロパティの値がnull
であるか、またはUIResource
インタフェースによってマークされている場合は、TransferHandler
がComponentUI
によってインストールされます。ComponentUI
にインストールされたデフォルトのTransferHandler
実装は、開発者がデフォルトのTransferHandler
をオーバーライドできるようにして、UIResource
インタフェースによってマークされます。次の表に提供されるサポートを示します。
コンポーネント | エクスポート(ドラッグ、カット、コピー) | インポート(ドロップ、ペースト) |
---|---|---|
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で提供できるようになります。クリップボード用のキーボード・バインドは、インストールされている現在のルック・アンド・フィール機能に依存しています。
ドラッグ・アンド・ドロップと同様に、クリップボードによる転送は、選択範囲をサポートするコンポーネントにとってもっとも役に立ちます。「DnDをサポートするコンポーネント」表のエクスポート欄に示したコンポーネントのリストには、コンポーネントの入力マップ内のキーボード・バインドに関するLAFに依存するセットに加えて、コンポーネントのアクション・マップ内にカット、コピー、およびペーストのアクションがあります。Swingでこれらのバインドが提供されるので、開発者は、現在のルック・アンド・フィールの追跡とバインドの変更をしないで済みます。
カット、コピー、およびペーストがうまく動作する実装では、転送を実行するためにJComponent
でtransferHandler
プロパティが使用されています。transferHandler
プロパティがJComponent
上に設定されていると、現在インストールされているアクションが何もなければ、Clipboard
とTransferHandler
間の転送にリンクする単純なAction
実装が、コンポーネントのアクション・マップ内のcut
、copy
、およびpaste
キーの下にインストールされます。
注: 次の説明は、非公開の実装の詳細についてと、変更の主題についてです。この情報は、ソース・コードにアクセスして、特に興味をお持ちの方々に対してだけ提供します。
TransferHandler
がJComponent
にインストールされている場合、ルック・アンド・フィールは、次の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
で自動的にインストールされなくなったため、ルック・アンド・フィールなどのコードでこれらの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では修正されました。