JRuby+swingでファイルのドラッグ・アンド・ドロップを試す
Windowsとかからファイルをドラッグ&ドロップできるようにします。
swingの"TransferHandler"を使うと簡単に実現できるようです。
メモします。
# coding: cp932 require 'java' JFrame = javax.swing.JFrame JLabel = javax.swing.JLabel TransferHandler = javax.swing.TransferHandler DataFlavor = java.awt.datatransfer.DataFlavor class FileDropHandler < TransferHandler def initialize(model) super() @model = model end #ファイル(リスト)のドロップ許可を与える def canImport(support) unless support.is_drop return false end support.isDataFlavorSupported(DataFlavor.javaFileListFlavor) end #ドロップされたアイテムに対して処理を与える def importData(support) begin if support.isDataFlavorSupported(DataFlavor.javaFileListFlavor) filelist = support.transferable.get_transfer_data(DataFlavor.javaFileListFlavor) # puts filelist.to_a.each {|file| puts file} @model.text = filelist.to_s #参照先(ラベル)にファイル一覧を渡す end rescue => e puts e.message false end true end end frame = JFrame.new "File Drag & Drop" frame.default_close_operation = JFrame::EXIT_ON_CLOSE label = JLabel.new label.text = "ここにファイルをドラッグ&ドロップ" frame.content_pane.add(label) label.transfer_handler = FileDropHandler.new(label) frame.pack frame.set_bounds(10,10,400,60) frame.visible = true
canImportでDnDの許可を与えます。ここをtrueを返すようにするとドラッグしたときマウスのアイコンが禁止マークではなくなります。
importDataはドロップしたデータを受け取ります。受け取ったデータ(ファイル一覧)をlabel.textに表示させています。
immportData内でドラッグしたことを判断する条件式が足りていないかもしれませんが、今回は細かいことは省略します。
get_transfer_data(DataFlavor.javaFileListFlavor)で取得したfilelistは、"java.util.ArrayList"です。ちょっとどう扱えばよいか考えてしまいます。でも難しく考えずにRubyの配列のようにeachブロックを使って処理すればよいです。
あと、filelist.to_aを使うとjava.util.ArrayListからRubyのArrayクラスに変換できます。
クラスの継承で、initialize内"super()"のカッコ"()"は必要です。
jruby-1.7.0.preview1でこのスクリプトを実行すると
warning: instance vars on non-persistent Java type FileTransferHandler (http://wiki.jruby.org/Persistence)
とワーニングが表示されますが、とりあえず無視します。おそらくpreview2とかで解決されているはずなので。
感想
ドラッグ&ドロップを調査はじめのころAWTのdndを見つけてテストしてました。ですが、僕には理解できませんでした。それでもう少し調べたらswingにもDnDをサポートしているという記述を発見しもっと簡単に実装できることを知りました。
確かにTransferHandlerならcanImportとimportDataだけわかれば実装できるので簡単だと思いました。
swingアプリを作るとき苦労するのはレイアウトだと思います。レイアウトマネージャもよくわからないのがたくさんあるのでどれを使ったらよいかわかりません。ちょっとしたアプリなら今回みたいなドラッグ&ドロップできるシンプルなUIをめざすべきかなと思っていますw
もう少し、UIを手設計で簡単になると良いのですが。。。