2012-05-09 30 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); 
    } 
}