ブログトップ 記事一覧 ログイン 無料ブログ開設

プログラムdeタマゴ

2013/02/07

JavaFXの練習2:Controllerとか

 というわけで、今回もJavaFXの練習した内容です。

 今回は以下のような感じのパネルを作ってみようとしております。

f:id:nodamushi:20130207170530p:image:w360


 画像と、ファイル名と、ファイルの説明を表示して、ボタンをクリックするとファイル名と説明部分がスライドアウトしたりスライドインしたりするようなものです。かっくいいね。このスライドイン、アウトをどうすればいいのかにえらい四苦八苦しました。。。

 今回はJava言語を利用する必要があるので、Eclipseでプロジェクトを作成します。先に空っぽのtest.cssと表示する画像のサンプルをプロジェクトフォルダに入れておきました。

f:id:nodamushi:20130207170520p:image


 JavaFXの開発をするにはjfrt.jarが必要ですので、jre/libの下にあるjfxrt.jarをビルドパスに追加しておきます。

f:id:nodamushi:20130207170521p:image:w360


 ビルダーを起動して、とりあえず空っぽのまま、fxmlをEclipseのプロジェクト上に保存しておきます。

f:id:nodamushi:20130207170535p:image:w360

f:id:nodamushi:20130207170522p:image



 さて、準備完了したので上の設計図の様に作れるように配置をしていきます。とりあえず、こんな感じになりました。

f:id:nodamushi:20130207170523p:image:w360


 AnchorPaneはスライドインしたり、スライドアウトしたりする為に利用しています。VBoxのAnchorPaneに対する制約は、上下右を全部0にしています。

f:id:nodamushi:20130207170524p:image 

 また、全てのノードの大きさを計算した結果の最適な大きさに指定しています。ていうか、なんでJavaFXはサイズに関する指定をCSSでできるようにしなかったのかね?

f:id:nodamushi:20130207170525p:image



 CSSを適応させる為に、各ノードのStyleClass名をこんな感じに設定しました。

f:id:nodamushi:20130207170526p:image:w360

 で、先に作っておいたtest.cssを読み込ませます。

f:id:nodamushi:20130207170529p:image

 さて、CSSを作っていきます。

 まずは背景は真っ黒で、文字列は白色なので、その設定。

.image_info_panel{
    -fx-background-color:black;
    -fx-padding:20px 0 20px 20px;
}

.image_info_panel .label{
    -fx-text-fill:white;
    -fx-font:14px "Arial",self;
}

 次に、文字列やボタンを予定通り下に配置する為にalignmentをbottom-leftにする。

.contents_info,.slidepanel{
    -fx-alignment:bottom-left;
    -fx-padding:0 5px 10px 5px;
}


 ボタンの色と、ボタンの上にマウスが乗ったときに色がほんのり変わるように設定。三角形が横を向くように-fx-rotateをCSSで90を指定しておくと、Java側でsetRotateをしても変化させることが出来なくなったので、コメントアウトしています。この辺JavaFXのCSSは使いにくい…。

.slidebutton{
    -fx-background-color:rgba(0,0,0,0);
    -fx-padding:0;
    -fx-text-fill:gray;
    /*-fx-rotate:-90;*/
}

.slidebutton:hover{
    -fx-text-fill:#608C71;
   -fx-effect:dropshadow( gaussian,#ff0 ,10px, 0, 0,0);
}


 微妙に装飾が寂しかったので、色々装飾。そのさい、-fx-font-style:italicを設定しても、全然斜体にならなかったんですけど、これなんでなんですかね。


/*画像のファイル名*/
.fname_info{
    -fx-padding:0 10px 10px 10px;

    /*font-styleで結果が変わらないんだけど、なんで?*/
    -fx-font-style:italic;
    

    /*仕方が無いので、書き直し*/
    -fx-font:italic 14px "Arial",self;
    -fx-effect:dropshadow( gaussian,#ff0 ,10px, 0, 0,0);
}

/*画像の説明*/
.exp_info{
    -fx-padding:0 10px 0 30px;
}

/*画像の内側にインナーシャドウ*/
.contents_img{
    -fx-effect:innershadow( gaussian, black, 20px , 0,10,0);
}


 はい、これでCSSの設定は終わりです。こんな感じのデザインになりました。

f:id:nodamushi:20130207170527p:image:w360

 お〜、当初の予定をだいぶいい感じに再現できましたね。後はJavaでこれらを操作できるようにControllerの設定をしてビルダーのお仕事は終了です。

f:id:nodamushi:20130207170528p:image

 Eclipseに戻ってきて、JavaFXを実行できるようにします。実はSceneが何なのか私よく理解してないんですが、とりあえず、これが定石らしいです。

import java.net.*;
import java.nio.file.*;
import javafx.application.*;
import javafx.fxml.*;
import javafx.scene.*;
import javafx.stage.*;

public class Main extends Application{
  public static void main(String[] args) {
    launch(args);
  }

  @Override
  public void start(Stage stage) throws Exception {
    Path fxmlfile = Paths.get("test.fxml");
    URL url = fxmlfile.toUri().toURL();
    
    Parent parent = (Parent)FXMLLoader.load(url);
    
    Scene scene = new Scene(parent);
    stage.setScene(scene);
    stage.show();
  }
}



 で、コントローラーの作成。infoboxとかsbuttonとかの値の設定やslideActionとかの呼び出しはリフレクションが使われる為、セキュリティの設定よっては、privateやprotectedにするとエラーになるらしい。というわけで、publicにしておいた。privateなどの場合は@FXMLアノテーションを付ける必要がある。

package test;

import javafx.event.*;
import javafx.fxml.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;

public class ImgInfoController{
  //これらの値は自動的にセットされる
  public AnchorPane infobox;
  public Button sbutton;
  
  public void slideAction(ActionEvent event){
    System.out.println("クリックされた!");
  }
}

実行結果

f:id:nodamushi:20130207170532p:image:w360



 予定通り、閉じたり開いたり出来るようにしたい。今回はいきなりアニメーションに行くのはしんどいので単純に閉じたり開いたりするだけを実装してみました。

private boolean isOpen=true;

public void slideAction(ActionEvent event){
  System.out.println("クリックされた!");
  
  if(isOpen){
    infobox.setMaxWidth(0);
    infobox.setMinWidth(0);
    sbutton.setRotate(90);
    isOpen=false;
  }else{
    infobox.setMaxWidth(Double.MAX_VALUE);
    sbutton.setRotate(-90);
    isOpen=true;
  }  
}

 で、やってみると………

f:id:nodamushi:20130207170533p:image:w360

 あるぅええええ?画像の上に文字が出てるんですけどー。とりあえず、CSSのoverflow:hiddenとか設定すればいいのかと思ったら、そんな項目ないし。で、色々悩んで、とりあえずclip設定すればいいんでね?とやってみた。

 clipの設定はオブジェクトが作られたときにやって欲しかったので、このクラスにInitializableを実装する。

import java.net.URL;
import java.util.ResourceBundle;
import javafx.scene.shape.Rectangle;
public class ImgInfoController implements Initializable{
  //オーバーしたのを隠すためのクリップ
  private Rectangle clip;
  
  @Override
  public void initialize(URL url, ResourceBundle resource) {
    clip = new Rectangle();
    infobox.setClip(clip);
    //clipの大きさをinfoboxの大きさに常に合わせる
    clip.widthProperty().bind(
        infobox.widthProperty());
    clip.heightProperty().bind(
        infobox.heightProperty());
    
    sbutton.setRotate(-90);
  }

 実行結果

f:id:nodamushi:20130207170534p:image:w360

 おぉ、消えた消えたヽ( ・∀・)ノ

 次はアニメーションに挑戦かー。まだやってないので、次がいつのかわかりません。

...... 2013/02/08 17:33 It's nice contents. Thank you (^_^)/

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/nodamushi/20130207/1360264166