Challenge Engineer Life !

エンジニア人生を楽しみたい!仕事や趣味で学んだ技術的なことを書いていくブログです。

JavaFX勉強会で堀北真希さんのLTをしてしまいました… #javafx_ja

今日はGlassFish勉強会とJavaFX勉強会が同日に平行開催されました。

GlassFish勉強会に登録していたのですが、後半で抜け出してJavaFX勉強会でLTをさせて頂きました(^^;

LTきっかけ

さくらばさんからJavaFX勉強会でお話しませんか、とお声かけ頂きました(>_<)

こんな光栄な機会を断るわけにいかない!ということで、技術的な内容が全くないLTでしたが、JavaFXに興味があるけど実際に触ったことがない方をターゲットに(ってJavaFX勉強会には、そんな人いないんじゃないかと思いつつ…汗)した発表をさせて頂きました。


発表資料

発表資料はアップしました。

堀北真希さんのことばかりで本当に恐縮です…

デモ動画

上記資料にもリンクで貼ってますが、ここでも載せておきます。
アプリケーションを作成したときのブログも入れときますが、作った時点からは色々といじって非同期にしたりとかしてますが、その辺りはどこかで機会あればまとめます(^^;

MakiMakiImageViewer

上記動画の後半はStageStyleでTRANSPARENTを指定したもので、アプリ上段の枠が消えただけなのですが、なんかビューアっぽい感じになってるかと(^^)これも作った後、さくらばさんからアドバイスもらったものです。

作ったときのブログ
堀北真希さん誕生日を祝ってJavaFXで画像ビューアを作ってみる
StageStyleを指定してみる

ここから始めるJavaFX!

自分はJJUGで今年の8月に行われたJavaFXハンズオンの資料を参考にして、初めてJavaFXを触りました。

このハンズオンで、SceneBuilderやプログラム作成の基本的な流れはわかるので、あとは自分で作りたいものを作ればいいのかなと。

JavaFXハンズオンにお家でChallenge!

感想

堀北真希エバンジェリストになりたい…(*´Д`)

SendGridFX : JavaFX meets SendGrid ! #JavaFX #SendGrid

I'm new to JavaFX and want to make something interesting.

A month ago I signed up SendGrid, because my old colleague @nakansuke starts to new business with SendGrid company.
He advised me that there is a good Java wrapper library of SendGrid WebAPI, it's sendgrid4j.
http://oss.flect.co.jp/libs/en/sendgrid4j.html

Exactly, it's good and easy to use SendGrid WebAPI.

Today I was having fun with JavaFX and SendGrid.
My simple idea is sending HTML mail with HTMLEditor on JavaFX.

This is my simple application.
I only use Label, TextField, Button and HTMLEditor.

f:id:kikutaro777:20131025233829j:plain

Only input sending e-mail address and subject and contents of mail by HTML.

f:id:kikutaro777:20131025234142j:plain

HTMLEditor component on JavaFX is good to write HTML.

I sent this mail to my web-mail of Yahoo, so checked it.

I think JavaFX programmer might say "Hey guy, why don't you check your web mail by WebView?" Yeah, that's true. I did it :)

This is my JavaFX application includes WebView.
Yes! I got the mail!
f:id:kikutaro777:20131025234414j:plain

I opened it and saw HTML mail.

f:id:kikutaro777:20131025235010j:plain

Of course, it's same looking of HTMLEditor :)

I show my code of JavaFX Controller class. It's very simple.

package jp.co.hoge.sendgridfx;

import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.web.HTMLEditor;
import jp.co.flect.sendgrid.SendGridClient;
import jp.co.flect.sendgrid.SendGridException;
import jp.co.flect.sendgrid.model.WebMail;

public class SendGridFXController implements Initializable {
    
    //SMTP authentication info of SendGrid
    private static final String SMTP_AUTH_USER = "blah-blah-blah";
    private static final String SMTP_AUTH_PWD  = "blah-blah-blah";
    
    //Mail from info
    private static final String MAIL_FROM = "kiku@test.com";
    private static final String MAIL_FROM_NAME = "Test from Kiku";
    
    SendGridClient client;
    
    @FXML
    private HTMLEditor editor;
    
    @FXML
    private TextField textTo;
    
    @FXML
    private TextField textTitle;
    
    @FXML
    private Label message;
    
    @FXML
    private void sendButtonAction(ActionEvent event) {
        try {
            WebMail mail = new WebMail();
            
            //setting mail from
            mail.setFrom(MAIL_FROM);
            mail.setFromName(MAIL_FROM_NAME);
            
            //setting mail to
            mail.setTo(textTo.getText());
            
            //setting mail subject
            mail.setSubject(textTitle.getText());
            
            //setting HTML content
            mail.setHtml(editor.getHtmlText());
            
            //sending mail
            client.mail(mail);
            
            message.setText("Sending mail is success.");
        } catch (IOException | SendGridException ex) {
            message.setText("Sending mail is failed.");
        }
    }
    
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        client = new SendGridClient(SMTP_AUTH_USER, SMTP_AUTH_PWD);
    }    
}

We can use sendgrid4j by maven.

Here is pom.xml.
Repository setting of sendgrid4j.

<repositories>
    <repository>
        <id>jp.co.flect</id>
        <name>FLECT maven repository</name>
        <url>http://flect.github.io/maven-repo/</url>
    </repository>
</repositories>

Dependency is here.

<dependencies>
    <dependency>
        <groupId>jp.co.flect</groupId>
        <artifactId>sendgrid4j</artifactId>
        <version>0.9.1</version>
    </dependency>
</dependencies>

That's it :)

JavaFXとSendGridで簡易送信メーラーSendGridFXを作る!

少し前にSendGridへ登録したのですが、結構放置してました(^^;

登録の流れやJavaで送信する簡易プログラムは前のエントリを参照下さい↓

JavaでSendGridを利用したメール送信

sendgrid4j使うとJavaで簡単にSendGrid経由にメール送れるので何か面白いことできないかなぁ、と思ってたのですが、最近遊んでるJavaFXと合わせてみました。

名付けてSendGridFX!(なにそれ

すごい簡単なプログラムですが、JavaFXのHTMLEditorコンポーネントを使って、SendGrid経由でHTMLメールを送る、というものです(^^;それだけ

画面は以下のような感じで、ラベルとテキストとボタン、そしてHTMLEditorだけの超シンプルな構成です。

f:id:kikutaro777:20131025193729j:plain

宛先とタイトルを入れて、メール内容をHTMLEditorで書きます。

f:id:kikutaro777:20131025193805j:plain

HTMLEditorで

  • フォント色やサイズ、太字・イタリックに変えたり
  • 横罫線入れたり
  • 箇条書き(番号つきも)
  • センタリングや右寄せ

などなどしてみました。

で、送信!!

受信したメーラ(ThunderBird)でみると(本当はメーラもJavaFXで作ってるとかっこいい気も…)

ちゃんとHTMLメール!!(あたりまえっ

f:id:kikutaro777:20131025194056j:plain

せっかくなので、Yahooメール辺りに送って、JavaFXのWebViewからみてみます(^^;

こんなメールを

f:id:kikutaro777:20131025195149j:plain

送信!

JavaFXでWebViewを置いたアプリでYahooのメールをみてみます。

f:id:kikutaro777:20131025195218j:plain

おおー

f:id:kikutaro777:20131025195227j:plain

やはりJavaFX面白い!そしてSendGridも便利そう!

ちなみにSendGridは前に一緒に仕事していた後輩がSendGrid社とパートナーになって最近力を入れていますので興味ある方は是非彼に!ブログも始めたらしい(^^↓

プログラム

NetBeans7.4からJavaFXプロジェクトをMavenで作れるようになったので、sendgrid4jもpom.xml

リポジトリ

<repositories>
    <repository>
        <id>jp.co.flect</id>
        <name>FLECT maven repository</name>
        <url>http://flect.github.io/maven-repo/</url>
    </repository>
</repositories>

依存性を書けばOKですね。

<dependencies>
    <dependency>
        <groupId>jp.co.flect</groupId>
        <artifactId>sendgrid4j</artifactId>
        <version>0.9.1</version>
    </dependency>
</dependencies>

Maven使えるとやはり楽w

コードはこんなレベルです(^^;JavaFXのコントローラだけですが

package jp.co.hoge.sendgridfx;

import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.web.HTMLEditor;
import jp.co.flect.sendgrid.SendGridClient;
import jp.co.flect.sendgrid.SendGridException;
import jp.co.flect.sendgrid.model.WebMail;

public class SendGridFXController implements Initializable {
    
    //SendGridのSMTPアクセス情報
    private static final String SMTP_AUTH_USER = "hogehoge";
    private static final String SMTP_AUTH_PWD  = "hogehoge";
    
    //送信元の情報
    private static final String MAIL_FROM = "kiku@test.com";
    private static final String MAIL_FROM_NAME = "キクタローテスト";
    
    SendGridClient client;
    
    @FXML
    private HTMLEditor editor;
    
    @FXML
    private TextField textTo;
    
    @FXML
    private TextField textTitle;
    
    @FXML
    private Label message;
    
    @FXML
    private void sendButtonAction(ActionEvent event) {
        try {
            WebMail mail = new WebMail();
            
            //送信元情報
            mail.setFrom(MAIL_FROM);
            mail.setFromName(MAIL_FROM_NAME);
            
            //送信先
            mail.setTo(textTo.getText());
            
            //送信タイトル
            mail.setSubject(textTitle.getText());
            
            //HTMLエディタ入力内容
            mail.setHtml(editor.getHtmlText());
            
            //メール送信
            client.mail(mail);
            
            message.setText("メールの送信に成功しました。");
        } catch (IOException | SendGridException ex) {
            message.setText("メールの送信に失敗しました。");
        }
    }
    
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        client = new SendGridClient(SMTP_AUTH_USER, SMTP_AUTH_PWD);
    }    
}

簡単なメール送信するだけなら、こんなレベルで作れます(^^;

ちなみにJDK8で作っていたのですが、HTMLEditorを使うと実行時に以下のエラーで落ちました…。


Exception in Application start method
java.lang.StringIndexOutOfBoundsException: String index out of range: -1
at java.lang.String.substring(String.java:1959)
at com.sun.javafx.scene.web.skin.HTMLEditorSkin$15$1.updateItem(HTMLEditorSkin.java:699)
at com.sun.javafx.scene.web.skin.HTMLEditorSkin$15$1.updateItem(HTMLEditorSkin.java:694)
at javafx.scene.control.ListCell.updateItem(ListCell.java:442)
at javafx.scene.control.ListCell.indexChanged(ListCell.java:320)
at javafx.scene.control.IndexedCell.updateIndex(IndexedCell.java:115)
at com.sun.javafx.scene.control.skin.VirtualFlow.setCellIndex(VirtualFlow.java:1730)
at com.sun.javafx.scene.control.skin.VirtualFlow.getCell(VirtualFlow.java:1627)
//略
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:491)
//略
Caused by: java.lang.RuntimeException: Exception in Application start method
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:868)
at com.sun.javafx.application.LauncherImpl.access$000(LauncherImpl.java:55)
at com.sun.javafx.application.LauncherImpl$1.run(LauncherImpl.java:157)
at java.lang.Thread.run(Thread.java:724)
Caused by: java.lang.StringIndexOutOfBoundsException: String index out of range: -1
at java.lang.String.substring(String.java:1959)
at com.sun.javafx.scene.web.skin.HTMLEditorSkin$15$1.updateItem(HTMLEditorSkin.java:699)
at com.sun.javafx.scene.web.skin.HTMLEditorSkin$15$1.updateItem(HTMLEditorSkin.java:694)
at javafx.scene.control.ListCell.updateItem(ListCell.java:442)
//略
at com.sun.glass.ui.win.WinApplication.access$300(WinApplication.java:39)
at com.sun.glass.ui.win.WinApplication$3$1.run(WinApplication.java:101)
... 1 more
Exception running application jp.co.hoge.sendgridfx.MainApp

JDKというよりmavenまわりなのかな(^^;JDK7にしたら動いたので、とりあえず今回のサンプルはNetBeans7.4とJDK7で作りました。

JavaFXでYouTubeのダウンローダ的なサンプルを作ってみる ~動画の自動再生と履歴ページ遷移~

ブログと関係ないですが、昨日から堀北真希さん主演ドラマ「ミス・パイロット」が始まりました(^^)/システム屋らしく緊急対応で観れないっていう残念な事態になりましたが…とほほ(-_-;

まあ、録画したので、後日楽しみます。フジテレビの公式サイトはこちら↓
http://www.fujitv.co.jp/misspilot/index.html

……

宣伝はさておき、今日は先日サンプルで作ったJavaFXのYouTubeダウンローダ的なサンプルを少し改造しました。作ったときのブログはこちら↓
JavaFXでYouTubeのダウンローダ的なサンプルを作ってみる

すごいショボイですが、以下2つトライしました。

  • ダウンロードが終わったら動画を自動再生する
  • サイトの履歴を表示して、選択した履歴を表示できるようにする

ダウンロードが終わったら動画を自動再生する

本当は落としたファイルをJavaFXのMediaViewで観れるようにしてみよう!とか思ったのですが、SceneBuilderにMediaViewがない(^^;そういうものなのかな。

あと、YouTubeで落とした動画もWEBM形式というのに(最近?)なっているので、MediaViewが使えても再生できるかわからなかったので、とりあえずベタにChromeのexeを叩いて実行する、という方法でやりました。

Javaからexe叩く方法は以下サイトを参考にさせて頂きました。
ひしだまさんのサイト 外部プロセス起動

実行結果はこんな感じ。

起動するとYouTubeページを表示

f:id:kikutaro777:20131016192734j:plain

せっかくなので「ミスパイロット」で検索して

f:id:kikutaro777:20131016192822j:plain

適当な動画を選びます。
ジャケット着る姿が超りりしい (*´Д`)ハァハァ

f:id:kikutaro777:20131016192846j:plain

ダウンロードボタンを押すと、前回と同様に動画のダウンロードされます。

f:id:kikutaro777:20131016192947j:plain

で、ダウンロード完了と同時にChromeが起動して自動再生します。
二度目の (*´Д`)ハァハァ。

f:id:kikutaro777:20131016193010j:plain

こんだけ(^^;

履歴ページ遷移

画面にコンボボックスを設けてページ遷移の履歴を一覧表示するようにしました。

適当に色々たどった状態でコンボボックスを開くと

f:id:kikutaro777:20131016193204j:plain

以下のような感じで履歴が出ます。

f:id:kikutaro777:20131016193230j:plain

横が長すぎて不格好(^^;
今はWebEngineから取得できるHistoryのリストをそのままコンボボックスにぶっこむ雑な処理をしてるためです。
HistoryのEntryクラスを継承してtoStringをオーバーライドすればいいのかなと思ったら、Entryクラスがfinalでした;ここら辺はもう少し綺麗にしたいところ。

で、とりあえず選択イベントで履歴URLのページへ遷移するようになってます。

f:id:kikutaro777:20131016193843j:plain

コード

前回のをベースに以下のような感じです。

Chromeの実行はProcessBuilderでexeファイルを叩いてるだけ(^^;
履歴もWebEngineのHistoryにListChangeListenerをつけて履歴が変わるタイミングでコンボボックスの中身を入れ替えてるだけです。

package maki.makimakidownloader;

import com.github.axet.vget.VGet;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.collections.ListChangeListener;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.ComboBox;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebHistory.Entry;
import javafx.scene.web.WebView;

public class MakiMakiDownloaderController implements Initializable {

    private static final String DL_DIR = "D:\\movie\\horikita";
    
    private static final String CHROME_EXE = "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe";
    
    @FXML
    private WebView webView;
    
    @FXML
    private ComboBox historyComboBox;
    
    private WebEngine webEngine;
    
    /**
     * ダウンロードボタン押下時のイベント.
     * 
     * 動画をダウンロードして、Chromeでビューする。
     * 
     * @param event 
     */
    @FXML
    private void handleBtnDownloadAction(ActionEvent event) {     
        try {
            //動画のダウンロード
            URL downloadUrl = new URL(webEngine.getLocation());
            VGet vget = new VGet(downloadUrl, new File(DL_DIR));
            vget.download();

            //ダウンロードしたファイル(webm形式)をChromeで実行する
            ProcessBuilder processBuilder 
                    = new ProcessBuilder(CHROME_EXE, "\"" + vget.getTarget().getAbsoluteFile() +"\"");
            Process process = processBuilder.start();
            
            //実行結果の判定
            int ret = process.waitFor();
            if(ret == 0){
                System.out.println("正常終了しました。");
            }else{
                System.out.println("異常終了しました。コードは" + ret);
            }
        } catch (IOException | InterruptedException ex) {
            System.out.println(ex.getMessage());
        }
    }
    
    /**
     * コンボボックス選択時のイベント.
     * 
     * 選択された履歴のURLに遷移する。
     * 
     * @param event 
     */
    public void selectHistoryComboBox(ActionEvent event){
        if(historyComboBox.getValue() instanceof Entry){
            Entry selectedEntry = (Entry) historyComboBox.getValue();
            webEngine.load(selectedEntry.getUrl());
        }
    }
    
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        webEngine = webView.getEngine();
        
        //YouTubeのサイトを表示
        webEngine.load("http://www.youtube.com/?gl=JP&hl=ja");
        
        //サイト履歴が変わる度にコンボボックスの値を更新する
        webEngine.getHistory().getEntries().addListener(new ListChangeListener<Entry>(){

            @Override
            public void onChanged(ListChangeListener.Change<? extends Entry> change) {
                change.next();
                historyComboBox.getItems().clear();
                historyComboBox.getItems().addAll(webEngine.getHistory().getEntries());
            }
            
        });
    }
}

JavaFXおもしろいなぁ。

JavaFXでYouTubeのダウンローダ的なサンプルを作ってみる

今や便利なダウンロードツールが色々あるので、作る意味はあまりないのですが、JavaYouTube動画とか取るには…と探したらライブラリがあったので、JavaFXと合わせてみました(^^;

注意
ちなみにYouTubeの動画をダウンロードすること自体、本来は(自分の著作物を上げた場合以外は)いけないことですね;利用規約はこちら。「5. お客様によるサイト上のコンテンツの使用」の部分です。
http://www.youtube.com/static?template=terms&hl=ja&gl=JP

その他の参考
http://ihoudownload.chosakuken-kouza.com/q/q2.html

というわけで、今回のブログ、不適切だったら後で削除するかも…です。

ちなみにJavaYouTubeをダウンロードする、で調べたら海外にわんさか(^^;
自分が参考にしたのは

How to download videos from youtube on java?

でした。で、回答の1つに「vget」なるライブラリがあって簡単そうだったので使ってみました。

https://github.com/axet/vget

このライブラリの内部では他のライブラリを使っているようで、Maven使うのが楽そうです。

で、NetBeans7.3.1を使っていたのですが、MavenのメニューにJavaFXがない!とつぶやいたら@sk44_さんと@aoetkさんからNetBeans7.4から使えます、と教えて頂きました。
というわけで7.4RC1入れていたので(今はもうRC2出てますが)やってみたところ

f:id:kikutaro777:20131014234914j:plain

あった!やったー(^^)/

ということで、MavenJavaFXプロジェクト作りました。

このvgetというライブラリ、URLがわかればダウンロードできるので、JavaFXのWebView使ってURLを取るようにしただけの雑なサンプルです(^^;

起動するとYouTubeのトップを表示するようにして、検索して目的の動画へ。
自分の著作物であげたものがないので…一時的に堀北さんのCMを試してみました。

f:id:kikutaro777:20131014233457j:plain

ダウンロードボタンを押してしばらくするとwebm形式のファイルを取得。

f:id:kikutaro777:20131014234132j:plain

実行するとこんな感じ!取れてる!

f:id:kikutaro777:20131014234103j:plain

コードは超適当ですが、こんなんで動いてます。
ちなみにViewのFXMLはWebViewとVBox、Buttonだけです。

package maki.makimakidownloader;

import com.github.axet.vget.VGet;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;

public class MakiMakiDownloaderController implements Initializable {
    
    @FXML
    private WebView webView;
    
    private WebEngine webEngine;
    
    @FXML
    private void handleBtnDownloadAction(ActionEvent event) {
        try {
            URL downloadUrl = new URL(webEngine.getLocation());
            VGet vget = new VGet(downloadUrl, new File("D:\\movie\\horikita"));
            vget.download();
        } catch (MalformedURLException ex) {
            System.out.println(ex.getMessage());
        }
    }
    
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        webEngine = webView.getEngine();
        webEngine.load("http://www.youtube.com/?gl=JP&hl=ja");
    }    
}

真面目に作るなら欲しい機能として

  • ダウンロード中はプログレスバーを表示
  • 落とせない形式(があるっぽい)の場合にはメッセージダイアログを表示
  • 非同期で複数ダウンロードできるようにする

などなど(^^;他にもあるよなぁ。

先日のマキマキビューアも途中だけど、これも真面目に作ってみようかな。って個人で楽しむためのツールですが。

てか、最近JavaFXネタが増えつつある(^^;

Java EEは仕事でガッツリ開発入って今まで使ってないようなものを触らないと中々書くことがない今日この頃。もっとガッツリ開発したいなぁ。

StageStyleを指定してみる

昨日のブログ、軽い気持ちで書いたプログラムだったので、思ったより反応があってびっくりでした…(^^;

Java EEより反応いいんじゃ…

……

@skrbさんから


というコメントを頂いたので、早速試してみました(^^)

StageStyleとは?

その名の通り、Stageのスタイルに設定できる列挙型とのこと。

http://docs.oracle.com/javafx/2/api/javafx/stage/StageStyle.htmlf:id:kikutaro777:20131007191758j:plain

Applicationクラスを継承したMakiMakiImageViewerクラスはNetBeansの自動生成まかせのままで昨日のブログには載せていなかったのですが、以下のような感じで、1行追加しました。

package makimakiimageviewer;

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

public class MakiMakiImageViewer extends Application {
    
    @Override
    public void start(Stage stage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("MakiMakiImageView.fxml"));
        
        Scene scene = new Scene(root);
        
        stage.setScene(scene);
        
        //TRANSPARENTを指定してみる
        stage.initStyle(StageStyle.TRANSPARENT);
        
        stage.show();
    }

    /**
     * The main() method is ignored in correctly deployed JavaFX application.
     * main() serves only as fallback in case the application can not be
     * launched through deployment artifacts, e.g., in IDEs with limited FX
     * support. NetBeans ignores main().
     *
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }
}

結果

昨日の実行結果は以下でした。

f:id:kikutaro777:20131007192312j:plain

で、上記プログラムの実行結果は

f:id:kikutaro777:20131007192652j:plain

拡大してるとイマイチわかりませんね(^^;ひいてみます。

昨日のプログラム

f:id:kikutaro777:20131007193414j:plain

今日のプログラム

f:id:kikutaro777:20131007193438j:plain

画像だとわかりにくいですが、実際に動いてるものをみるとだいぶ印象が違います!!

ちなみに値を色々変えてみましたが

StageStyle.DECORATEDを指定した場合(昨日と同じ)

f:id:kikutaro777:20131007193710j:plain

StageStyle.UTILITYを指定した場合

f:id:kikutaro777:20131007193800j:plain
わかりにくいですが、右上の最小化・最大化ボタンが消えてます。

StageStyle.TRANSPARENTを指定した場合

f:id:kikutaro777:20131007193855j:plain

今回のサンプルではStageStyle.UNDECORATEDもこれと同じでした。

画像のエリア以外を透明に

縦画像の場合、こんな感じです。

f:id:kikutaro777:20131007194254j:plain

で、SceneにsetFill(null)を指定してみました。すっきり!

f:id:kikutaro777:20131007194330j:plain

Scene scene = new Scene(root);
scene.setFill(null);

たいしたプログラム書いていないのですが、結構それっぽいプログラムができて楽しい!
やばいです。JavaFX面白いw

堀北真希さん誕生日を祝ってJavaFXで画像ビューアを作ってみる

今日は堀北真希さん25歳の誕生日!

デビュー当時から堀北真希さんを応援してるのでかれこれ10年(>_<)

今日は写真集「Dramatic」の発売記念と合わせて、久々の握手会イベントがあったとのこと…残念ながら抽選外れましたが orz

今や飛ぶ鳥を落とす勢いな堀北さん、その可愛さのあまり、気が付けば自分のマシンに画像も溜まっているわけです…(別に仕事中に集めてるわけじゃないからねっ)

ということで、そういうフォルダを指定したら、その配下を走査して画像表示する簡易ビューアみたいなのをJavaFXで作ってみました(^^)

JavaFXやってみる

JavaFXをまともに触ったことなく、先日JJUGでハンズオンイベントが行われた際の資料を家でやったぐらいの私…(^^;(一応ブログ書いてた)

JavaFXハンズオンにお家でChallenge!

でもJavaOne2013の基調講演を生でみたら何か色々触ってみたい気持ちが強くなったので、やってみることに(^^)/

環境

せっかくなのでわりと新しい環境でやってみました。

OS:Windows 8 Professional
IDE:NetBeans7.4RC1
JDK:8 Early Access
Tool:SceneBuilder1.1

できたもの

先に動かしたプログラムの結果から(^^;

実行するとウィンドウが出てきて、堀北さんの写真が表示されます。

f:id:kikutaro777:20131006223559j:plain

かわいいですね(^^)

f:id:kikutaro777:20131006223604j:plain

少し薄くなってもかわいい(^^)

f:id:kikutaro777:20131006223609j:plain

待って、まだみていたい!

f:id:kikutaro777:20131006223614j:plain

あー消えてしまう…。

f:id:kikutaro777:20131006223727j:plain

けど次っ!

f:id:kikutaro777:20131006223741j:plain

と、5秒間、フェードアウトするように薄くなっていき、3秒停止して次の画像へ。が延々と繰り返されます。

それだけ(^^;

f:id:kikutaro777:20131006223749j:plain

昔の写真も

f:id:kikutaro777:20131006223753j:plain

かわいいですね(^^)笑

フォルダは以下のような感じで整理されてません(^^;

f:id:kikutaro777:20131006223921j:plain

コード

作る前に「こんなことやらねばー」というのを挙げたら

  • 画像表示
  • フォルダ配下にある画像を(再帰的に)走査
  • アニメーション

という感じでした。ざっくり仕様ですが。

で、ほとんど以下の@skrbさん記事に辿り着いて終わりました…(^^;なんと

で、とりあえず書いてみたのがこんな感じ。

package javafxsample;

import java.io.IOException;
import java.net.URL;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import javafx.animation.Animation;
import javafx.animation.FadeTransition;
import javafx.animation.PauseTransition;
import javafx.animation.SequentialTransition;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.util.Duration;

public class MakiMakiViewerController implements Initializable {
    
    /**
     * 画像表示エリア
     */
    @FXML
    private ImageView photo;
    
    /**
     * 画像パスのリスト
     */
    private List<String> imageList;
    
    /**
     * 連続アニメーション
     */
    private SequentialTransition transition;
    
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        
        //写真格納フォルダのトップを指定
        Path photoPathRoot = Paths.get("D:\\photo\\horikita");
        
        //画像を総なめしてパスをかき集める
        imageList = new ArrayList<>();
        FileVisitor<Path> visitor = new SimpleFileVisitor<Path>(){

            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                imageList.add(file.toUri().toString());
                return FileVisitResult.CONTINUE;
            }
        };
        
        try {
            Files.walkFileTree(photoPathRoot, visitor);
        } catch (IOException ex) {
            System.out.println("画像読み込みの途中でエラーが起きました。");
        }
        
        //繰り返すアニメーションを一旦リストする
        List<Animation> listAnime = new ArrayList<>();
        
        imageList.stream().forEach((imagePath) -> {
            photo.setImage(new Image(imagePath));
            
            //フェードアニメーション
            FadeTransition fade = new FadeTransition(Duration.millis(5000));
            fade.setFromValue(1.0);
            fade.setToValue(0.1);
            fade.setAutoReverse(true);
            fade.setCycleCount(1);
            fade.setNode(photo);
            
            //ポーズアニメーション 終了時に画像ファイル読む
            PauseTransition pause = new PauseTransition(Duration.millis(3000));
            pause.setOnFinished((ActionEvent t) -> {
                photo.setImage(new Image(imagePath));
            });
            listAnime.add(fade);
            listAnime.add(pause);
        });

        //上記フェードとポーズの連続アニメーションとする
        Animation[] arrAnime = new Animation[listAnime.size()];
        transition = new SequentialTransition(listAnime.toArray(arrAnime));
        
        //アニメーションを繰り返す
        transition.setCycleCount(Animation.INDEFINITE);
        
        //アニメーション実行
        transition.play();
    }    
    
}

画像ファイルの判定とかしないと…ですが、とりあえず(^^)

せっかくなので色々機能を付け加えていこうかな~と。

しばらくChallenge JavaFXになりそう…?

JavaFXハンズオンにお家でChallenge!

8/24(土)、JJUG(日本Javaユーザーグループ)によるハンズオン祭りが行われたようです。
Java EEJavaFXの2つのハンズオンが同時開催というものだったようですね。
http://www.java-users.jp/?p=618

残念ながら予定ありで参加できず…。

資料でるかなぁ、と思っていたら@skrbさんから以下、ハンズオン資料の公開がされていました!解説も詳細なので、お家で一人ハンズオンやってみました(^^)
(Java EEも出ていたので、後程やってみます)

私の環境はWindows7でNetBeans7.3でしたが、特に問題なく淡々と進んで…

できた!

前半の資料
「JavaFX で Hello, World!」
で、テキストに文字入れてボタン押すと、ラベルに(テキスト入力した文字列を連結して)表示するサンプル↓
f:id:kikutaro777:20130825090654j:plain

後半の資料
「テーブルと組み込みブラウザ」
で、上段のブックマークテーブルで選択したサイトを組込みブラウザで表示するサンプル↓
f:id:kikutaro777:20130825090707j:plain

ができました!

WebViewはWebKitベースとのことで色々遊べそう!

作ったサンプルをベースにBorderPaneのBottomに前半に使ったHBoxを置いて、その中にテキストとボタン増やしてブックマークの登録・削除できるようにしたりしてみたり。

f:id:kikutaro777:20130825112738j:plain

YouTube動画見て、気に入ったのを登録。

といっても実用するにはファイルに吐いたりしないとダメだけど(^^)

色々遊べそうww
本格的にChallenge JavaFXしてみようかな(^^;

にほんブログ村 IT技術ブログへ
にほんブログ村 にほんブログ村 IT技術ブログ Javaへ
にほんブログ村