我想创建一个自定义按钮,它有两种状态是否按下,比如切换按钮。我有两个图像可以做到这一点(按下和未按下),那么我如何创建按钮并用我的图像显示它?按钮必须采用图像的大小。
我没有使用 FXML。感谢您的帮助。
问问题
127082 次
3 回答
52
有几种不同的方法可以做到这一点,我将概述我的最爱。
使用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-graphic 规范而不是 -fx-background-* 规范,因为设置背景图像样式的规则很棘手,并且设置背景不会自动将按钮调整为图像大小,而设置图形则可以。
还有一些示例代码:
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();
}
}
这样做的一些优点是:
- 您可以获得默认的切换按钮行为,并且不必通过添加自己的焦点样式、鼠标和键处理程序等来自己重新实现它。
- 如果您的应用程序被移植到不同的平台,例如移动设备,它将开箱即用地响应触摸事件而不是鼠标事件等。
- 您的样式与您的应用程序逻辑分离,因此更容易重新设计您的应用程序。
另一种方法是不使用 css 并仍然使用 ToggleButton,但在代码中设置图像图形:
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 引用它们,而不是从网上下载它们。
于 2012-05-09T19:38:31.177 回答
7
您只需要创建自己的从父类继承的类。在其上放置一个 ImageView,在 mousedown 和 mouse up 事件上只需更改 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
}
}
于 2012-05-09T15:12:56.343 回答
4
前两个答案的组合起到了作用。谢谢。继承自 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);
}
}
于 2015-08-16T11:40:40.997 回答