JavaFX の SplitPane を試してみた。

JavaFX の SplitPane の存在は知っていたが使う機会が無かったので使い方を知らないまま今日に至っています。

とりあえず簡単な使い方だけでも知っておこうとググってみたのですが日本語での情報を見つけることができませんでした。(>_<。)

しかたないので API ドキュメントをサラッと 読んで 眺めてみることにしました。

Class SplitPane

http://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/SplitPane.html#getDividerPositions–

縦、横の指定や分割位置などが設定できるようでメソッド数も少なくシンプルなものです。

ただ、私の英語力及び Java 力では理解できないものがあり目から汗が出ています。

Example に sp.setDividerPositions(0.3f, 0.6f, 0.9f); とあるんだけど

最後の引数の 0.9f は無くてもいいんじゃないの?

最後のスペースは自動計算されるはずでは?

なぜなんだろう?

何か意味があるはずなんだろうけど・・・

と言うことでサクッとプログラムを組んで動作確認してみました。

上記のように ? の状態なのでこれであっているか自信はありません。

ラベルをみっつ均等に表示させ、左のラベルは全体の33パーセントより小さくさせない、右のラベルは全体の33パーセントより大きくさせないという制限も付加してみました。

package jp.yucchi.trysplitpane;

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.SplitPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

/**
 *
 * @author Yucchi
 */
public class TrySplitPane extends Application {

    @Override
    public void start(Stage primaryStage) {

        Group root = new Group();

        SplitPane sp = new SplitPane();
        final StackPane sp1 = new StackPane();
        sp1.getChildren().add(new Label("堀北真希"));
        final StackPane sp2 = new StackPane();
        sp2.getChildren().add(new Label("新垣結衣"));
        final StackPane sp3 = new StackPane();
        sp3.getChildren().add(new Label("綾瀬はるか"));
        sp.getItems().addAll(sp1, sp2, sp3);

        // 均等に分割
        sp.setDividerPositions(0.333f, 0.666f);

        // 真希ちゃんラベルを33パーセントより小さくさせない。
        sp1.minWidthProperty().bind(sp.widthProperty().multiply(0.333));
        // はるかちゃんラベルを33パーセントより大きくさせない。
        sp3.maxWidthProperty().bind(sp.widthProperty().multiply(0.333));

        root.getChildren().add(sp);

        Scene scene = new Scene(root, 300, 30);

        sp.prefWidthProperty().bind(scene.widthProperty());
        sp.prefHeightProperty().bind(scene.heightProperty());

        primaryStage.setTitle("Hello SplitPane");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

}


このプログラムの実行結果は下図のようになります。

初期状態

1

左の Divider を右へドラッグして左のラベルを大ききします。

2

左の Divider を左へドラッグして左のラベルを小さくしようとしますが制限がかかっていて小さくなりません。

3

右の Divider を右へドラッグして中央のラベルを大きくします。

4

右の Divider 左へドラッグして右のラベルを大きくしようとしますが制限がかかっておおきくなりません。

5

これって以外と便利に使えるかもしれないですね。

なんで日本語の情報がないんだろう?

シンプルすぎてスルーされているんだろうか?

最後に、ラベルのテキストは私個人の好みであり所属する会社の公式な好みではありません。(ヲヒ

Hatena タグ:

バブルソート (Bubble Sort)

今日も簡単なアルゴリズムのエントリーです。

私が初めて覚えたソートアルゴリズムです。

当時はこれを考えた人はもの凄い頭のいい人だと感動しました。

バブルソート (Bubble Sort) は読んで字のごとく泡のソートです。(^_^;)

つまりソートの過程がデータが下から上へ移動する様子が、泡が浮かんでいくように見えることから名付けられたとされています。

最悪計算時間が O(n2) と遅いのですがシンプルで理解しやすい優しいアルゴリズムです。

そして安定であることが特徴の一つでもあります。

実際どんなことをしているかというと隣り合う要素の大きさを比較して並べ替えていくという単純なものです。

これを要素数 –1 回繰り返すことでソートを行なうことによって完了します。

バブルソートのアルゴリズムを解説したサイトは数多く存在します。

たいていの場合は「要素数-1回繰り返すことでソートを行う」を素直にコードにして紹介されています。

これはバブルソートの解説には解りやすくて良いのですが無駄が発生するので良くありません。

なので今回、私は涙ぐましい改良を施されたバブルソートを組みました。

ソートの部分的完了を検出し、比較範囲の限定を行っています。

ついでに配列が並び変わっていく様子を表示させてみました。(比較、交換作業は除く)

package jp.yucchi.bubblesort;

import java.security.SecureRandom;
import java.util.Arrays;

/**
 *
 * @author Yucchi
 */
public class BubbleSort {
1
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {

        int[] randomNumber = new SecureRandom().ints(10L, 1, 11).toArray();

        System.out.println("befor:" + Arrays.toString(randomNumber) + System.getProperty("line.separator"));

        bubbleSort(randomNumber);

        System.out.println(System.getProperty("line.separator") + "after:" + Arrays.toString(randomNumber));

    }

    private static void bubbleSort(int[] randomNumber) {

        int incompleteIndex = 0; // ソートがまだ完了していない位置

        while (incompleteIndex < randomNumber.length - 1) {

            int lastChangeIndex = randomNumber.length - 1; // 最後に要素を交換した位置

            for (int j = randomNumber.length - 1; j > incompleteIndex; j--) {

                if (randomNumber[j - 1] > randomNumber[j]) {
                    // 要素の交換 本当は一時変数を用意して入れ替えるのが良い
                    randomNumber[j - 1] ^= randomNumber[j];
                    randomNumber[j] ^= randomNumber[j - 1];
                    randomNumber[j - 1] ^= randomNumber[j];

                    lastChangeIndex = j;
                }
            }

            incompleteIndex = lastChangeIndex;
            trace(randomNumber);

        }

    }

    private static void trace(int[] randomNumber) {

        System.out.println("trace:" + Arrays.toString(randomNumber));

    }

}

プログラムの実行結果は下図のようになります。

1

ザックリ説明すると例えば次のような配列が与えられた時

1, 2, 5, 8, 7, 9, 6

最初の while ループは

1, 2, 5, 8, 7, 9 ← 6

1, 2, 5, 8, 7 ← 6, 9

1, 2, 5, 8 ← 6, 7, 9

1, 2, 5 – 6, 8, 7, 9

1, 2 – 5, 6, 8, 7, 9

1 – 2, 5, 6, 8, 7, 9 (赤字は比較交換、緑字は比較未交換)

となり、配列のインデクスナンバー 3 まではソート完了となります。

1, 2, 5, 6, 8, 7, 9 (ピンク色の数字はソート完了済み)

よって、while ループの条件を可変することにより無駄な処理をへらせます。

また、内側の for ループも最後に要素交換した右側のインデックスナンバー(ソートが確定していない)を利用して

無駄に比較捜査をしないようにさせています。要するにソート済み部分の再捜査をしないことによって効率を上げようというものです。

次の while ループ処理は

1, 2, 5, 6, 8, 7 – 9

1, 2, 5, 6, 8 ← 7, 9

1, 2, 5, 6, 7, 8, 9

次の While ループで

1, 2, 5, 6, 7, 8 – 9

1, 2, 5, 6, 7, 8, 9

ソート完了!

もし、涙ぐましい改良がされていなければ無駄な比較処理がたくさん行われることになったでしょう。

今回は一般的なバブルソートの改良版を紹介しましたがバブルソートの亜種はまだあります。

シェーカーソートはバブルソートの亜種で安定のまま高効率化が達成?されています。

これはバブルソートを先頭からと末尾から交互に捜査して並べ替えていくものです。

だからシェーカーなんですね。(^_^)

アルゴリズムの基本的な考え方はバブルソートそのものなので興味のあるかたはプログラムを組んで楽しんでください。(^_^)

Hatena タグ: