2012-05-09 32 views
15

我想創建一個自定義按鈕,有兩個狀態按下或不按鈕,如切換按鈕。我有兩個圖像來做到這一點(按下而不是按下),所以我如何創建按鈕並顯示它與我的圖像?該按鈕必須取得圖像的大小。
我沒有使用FXML。 謝謝你的幫助。JavaFX - 創建自定義按鈕與圖像

回答

40

有幾種不同的方法可以實現這一點,我將概述我的最愛。使用ToggleButton並對其應用自定義樣式。我建議這樣做是因爲你需要的控件「像一個切換按鈕」,但看起來與默認的切換按鈕樣式不同。

我的優選的方法是在CSS定義爲按鈕的圖形:

.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來定義的背景圖像。

// 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優勢如果你不喜歡它。

爲了獲得最佳性能並且易於移植到未簽名的applet和webstart沙箱,請將圖像與您的應用捆綁在一起,並通過相對路徑URL引用它們,而不是從網上下載它們。

+0

哇!我能說什麼?這是一個非常好的答案,非常感謝。我想我會選擇第一種解決方案,我會將代碼的大小應用到我的按鈕中,這似乎與Swing不同,它在JavaFX應用程序中很常見。 – jerome

+1

我不得不添加-fx-background-color:transparent;在CSS只有我的按鈕充滿了我的形象。 – jerome

+0

這是一個很好的答案,但在JavaFX中表現出一個弱點。這種要求在21世紀是混亂和不必要的。 –

6

你只需要創建自己的父類繼承的類。 放置一個ImageView,並在mousedown和鼠標向上事件只是改變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); 
    } 
}