2012-05-09 12 views
15

トグルボタンのように、2つの状態が押されているかどうかを示すカスタムボタンを作成したいとします。私はこれを行うための2つの画像を持っています(押されていない)ので、どのようにボタンを作成して画像で表示できますか?ボタンは画像のサイズをとる必要があります。
私はFXMLを使用していません。 ありがとうございます。JavaFX - イメージ付きのカスタムボタンを作成する

答えて

40

これを行うにはいくつかの方法がありますが、私はお気に入りを概説します。

ToggleButtonを使用してカスタムスタイルを適用します。これは、必要なコントロールが「トグルボタンと似ています」が、デフォルトのトグルボタンのスタイリングとは違っているためです。

.toggle-button { 
    -fx-graphic: url('http://icons.iconarchive.com/icons/aha-soft/desktop-buffet/128/Pizza-icon.png'); 
} 

.toggle-button:selected { 
    -fx-graphic: url('http://icons.iconarchive.com/icons/aha-soft/desktop-buffet/128/Piece-of-cake-icon.png'); 
} 

や背景画像を定義するために取り付けられたCSSを使用:

私の好ましい方法は、CSSのボタンのグラフィックを定義することです。

// file imagetogglebutton.css deployed in the same package as ToggleButtonImage.class 
.toggle-button { 
    -fx-background-image: url('http://icons.iconarchive.com/icons/aha-soft/desktop-buffet/128/Pizza-icon.png'); 
    -fx-background-repeat: no-repeat; 
    -fx-background-position: center; 
} 

.toggle-button:selected { 
    -fx-background-image: url('http://icons.iconarchive.com/icons/aha-soft/desktop-buffet/128/Piece-of-cake-icon.png'); 
} 

私はトリッキーで、背景を設定すると、自動的に設定する一方で、画像へのボタンのサイズをしないスタイリング背景画像のためのルールとして-fx-バックグラウンド*仕様オーバー-fx-グラフィック仕様を好みますグラフィックはしません。

そして、いくつかのサンプルコード:これを行うの

import javafx.application.Application; 
import javafx.scene.*; 
import javafx.scene.control.ToggleButton; 
import javafx.scene.layout.StackPaneBuilder; 
import javafx.stage.Stage; 

public class ToggleButtonImage extends Application { 
    public static void main(String[] args) throws Exception { launch(args); } 
    @Override public void start(final Stage stage) throws Exception { 
    final ToggleButton toggle = new ToggleButton(); 
    toggle.getStylesheets().add(this.getClass().getResource(
     "imagetogglebutton.css" 
    ).toExternalForm()); 
    toggle.setMinSize(148, 148); toggle.setMaxSize(148, 148); 
    stage.setScene(new Scene(
     StackPaneBuilder.create() 
     .children(toggle) 
     .style("-fx-padding:10; -fx-background-color: cornsilk;") 
     .build() 
    )); 
    stage.show(); 
    } 
} 

いくつかの利点があります:

  1. あなたは、デフォルトのトグルボタンの動作を取得し、あなたを追加することによって、自分自身を再実装もする必要はありません
  2. あなたのアプリがモバイルデバイスなどの異なるプラットフォームに移植された場合、マウスイベントなどではなくタッチイベントに応答してすぐに機能します。
  3. スタイリングはアプリケーションロジックと分離されているため、アプリケーションのスタイルを変更する方が簡単です。

代替は、CSSを使用して、まだトグルボタンを使用していますが、コード内の画像グラフィックを設定しないことです。

import javafx.application.Application; 
import javafx.beans.binding.Bindings; 
import javafx.scene.*; 
import javafx.scene.control.ToggleButton; 
import javafx.scene.image.*; 
import javafx.scene.layout.StackPaneBuilder; 
import javafx.stage.Stage; 

public class ToggleButtonImageViaGraphic extends Application { 
    public static void main(String[] args) throws Exception { launch(args); } 
    @Override public void start(final Stage stage) throws Exception { 
    final ToggleButton toggle  = new ToggleButton(); 
    final Image  unselected = new Image(
     "http://icons.iconarchive.com/icons/aha-soft/desktop-buffet/128/Pizza-icon.png" 
    ); 
    final Image  selected = new Image(
     "http://icons.iconarchive.com/icons/aha-soft/desktop-buffet/128/Piece-of-cake-icon.png" 
    ); 
    final ImageView toggleImage = new ImageView(); 
    toggle.setGraphic(toggleImage); 
    toggleImage.imageProperty().bind(Bindings 
     .when(toggle.selectedProperty()) 
     .then(selected) 
     .otherwise(unselected) 
    ); 

    stage.setScene(new Scene(
     StackPaneBuilder.create() 
     .children(toggle) 
     .style("-fx-padding:10; -fx-background-color: cornsilk;") 
     .build() 
    )); 
    stage.show(); 
    } 
} 

コードベースのアプローチでは、CSSを使用する必要がないという利点を持っていますあなたがそれに似ていないならば。

最高のパフォーマンスと、署名のないアプレットやWebstartサンドボックスへの移植が容易になるように、画像をアプリケーションにバンドルし、ネットからダウンロードするのではなく、相対パスのURLで参照してください。

+0

うわー!何と言えばいい ?それは本当に素晴らしい答えです、ありがとうございます。私は最初のソリューションに行くと思う、私はコード内のボタンにサイズを適用する、それはSwingとは異なりJavaFXアプリケーションでは一般的なようだ。 – jerome

+1

-fx-background-color:transparentを追加しなければならなかった。私のイメージにはボタンだけが埋め込まれています。 – jerome

+0

これは良い答えですが、JavaFXの弱点を示しています。この種の要求は、21世紀には乱雑で不当である。 –

6

親から継承した独自のクラスを作成するだけで済みます。 ImageViewをその上に配置し、マウスダウンイベントではImageViewの画像を変更するだけです。

public class ImageButton extends Parent { 

    private static final Image NORMAL_IMAGE = ...; 
    private static final Image PRESSED_IMAGE = ...; 

    private final ImageView iv; 

    public ImageButton() { 
     this.iv = new ImageView(NORMAL_IMAGE); 
     this.getChildren().add(this.iv); 

     this.iv.setOnMousePressed(new EventHandler<MouseEvent>() { 

      public void handle(MouseEvent evt) { 
       iv.setImage(PRESSED_IMAGE); 
      } 

     }); 

     // TODO other event handlers like mouse up 

    } 

} 
+0

これは素晴らしいスタートです。 – jerome

2

前の2つの回答の組み合わせがこのトリックでした。ありがとう。 Buttonから継承する新しいクラスです。注:ボタンを表示する前にupdateImages()を呼び出す必要があります。

import javafx.event.EventHandler; 
import javafx.scene.control.Button; 
import javafx.scene.image.Image; 
import javafx.scene.image.ImageView; 
import javafx.scene.input.MouseEvent; 

public class ImageButton extends Button { 

    public void updateImages(final Image selected, final Image unselected) { 
     final ImageView iv = new ImageView(selected); 
     this.getChildren().add(iv); 

     iv.setOnMousePressed(new EventHandler<MouseEvent>() { 
      public void handle(MouseEvent evt) { 
       iv.setImage(unselected); 
      } 
     }); 
     iv.setOnMouseReleased(new EventHandler<MouseEvent>() { 
      public void handle(MouseEvent evt) { 
       iv.setImage(selected); 
      } 
     }); 

     super.setGraphic(iv); 
    } 
} 
関連する問題