2016年9月14日水曜日

Mutter Launcher .NET を Vector でも登録&公開

先の記事で Mutter Launcher を C# .NET に移植しているというのを書きましたが、
実装が一通りまとまったので区切りの良い単位で Vector でも登録&公開しました。




GitHub での公開+更新はそのまま引き続き継続中です。
気軽に fork or pull request してみて下さい。

ちなみに、使い方の説明のドキュメントが追いついてないです…

2016年8月28日日曜日

C# / .NET 版 Mutter Launcher を Github で公開中

ここ最近は先の Java/JavaFX 版をベースに Mutter Launcher を C# / .NET に移植していました。
ちなみにもともとの Windows版の Mutter Launcher はこんなもの。

その C# / .NET 版の Mutter Launcher は GitHub で公開しています。
まだ完全な実装ではないですが(特に設定画面部分がまだ未実装)
実処理部分は大部分を実装をしているので、
もし興味ある方は覗いてみて下さい。

2016年7月22日金曜日

Java/JavaFX 版 Mutter Launcher を Github で公開中

ここ最近の Java/JavaFX の投稿は、
以前に Windows 向けに C/C++ と Win32API で作ったアプリケーション Mutter Launcher を Java/JavaFX に移植するという作業の中から出てきたノウハウでした。

ちなみにもともとの Windows版の Mutter Launcher はこんなもの。

その Java/JavaFX 版の Mutter Launcher は Github で公開しています。
完全移植ではなく、まだまだ作成途中ではありますが、
大分、実装がまとまってきたので、
この blog でも記事として投稿してみました。

ここ最近書いてきたような Java/JavaFX のサンプルとして、
あるいは単純に Java アプリケーションとして
もし興味ある方は覗いてみて下さい。

2016年7月21日木曜日

JavaFX の ListView でアイコンを表示/Cell のカスタマイズ


JavaFX の ListView で String 以外を構成要素にするの拡張的な内容になりますが、
ListView の表示が toString() では収まらない、文字列以外も表示したい、という際には、ListView のリストを構成する Cell をカスタマイズすることになります。
その Cell をカスタマイズした一例として…

やりたかったことは ListView にファイル名と対応するアイコンの表示。
ポイントは ListView の Cell のカスタマイズと Icon の描画方法。

といっても、ほとんど

JavaFX file listview with icon and file name - Stack Overflow
http://stackoverflow.com/questions/28034432/javafx-file-listview-with-icon-and-file-name

のマネです。

Item というクラスがファイル名などを持っていて、ListView<Item> として ListView の要素のクラスとなっているとします。
ListView#setCellFactory() で Cell をカスタマイズする ListCell を拡張したクラス(この場合 ItemFormatCellを返すようにします。
        listView.setCellFactory(new Callback<ListView<Item>, ListCell<Item>>() {
             @Override
             public ListCell<Item> call(ListView<Item> list) {
                 return new ItemFormatCell();
             }
         });

ItemFormatCell クラスで、実際に1つのセルの表示内容をカスタマイズすることになりますが、ここで updateItem() をオーバーライドして実装するのが定番のようです。
次の例では、

  • 空行には何も表示しない(setText(), setGraphic() で null 指定)
  • 対応する Item がある場合には、アイコン(setGraphic())+ファイル名(setText())を表示する

ということをやっています。
    final class ItemFormatCell extends ListCell<Item> {
        public ItemFormatCell() {    }
   
        @Override protected void updateItem(Item item, boolean empty) {
            final boolean bUseJLabel = false;
     
            super.updateItem(item, empty);
     
            if(empty || item == null){
                 setText(null);
                 setGraphic(null);
                 return;
            }
     
            // getItemName() はファイル名を返すメソッドとして実装
            setText(item.getItemName());
            setContentDisplay(ContentDisplay.LEFT); // Graphic は Text の左に表示
            // getIcon() は対応する Icon を返すメソッドとして実装
            // Windows では FileSystemView.getFileSystemView().getSystemIcon() を利用
            Icon icon = item.getIcon();
            BufferedImage bufferedImage = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
            icon.paintIcon(null, bufferedImage.getGraphics(), 0, 0);
            // 最終的に Icon を ImageView の形で Cell に表示
            setGraphic(new ImageView(SwingFXUtils.toFXImage(bufferedImage, null)));    
        }
    }

ListView の Cell のカスタマイズについては、Cell の javadoc も参照してみて下さい。


2016年7月20日水曜日

JavaFX の ListView で String 以外を構成要素にする

ListView では javadoc にもあるように、ListView<String> という形で String 型のものを要素として第一に想定していますが、
もちろん、それ以外の独自のクラスを指定することも可能です。
その際に一番簡単な方法は次の通り。

例として独自の Item クラスというのを ListView で扱いたい場合、

・ObservableList<Item> を ListView<Item> に setItems() で設定する

・リストに表示される文字列は Item クラスの toString に実装

実装イメージを書くとこんな感じになります。
// ListView 側
    @FXML
    private ListView<Item> itemListView;

(略)
        ObservableList<Item> items = FXCollections.observableArrayList();

        // items に項目を追加する処理
        itemListView.setItems(items);

// Item 側
public class Item{
    private String itemName;

    @Override
    public String toString() {
        return itemName;
    }

2016年7月16日土曜日

JavaFX の fxml 使用時の Application と Controller の相互参照方法

fxml を使って JavaFX のアプリを作っていると、
Application#start() で渡されるメインとなる Stage(primaryStage)と Controller とのやり取りが、どうしても欲しくなってきます。
その際に、正規のやりとりの口はないらしく、

などを参照すると、自力で相互参照を作らないといけないようです。
  • Application#start() → Controller の参照
    FXMLLoader#getController() で load した fxml に関連した Controller のインスタンスが取得できる
  • Controller → primaryStage の参照
    Controller 側で stage を設定できる public メソッドを用意しておいて、上で取得した Controller に対して primaryStage を設定する
という方法になります。
孫引きになりますが、サンプルソースはこんな感じになります。
// MyGui.fxml のロードと、関連した Controller インスタンスの取得
FXMLLoader loader = new FXMLLoader(getClass().getResource("MyGui.fxml"));
MyController controller = (MyController)loader.getController();

// primaryStage を controller 側へ設定
controller.setStageAndSetupListeners(primaryStage); 



2016年7月12日火曜日

JavaFX の ComboBox で Return/Enter キーの入力をひろう

JavaFX の ComboBox でキーイベント等をひろうの続きっぽい内容ですが、
ComboBox で Return/Enter キーの入力をひろうのに苦労したので、
そこのメモ。

検索すると

  1. OnAction のイベントハンドラーで処理できる
  2. ComboBox の getEditor() で取得できる内部の TextField のキーイベントの getCode() と KeyCode.ENTER を比較
なんて方法が出てくるがどちらもうまく行かなかった。

1. の方法は、それで処理されるときもあれば、処理されないときもあるという動作が不確定。

2. の方法は、確かに OnKeyTyped の際にはイベント通知が来るが(ちなみに OnKeyPressed はダメだった)、ログ出ししてみるとなぜか getCode() した結果が UNDEFINED 値(KeyCode.ENTER との比較が true にならない)。

ということで、最終的にイベントのログ出し結果等から私が書いたコードは次のようになった。
    comboBox.getEditor().setOnKeyTyped((event) -> {
        System.out.println("ComboBox onKeyTyped:" + event);
        if(event.getCode() == KeyCode.ENTER || event.getCharacter().equals("\n") || event.getCharacter().equals("\r")){
            executeSelectedItem();
        }
    });
今のところ、ログやデバックでの動作を見る限り getCharacter() の "\r" との比較で上手く動作しています。
それ以外の比較は、環境や動作が変わった場合の保険。
(event.getCode() 値が KeyCode.ENTER になるのが正しい動作だと思うので)

もっとエレガントで正しい書き方があれば知りたい…