Java FX in RPi 〜プロパティファイルの読み込み JavaFX実装〜

今回は、プロパティファイルの読み込みを実装します。
以前、コンソールアプリ作成でやったものもあるのでそちらもどうぞ。

ちなみに、前回は大まかにどんなものを作るのか?ということと、実装環境に関して記載しました。

プロパティファイルを読む

目的は、アプリケーションの起動時に初めに設定を読み込み表示するYoutubeのURLを設定、?秒おきに表示を切り替えるものです。

ちなみに作成したプロパティファイルは下のようなものです。

# Properties for this application

#########################################################
# URL List for load Youtube (rule "url" + number        #
#########################################################
url1=https://www.youtube.com/watch?v=6qhJsvpd0ds
url2=https://www.youtube.com/watch?v=w9BubZIEGdg
url3=https://www.youtube.com/watch?v=YPuaUUvCdMg
url4=https://www.youtube.com/watch?v=w9iiCnX0STw
url5=https://www.youtube.com/watch?v=XW7FgoR5pzQ&t=63s
url6=https://www.youtube.com/watch?v=DZEWd0Viiuk&t=1s
url7=https://www.youtube.com/watch?v=45xcPvhGhDo
url8=https://www.youtube.com/watch?v=w9BubZIEGdg

プロパティファイルの読み込み

使用するクラスはPropertiesクラスです。

早速プログラムを作成しました。Githubにアップしてあります。
そして、テスト駆動開発ですので、テストケースから作成しています。

テストケースを作成する

JUnitでのテストを作るのに、以下のような手順で作成します。

  1. 作成するクラスはどのように動くか決める
  2. 作成したものが、想定通りに動く確認する処理をかきます
  3. 実行して緑色になることを確認(下の図を参照ください)

作成する時にJUnitでやる時のポイントも記載しておきます。
Junitをビルドパスニ追加しておく必要があります。そして、Mavenでdependencyを追加したときはすでにビルドパスに追加されています。。。

アノテーションで設定

「@Test」: 実行するテストを使用します。
「@Before」: テストを実行する前に起動する。主にテストの実行準備などを行う

具体的に。。。

public class MainTest {
    /** テスト対象クラス */
    private Main target;

    /**
     * テストを行うための準備処理
     */
    @Before
    public void initTest() {
        // テスト対象クラスのインスタンスを生成
        target = new Main();
    }

/** loadProperties()のテスト */
    @Test
    public void testLoadProperties() {
        target.loadProperties();
        Set keySet = target.getKeySet();
        keySet.forEach(System.out::println);
    }
}

上のコードを実行したものが、下のキャプチャです。

そして、@Beforeのついているメソッドは。。。

/**
 * テストを行うための準備処理
 */
@Before
public void initTest() {
    // テスト対象クラスのインスタンスを生成
    target = new Main();
}

のようになっています。単純にテスト対象クラスをインスタンス化してフィールド変数「target」に代入しています。

そして、テストケース(メソッド)「testLoadProperties()」

/** loadProperties()のテスト */
@Test
public void testLoadProperties() {
    target.loadProperties();
    Set keySet = target.getKeySet();
    keySet.forEach(System.out::println);
}

テストとして実行するメソッド(テストケース)は「@Test」をつけてやります。実行結果に関しては上のキャプチャに記載しています。
ちなみに実行したコードは下のものです。

/** loadProperties()のテスト */
@Test
public void testLoadProperties() {
    target.loadProperties();
    Set keySet = target.getKeySet();
    assertNull(keySet);
    keySet.forEach(System.out::println);
}

これは失敗したコードです。そしてテストとしては失敗しなくてはいけないコードです。

どーゆーことか?

コードに色付けができなかったのですが、下のようなコードを追加しました。
assertNull(keySet);このコードは取得したキーセットがNullにならないとAssertErrorを出力するメソッドです。
本当であれば、assertNotNull()を使わないといけません。このような部分はテスト仕様なのでどのような処理を行うかちゃんと設計しなくてはいけません。。。

そして、下のコードが直したものです。

/** loadProperties()のテスト */
@Test
public void testLoadProperties() {
    target.loadProperties();
    Set keySet = target.getKeySet();
    assertNotNull(keySet);
    keySet.forEach(System.out::println);
}

そして、実行結果は緑色になっています。

こんな感じでプロパティファイルが読めていることを確認しています。
keySet.forEach(System.out::println);
出力結果

*** testLoadProperties ***
url5
url6
url3
url4
url1
url2
url7
url8
*** testConvertKeySet ***
test4
test2
test3
test1

こんな感じで作成しました。

でわでわ。。。



Java FX in RPi 〜ラズパイで動くJavaFX〜

Javaで作成する、画面アプリをラズパイで動かそうと言うものです。
今回は、作成したアプリをラズパイ上で動かし、「Youtubeプレイヤーとして動かそう!」と言うものです。

JavaFX in RPi

開発環境構築

前提として、自分が使用している開発環境について記載します、

  1. SceneBuilderを使用しています。(JavaFXの初期コード生成などしてくれます)
  2. JDK1.8を使用(RPiもJDK1.8を使用します)

SceneBuilderのインストール

こちらの記事にインストール手順と実際に動かした時の内容を記載しました。(動かしてみた時の記事)
このセットアップをしておくとJavaFXのプロジェクトを作成した時に、下のようなコードを生成してくれます。

public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        try {
            BorderPane root = new BorderPane();
            Scene scene = new Scene(root,400,400);
            scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}

ちなみに、プロジェクトをMaven化しているのでPOMファイルがあります。生成されるのはapplication.cssとMain.javaです。

開発開始

現状(上こコード)では下のような表示ができます。

まぁ何も実装していないので何もないです(笑)
ここに必要なもの(コンポーネント(ボタンなど))を追加していきます。

設計

設計の大まかなところはGithubにアップしています。
なので、とりあえずはURLをロードして、表示する画面を作成します。
大まかな仕様は以下の通りです。
<仕様>

  1. JavaFXを起動
  2. プロパティファイルをロード(読み込む)
  3. プロパティファイルにあるURLを読み込み表示する

とりあえずはここまで実装しようと思っています。

JavaFXの起動

とりあえず生成されたコードで動いているので、この部分は飛ばします。

1.プロパティファイルの読み込み

RPi(ラズパイ)で動かす時にはMavenのプラグインで出力するJARファイルを起動して動かすので、別途プロパティファイルをJARファイルの隣(同じ階層)に配置する必要があります。
しかし、開発段階では気にしなくて良いので、resources/いかにプロパティファイルを配置します。

そんなわけで実装開始〜

プロジェクトの設定

単純に使用したいライブラリ、JARファイルの出力を設定します。
まずは使用するJUNIT(使い方など)dependencyに追加、使用できるようにします。

ちなみに、EclipseのMavenプロジェクトの場合はPOMファイルに下のような設定をかき、ビルド(Install)すると必要なライブラリが追加されます。

実行するときは下のようにPOMファイルを右クリックして Maven Installを実行します。

ちなみに、自分が作成したPOMファイル(コピペで作成)は以下のようなものです。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>RPiMediaPlayer</groupId>
  <artifactId>RPiMediaPlayer</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>RPi メディアプレーヤー</name>

<!-- 必要な情報をプロパティとしてもつ -->
  <properties>
      <java.version>1.8</java.version>
      <maven.compiler.target>${java.version}</maven.compiler.target>
      <maven.compiler.source>${java.version}</maven.compiler.source>
  </properties>  
<!-- 使用したいライブラリ(依存性)の設定 -->
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
<!-- ビルドの設定 -->
  <build>
    <sourceDirectory>src</sourceDirectory>
    <resources>
      <resource>
        <directory>src</directory>
        <excludes>
          <exclude>**/*.java</exclude>
        </excludes>
      </resource>
    </resources>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.7.0</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
    <plugin>
      <artifactId>maven-assembly-plugin</artifactId>
      <configuration>
        <archive>
          <manifest>
            <addClasspath>true</addClasspath>
            <mainClass>zenryokuservice.socket.server.SocketServerBasic</mainClass>
            <classpathPrefix>dependency-jars/</classpathPrefix>
          </manifest>
          </archive>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
      </configuration>
      <executions>
        <execution>
          <id>make-assembly</id> <!-- this is used for inheritance merges -->
          <phase>package</phase> <!-- bind to the packaging phase -->
          <goals>
            <goal>single</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-dependency-plugin</artifactId>
      <version>2.5.1</version>
      <executions>
        <execution>
          <id>copy-dependencies</id>
          <phase>package</phase>
          <goals>
          <goal>copy-dependencies</goal>
          </goals>
          <configuration>
           <outputDirectory>
             ${project.build.directory}/dependency-jars/
           </outputDirectory>
          </configuration>
         </execution>
       </executions>
     </plugin>
    </plugins>
  </build>
</project>

実装まで行きませんでしたが、ここら辺で失礼いたします。

でわでわ。。。



Java FX RPi Media Player 〜ラズパイ・メディアプレーヤー〜

今回は、ラズパイ上で動くメディアプレーヤーを作成しようと思います。

経緯

本当はYoutubeを再生するアプリを作成しようとしたのですが、これを設計している最中に「作成していく途中で結局メディアプレーヤーを作ることになるな・・・」と思い、このようになりました。

開発準備

いつも通りに、Eclipseを使用します。

そして、セットアップ関連はこちらの記事を参考にしてください。

Windows版はこちらの記事でEclipseのインストールを行いました。

ラズパイで動かす

今までにラズパイ上で動かすため、Eclipse Kuraのセットアップに挑戦していましたが、ちょっとこちらをストップ。
シンプルにJavaSE(JDKに入っているAPI)で進めてみようと思いました。

JavaSEはラズパイだろうが、PCだろうが、Arduinoだろうが動かすことができます。
ただし、Bluetoothなどのデバイスにアクセスしたい場合には、以下のような手間があります。

  1. ちょっとしたライブラリを使用
  2. 自分でデバイス用のプログラムを書く

なので、今回はそれらを使用しない方法でやろうと思います。
つまり。。。

JavaSEでの開発

Java 8 以降、JavaSEにはJavaFX(画面作成API)が梱包されているので、そのまま使用することができます。
具体的には下のようなコンポーネント(画面とか、ボタンとか)をJavaで作成、動かすことができます。
下のものは JavaFXでのサンプルアプリです。

そして、自分が作成したものです。

これらは、Javaのみで(PCに付けたUSBとかディスプレイなど)にアクセスしないで起動できるのでJavaSEのみで作成、起動することが可能です。

と言うわけでJavaFXでの開発方法を以下にまとめます。

開発方法

実際に開発するのには、手間が少ない方が良いです。(みんなそう思うし、時間ができれば色々なことができます)
なのでなるべくなら「手間を少なく」「良いアプリを作る」ここら辺に注力して準備を進めたいと思います。

  1. NotePCでのEclipseでの開発(プログラム作成)
  2. NotePC上でテスト(ローカル・テスト)
  3. RPi上でテスト(実機テスト)

こんな感じで開発を進めたいのですが、これを実現するためにMavenを使用します。
英語のサイトなので日本語訳してみます(最近のものは意味がわかるようになってきています)

まとめると下のようになります。

  1. Eclipseにプロジェクトを作成する
  2. Githubにリポジトリを作成する
  3. NotePC上でテストしたコードをコミット(PUSH)
  4. ラズパイでGithubからPULLしてソースを取得
  5. Mavenビルドで起動ファイル(*.JAR)を生成
  6. ラズパイのSHELLでOS起動時に動かす

まずはNotePCで動かす

そんなわけで、NotePC上で開発を始めます。ちなみに、上の手順「4」の確認は行いました。ハローワールドプログラムを起動することに成功しています。JavaFXも起動確認済みです。ただし、Xサーバー(GUIサーバー)を起動する必要があるのでラズパイをCUIモードで動かすとJavaFXが動きません。。。

ちょっと長くなってきたので、今回はここまでにします。

でわでわ。。。

関連ページ

Eclipseのインストール〜java学習フロー



JavaFX embed to browzer 〜JavaFXをブラウザから起動〜

イントロダクション

JavaFXで作成したアプリケーションをブラウザ(HTML)に埋め込む方法→HTMLで表示したページからJavaFXのアプリケーションを起動できるようにする方法を記載します。参考にしたのはこの記事(StackOverflow)

アプリの準備

JavaFXで動くものを作成します。今回は以前作成したサンプルアプリを使用します。こんなものです。これはOracleのドキュメントに載っていたものです。プログラムの全体はここのリンク先にあります(Zipファイルです、ダウンロードが始まります。)

このプログラムは下の図のように「MarthKitJavaFX」プロジェクトの中にあるXylophone.javaクラスを起動すると上記のようなアニメーションが観れます。

記事にあるように、やってみます。

*.jnplと*.htmlファイルを出力

まずはコンソールを起動します。Windowsの場合はコマンドプロンプトです。

そして、以下のようにコマンドを入力します。

cd プロジェクトまでのパス(自分の場合は「cd ~/git/MathKitJavaFX/MathKitJavaFX)

そして、javapackagerコマンドが使用できるか確認します。

$ javapackager -help

下のように使用方法が表示されるはずです。JDKにパスが通っていれば(javaコマンドが使用できればこれも使用できます。JDK1.8で試しました。)

続いて、以下のようにコマンドを叩きます。ちょっと長いので1行を区切って記載します。赤い字は自分で決める部分です。自分の場合はクラスを次のように配置しているます。「package zenryokuservice.fx.tutorial.download.Xylophone」そして、出力するJarファイルの名前は「myapp」です。

javapackager -createjar -outdir compiled

-outfile myapp -appclass zenryokuservice.fx.tutorial.download.

Xylophone -srcdir bin -v

繋げると下のようになります。叩くときは下のように入力してください。

javapackager -createjar -outdir compiled -outfile myapp -appclass zenryokuservice.fx.tutorial.download.Xylophone -srcdir bin -v

しかし、ここでエラーが出ました。詳細はこちらにてご確認下さい。

結局のところはこのコマンドを使用しなくてもよかったのですが、それは次のコマンドを実行した時にわかりました。自分が実行したものです。

javapackager -deploy -outdir deployed -outfile TestApp -width 600 -height 600 -name Xylophen -appclass zenryokuservice.fx.tutorial.download.Xylophone -v -srcdir compiled

出力したファイルは「TestApp.html」と「TestApp.jnlp」です。こいつを自分のとこのサーバーにアップロードします。

配置先はここからアクセスできます。しかし、現状では動きませんでした。ここからさらに調査を進めます。

でわでわ。。。









JavaFx グラフ描画〜y=axのグラフを描く〜

イントロダクション

前回は、グラフの土台→X軸とY軸、補助線の描画を行いました。

こんなグラフの土台を作りました。

いよいよ関数を描画

ここで問題があります。

<問題>

  1. 原点の位置(0, 0)が画面上の左上にある
  2. しかし描画したいのは画面の中心が(0, 0)

ここの問題を解決するのに以下の方法でやりました。

中心の座標を出せる様にXとYの値を変換するメソッドを作成しました。

下の様なメソッドです。

/**
 * X, Yの値をグラフ上の値から描画する座標に変換する。
 * @param value グラフ上の値(0,0)は画面の中心
 * @return 描画するCanvas上の値(0,0)は画面の左端
 */
private double convertCenter(int value, boolean isX) {
    int graphValue = 0;
    if (isX) {
        graphValue = value + (CANVAS_SIZE / 2);
    } else {
        graphValue = (CANVAS_SIZE / 2) - value;
    }
    return graphValue;
}

そして、関数を描画するメソッド

/**
 * 関数を描画する。
 * @param ctx Canvasから取得したクラス
 * @param root レイアウトクラス(シーン追加する)
 */
private void drawFunction(GraphicsContext ctx, VBox root) {
    /* 座標系を画面の端っこ(0, 0)を画面の中心にする */
    ctx.setFill(Color.RED);
    // 傾き
    int a = 1;
    for (int x = -(CANVAS_SIZE / 2); x <= (CANVAS_SIZE / 2); x++) {
        int y = y_ax(a, x);
        ctx.fillOval(convertCenter(x, true), convertCenter(y, false), 2, 2);
    }
}
/**
 * y=axの計算を行う。
 * @param a 傾き
 * @param x Xの値
 * @return yの値
 */
private int y_ax(int a, int x) {
    return a * x;
}

上のコードではfor文の中にある「x」が-300〜300まで移動するときのグラフを描画しています。※CANVAS_SIZE / 2 = 300

描画結果(Git)

赤い線が関数を描画下部分です。

次は、機械学習の教科書に戻ります。

<<< 前回
でわでわ。。。