setonaction - javafx toggle button image
JavaFX-crea un botón personalizado con imagen (3)
Solo necesitas crear tu propia clase heredada de tus padres. Coloque un ImageView sobre eso, y en los eventos de mousedown y mouse up simplemente cambie las imágenes de 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
}
}
Me gustaría crear un botón personalizado, que tenga dos estados presionados o no, como un botón para alternar. Tengo dos imágenes para hacer esto (presionadas y no presionadas), entonces, ¿cómo puedo crear el botón y mostrarlo con mis imágenes? El botón debe tomar el tamaño de la imagen.
No estoy usando FXML. Gracias por ayudar.
Hay algunas formas diferentes de lograr esto, describiré mis favoritos.
Use un ToggleButton y apliquele un estilo personalizado. Sugiero esto porque su control requerido es "como un botón para alternar", pero se ve diferente del estilo del botón de alternar predeterminado.
Mi método preferido es definir un gráfico para el botón en 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'');
}
O utilice el CSS adjunto para definir una imagen de fondo.
// 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'');
}
Prefiero la especificación gráfica -fx sobre las especificaciones -fx-background- * ya que las reglas para el diseño de imágenes de fondo son complicadas y establecer el fondo no ajusta automáticamente el tamaño del botón a la imagen, mientras que el ajuste sí lo hace.
Y algunos ejemplos de código:
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();
}
}
Algunas de las ventajas de hacer esto son:
- Obtiene el comportamiento predeterminado del botón de alternar y no tiene que volver a implementarlo usted mismo agregando su propio estilo de enfoque, mouse y manejadores de teclas, etc.
- Si su aplicación se transfiere a una plataforma diferente, como un dispositivo móvil, funcionará de manera inmediata para responder a eventos táctiles en lugar de eventos de mouse, etc.
- Su estilo está separado de la lógica de su aplicación por lo que es más fácil cambiar el estilo de su aplicación.
Una alternativa es no usar css y seguir usando un ToggleButton, pero configure el gráfico de la imagen en código:
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();
}
}
El enfoque basado en código tiene la ventaja de que no tiene que usar css si no está familiarizado con él.
Para obtener el mejor rendimiento y la facilidad de portar a entornos de aplicaciones sin firmar y de inicio de webstart, agrupe las imágenes con su aplicación y haga referencia a ellas mediante direcciones de ruta relativas en lugar de descargarlas de la red.
Una combinación de las 2 respuestas anteriores hizo el truco. Gracias. Una nueva clase que hereda de Button. Nota: se debe llamar a updateImages () antes de mostrar el botón.
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);
}
}