JavaFX 学習がてらにつまらないアプリをつくってしまった。

少し前から JavaFX を遊びながら学習しはじめたのですが情報が古い物から新しい物まであって何が何だか解らなくなります。

それだけ JavaFX は黒歴史なんだなぁって再認識しました。

それは置いといてどんなものを作ったかというと・・・

ついこの間はじめたばかりなのでネット上のサンプルを真似ていろいろ、あーでもない、こーでもない。。。

なんでこのコードで動かないの?

なんでこのコードで動くの?って状態でプログラムくんでます。(^_^;)

そんなこんなで創ったのは、あるサイトの画像を表示させるというプログラムです。

ついでに、1秒から5秒までのタイムリミット機能をつけてみました。

タイムアウト時にはデフォルト画像をお茶を濁す感じで表示させてみました。

無事に画像を表示させたらエフェクトをかけられるようにしました。

さらに、その画像を保存できるようにしてみました。

ただ、お遊びプログラムなので画像取得先サイトは3件だけです。

私の好みの女性タレント 堀北 真希さんと 北川 景子さんのブログから一枚取得するようにしました。

あと一つは 5秒以内で取得できない想定のために NASA です。

このプログラムではダミーで3秒のスリープをいれてあります。

以下にスクリーンショットと動画を貼っておきますね。

1

2

3

4

5

6

7

8

9

10

ちなみに最後の画像のダイアログはお遊びです。

普通はこんな問いかけはないですよね。

動画は仮想マシン上の Windows 8.1 で実行したものをキャプチャしたものなのでちょっと動作が緩慢になっています。

よ~く動画をみるとこのプログラムには致命的な欠点があることに気付きます。

学習用のお遊びサンプルとしては問題ないのですが・・・

そういう理由で今回はコードを晒しません。

そもそも学習し始めた初心者のコードに興味を持つ人はいないだろう。

動画が再生できない、もしくはこの欠陥アプリを使いたい人のために Java Web Start もおいときます。

Java 8 に依存している部分があるので Java 8 の実行環境でないと動かないです。

こちらは 0.5 秒のダミー(スリープ)をいれてあります。

Webstart: click to launch this app as webstart (Java 8 実行環境必須)

Hatena タグ:

JavaFX でさらに足し算のお勉強

前回のプログラムを利用して今回も JavaFX で足し算アプリに手を加えてみることにしました。

今回追加する機能は アプリのウィンドウサイズの変更をできないようにする。

チェックボックスを利用して BGM を流せるようにする。

問題の難易度を選択できるようにトグルボタンを排他制御して可能にする。

ツールチップを設定する。

ニーモニックを設定する。

結局、こんな感じにできあがりました。

1

 

2

 

3

 

4

 

トグルボタンは私の実力ではニーモニックを正しく動作させることができなかったので諦めました。(>_<。)

素直にラジオボタンを使えばよかったかも・・・

トグルボタンの排他制御のイベント処理はかなり怪しいことをしています。

我ながらこれは無いだろうと思いながら他に良い方法を知らないので動けばいいやってのりでやってます。(オヒ

だからニーモニックが・・・・・ とどのつまりラジオボタンを使おう、今度からは。

いちおう、なんとか動いたので良しとしました。(^_^;)

それではそんなこんなでいい加減ですがプログラムを晒しておきます。

package jp.yucchi.calc;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Calc2 extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("CalcForm.fxml"));

        Scene scene = new Scene(root);

        stage.setTitle("足し算できますか?");
        stage.setScene(scene);
        stage.setResizable(false);
        stage.show();
    }

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

}
package jp.yucchi.calc;

import java.awt.Toolkit;
import static java.lang.Integer.parseInt;
import java.net.URL;
import java.util.Random;
import java.util.ResourceBundle;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.control.ToggleButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;

public class CalcFormController implements Initializable {

    private int x;
    private int y;
    private int resultAnswer;
    private int modeNumber = 99;

    Random rnd = new Random();

    private final Media start = new Media(getClass().getResource("start.mp3").toExternalForm());
    private final Media ok = new Media(getClass().getResource("ok.mp3").toExternalForm());
    private final Media ng = new Media(getClass().getResource("ng.mp3").toExternalForm());
    private final Media bgm = new Media(getClass().getResource("bgm.mp3").toExternalForm());
    private final Media m_easy = new Media(getClass().getResource("easy.mp3").toExternalForm());
    private final Media m_normal = new Media(getClass().getResource("normal.mp3").toExternalForm());
    private final Media m_hard = new Media(getClass().getResource("hard.mp3").toExternalForm());

    @FXML
    private Label questionLabel;

    @FXML
    private TextField answerField;

    @FXML
    private Label resultLabel;

    @FXML
    CheckBox bgmCheck;

    @FXML
    ToggleGroup mode;

    @FXML
    ToggleButton easy;

    @FXML
    ToggleButton normal;

    @FXML
    ToggleButton hard;

    @FXML
    public void handleAnswer(ActionEvent event) {

        Pattern intPattern = Pattern.compile("[0-9]+");
        Matcher match = intPattern.matcher(answerField.getText());

        if (match.matches() != false || answerField.getText().isEmpty()) {
        } else {
            resultLabel.setText("数値を入力してね!");
            Toolkit.getDefaultToolkit().beep();
        }
        if (answerField.getText().isEmpty()) {
            resultLabel.setText("答えを入力してね!");
            Toolkit.getDefaultToolkit().beep();
        } else {
            boolean result = calc(answerField.getText());
            if (result) {
                resultLabel.setText("正解!");
                MediaPlayer mp_ok = new MediaPlayer(ok);
                mp_ok.play();
            } else {
                resultLabel.setText("不正解!");
                MediaPlayer mp_ng = new MediaPlayer(ng);
                mp_ng.play();
            }
        }
    }

    @FXML
    public void handleClear(ActionEvent event) {
        answerField.clear();
        resultLabel.setText(null);
        x = rnd.nextInt(modeNumber) + 1;
        y = rnd.nextInt(modeNumber) + 1;
        resultAnswer = x + y;
        questionLabel.setText(" " + x + " + " + y + " = ");
    }

    @FXML
    public void handleEasy(ActionEvent event) {
        if (easy.isSelected()) {
            modeNumber = 99;
            answerField.clear();
            resultLabel.setText(null);
            x = rnd.nextInt(modeNumber) + 1;
            y = rnd.nextInt(modeNumber) + 1;
            resultAnswer = x + y;
            questionLabel.setText(" " + x + " + " + y + " = ");
            MediaPlayer mp_easy = new MediaPlayer(m_easy);
            mp_easy.play();
        } else {
            easy.setSelected(true);
        }
    }

    @FXML
    public void handleNormal(ActionEvent event) {
        if (normal.isSelected()) {
            modeNumber = 999;
            answerField.clear();
            resultLabel.setText(null);
            x = rnd.nextInt(modeNumber) + 1;
            y = rnd.nextInt(modeNumber) + 1;
            resultAnswer = x + y;
            questionLabel.setText(" " + x + " + " + y + " = ");
            MediaPlayer mp_normal = new MediaPlayer(m_normal);
            mp_normal.play();
        } else {
            normal.setSelected(true);
        }
    }

    @FXML
    public void handleHard(ActionEvent event) {
        if (hard.isSelected()) {
            modeNumber = 99999;
            answerField.clear();
            resultLabel.setText(null);
            x = rnd.nextInt(modeNumber) + 1;
            y = rnd.nextInt(modeNumber) + 1;
            resultAnswer = x + y;
            questionLabel.setText(" " + x + " + " + y + " = ");
            MediaPlayer mp_hard = new MediaPlayer(m_hard);
            mp_hard.play();
        } else {
            hard.setSelected(true);
        }
    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {

        x = rnd.nextInt(modeNumber) + 1;
        y = rnd.nextInt(modeNumber) + 1;
        resultAnswer = x + y;
        questionLabel.setText(" " + x + " + " + y + " = ");
        MediaPlayer mp_start = new MediaPlayer(start);
        mp_start.play();

        bgmCheck.selectedProperty().addListener(new ChangeListener() {
            MediaPlayer mp_bgm;

            @Override
            public void changed(ObservableValue ov, Boolean oldVal, Boolean newVal) {
                if (newVal.booleanValue()) {
                    mp_bgm = new MediaPlayer(bgm);
                    mp_bgm.setVolume(0.07);
                    mp_bgm.play();
                    mp_bgm.setCycleCount(MediaPlayer.INDEFINITE);
                } else {
                    mp_bgm.stop();
                }
            }

        });

    }

    private boolean calc(String ans) {
        int answer = parseInt(ans);
        return answer == resultAnswer;
    }

}












  
    
      
        
          
            
            
              
                
              
            
          
        
        
          
            
              
                
              
              
                
              
              
                
              
            
            
              
                
              
              
                
              
            
            
              
                
              
            
          
        
        
          
            
            
          
          
            
          
        
      
    
    
    
      
        
      
      
        
      
    
  


アプリのウィンドウサイズの変更をできないようにするために Calc2.java の 19 行目で

stage.setResizable(false);

としています。

チェックボックスを利用して BGM を流せるようにするために CalcFormController.java の 163 行目から 178 行目までで

チェックボックスにリスナーを設定して制御しています。

トグルボタンはグループ化して排他制御可能としてます。

これは JavaFX Scene Builder を使って簡単に設定できます。

トグルボタンのイベントをそれぞれ実装して JavaFX Scene Builder で結びつければいいだけです。

トグルボタンのグループも JavaFX Scene Builder で簡単に設定できます。便利!便利!

ただ前述したとおりトグルボタンが必ずどれか一つ選択状態にあるようにしたいため適当なことをやっています。

おそらく、なんだこれは?といいたくなるかもしれませんがスマートな方法を知らないのでこうなりました。(^_^;)

よってトグルボタンにニーモニックを設定しても上手く動作しなくなります。だからニーモニックはあきらめました。(ヲヒ

チェックボックス、テキストフィールド、ボタンにはニーモニックを JavaFX Scene Builder で簡単に設定できます。

プロパティの Text 欄に _ を先頭につけて記入し(_BGM)

5

 

Mnemonic Parsing のチェックボックスを ON にすればいいだけです。

6

 

ツールチップも同様に JavaFX Scene Builder を使えば楽勝です!

JavaFX Scene Builder のライブラリ Popup Controls から Tooltip をドラッグアンドドロップして

プロパティを設定してやればいいだけという非常に楽ちんな作業です。

7

 

以上、こんな感じでできあがりました。

Webstart: click to launch this app as webstart

ちょっと五月蠅くなってしまいましたがご勘弁を。

もっといろいろ楽しいことが出来るようなのでボチボチと遊んでみたいと思ってます。

cludia_2013_08_06_001

Hatena タグ: ,