Elementos gráficos – Botones
Al igual que pasaba en Swing, los botones representan uno de los componentes más utilizados a la hora de realizar interfaces gráficas con javafx. Las posibilidades se resumen en los 5 principales tipos: button, radiobutton, togglebutton, checkbox. La mayoría de características y métodos que se pueden utilizar en estos componentes son comunes
Button
Para poder personalizar el aspecto de un botón se utiliza el método setGraphics, al cual se le pasa un imageview con la imagen correspondiente
1 2 |
javafx.scene.image.Image imagenOk = new Image(getClass().getResourceAsStream("recursos/ok.png")); botonEfecto.setGraphic(new ImageView(imagenOk)); |
Del mismo modo si se le quiere añadir un evento de sombra al botón se realizará mediante el método setEffect(), pasando un objeto de tipo effect
1 2 3 4 5 6 7 8 9 10 11 12 13 |
DropShadow sombra = new DropShadow(); botonEfecto.addEventHandler(MouseEvent.MOUSE_ENTERED, new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent event) { botonEfecto.setEffect(sombra); } }); botonEfecto.addEventHandler(MouseEvent.MOUSE_EXITED, new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent event) { botonEfecto.setEffect(null); } }); |
La gestión de eventos de un button se realiza mediante el método setOnAction, el cual serie un objeto de tipo EventHandler de tipo Action
1 2 3 4 5 6 |
botonNormal.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { System.out.println("Botón pulsado"); } }); |
Adicionalmente (como ya se ha visto en el ejemplo del la sombra), también se podrá controlar cualquier tipo de evento mediante un EventHandler, identificando el tipo de evento que se quiere controlar.
1 2 3 4 5 6 7 8 9 10 11 12 |
botonEfecto.addEventHandler(MouseEvent.MOUSE_ENTERED, new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent event) { botonEfecto.setEffect(sombra); } }); botonEfecto.addEventHandler(MouseEvent.MOUSE_EXITED, new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent event) { botonEfecto.setEffect(null); } }); |
Existen multitud de métodos que se pueden utilizar, pero propios del componente button caben destacar los que manejan las opciones por defecto.
1 2 3 4 |
// asignaría el botón aceptar por defecto al iniciar la interfaz botonNormal.setDefaultButton(true); // asignaría el botón cancelar por defecto al iniciar la interfaz botonNormal.setCancelButton(true); |
RadioButton
Un radiobutton es un elemento muy similar al caso anterior, con la diferencia que el tratamiento de la selección se realiza de forma diferente. En este caso el botón podrá estar seleccionado o deseleccionado, evaluado la propiedad mediante el método isSelected(). Para poder evaluar el cambio de esta propiedad se utilizará un listener de propiedad.
1 2 3 4 5 6 7 8 9 10 |
radioImagen.selectedProperty().addListener(new ChangeListener<Boolean>() { @Override public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) { if (newValue) { radioImagen.setGraphic(new ImageView(imagenSeleccionado)); } else { radioImagen.setGraphic(new ImageView(imagenDeseleccionado)); } } }); |
Adicionalmente se podrán crear grupos de radiobuttons donde tan solo uno de los elementos del grupo podrá estar seleccionado. De la misma forma se podrá evaluar cual de los elementos del grupo es el que está seleccionado
1 2 3 4 5 6 7 8 9 10 |
ToggleGroup grupoRadios = new ToggleGroup(); grupoRadios.getToggles().addAll(radioGrupo1, radioGrupo2); radioGrupo1.setUserData("Radio 1"); radioGrupo2.setUserData("Radio 2"); grupoRadios.selectedToggleProperty().addListener(new ChangeListener<Toggle>() { @Override public void changed(ObservableValue<? extends Toggle> observable, Toggle oldValue, Toggle newValue) { System.out.println("El radio seleccionado es el " + newValue.getUserData().toString()); } }); |
Dentro del código el método serUserData() asocia un objeto al componente correspondiente, pudiendo ser un objeto primitivo o complejo
ToggleButton
Caso muy similar al anterior, con la diferencia del aspecto gráfico. El resto de propiedades y evaluación de las mismas es igual
1 2 3 4 5 6 7 8 9 10 11 12 |
toggleNormal.isSelected(); toggleNormal.selectedProperty().addListener(new ChangeListener<Boolean>() { @Override public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) { if (newValue){ System.out.println("El toggle está activado"); } else System.out.println("El toggle está desactivado"); } }); |
Al igual que en el caso anterior también se puede crear un grupo de botones donde tan solo uno puede estar seleccionado
CheckBox
Comportamiento similar al anterior, siendo característico de casillas de verificación.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
javafx.scene.image.Image imagenOn = new Image(getClass().getResourceAsStream("recursos/togOn.png")); javafx.scene.image.Image imagenOff = new Image(getClass().getResourceAsStream("recursos/togOff.png")); checkNormal.setGraphic(new ImageView(imagenOff)); checkNormal.selectedProperty().addListener(new ChangeListener<Boolean>() { @Override public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) { if (newValue){ checkNormal.setGraphic(new ImageView(imagenOn)); } else checkNormal.setGraphic(new ImageView(imagenOff)); } }); |
En el caso de ToggleButton y RadioButton su aspecto gráfico no es posible cambiarlo mediante código, teniendo que hacerlo por CSS
Los códigos utilizados para este ejemplo son:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
<?xml version="1.0" encoding="UTF-8"?> <?import javafx.geometry.*?> <?import javafx.scene.control.*?> <?import java.lang.*?> <?import javafx.scene.layout.*?> <GridPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fundamentos.Controller"> <columnConstraints> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" /> </columnConstraints> <rowConstraints> <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> </rowConstraints> <children> <Label text="Button" GridPane.halignment="LEFT"> <GridPane.margin> <Insets left="20.0" /> </GridPane.margin> </Label> <Label text="Radio Button" GridPane.halignment="LEFT" GridPane.rowIndex="1"> <GridPane.margin> <Insets left="20.0" /> </GridPane.margin> </Label> <Label text="Checkbox" GridPane.halignment="LEFT" GridPane.rowIndex="3"> <GridPane.margin> <Insets left="20.0" /> </GridPane.margin> </Label> <Label text="Toggle Button" GridPane.halignment="LEFT" GridPane.rowIndex="2"> <GridPane.margin> <Insets left="20.0" /> </GridPane.margin> </Label> <HBox alignment="CENTER_LEFT" prefHeight="100.0" prefWidth="200.0" spacing="10.0" GridPane.columnIndex="1" GridPane.halignment="LEFT" GridPane.valignment="CENTER"> <children> <Button fx:id="botonNormal" alignment="CENTER" mnemonicParsing="false" text="Normal" /> <Button fx:id="botonEfecto" mnemonicParsing="false" /> <Button fx:id="botonImagen" mnemonicParsing="false" /> </children> </HBox> <HBox alignment="CENTER_LEFT" prefHeight="100.0" prefWidth="200.0" spacing="10.0" GridPane.columnIndex="1" GridPane.rowIndex="1"> <children> <RadioButton fx:id="radioNormal" mnemonicParsing="false" text="Op1" /> <RadioButton fx:id="radioImagen" mnemonicParsing="false" text="Op2" /> <RadioButton fx:id="radioGrupo1" mnemonicParsing="false" text="Gr1" /> <RadioButton fx:id="radioGrupo2" mnemonicParsing="false" text="Gr2" /> </children> </HBox> <HBox alignment="CENTER_LEFT" prefHeight="100.0" prefWidth="200.0" spacing="10.0" GridPane.columnIndex="1" GridPane.rowIndex="2"> <children> <ToggleButton fx:id="toggleNormal" mnemonicParsing="false" text="Toggle" /> </children> </HBox> <HBox alignment="CENTER_LEFT" prefHeight="100.0" prefWidth="200.0" spacing="10.0" GridPane.columnIndex="1" GridPane.rowIndex="3"> <children> <CheckBox fx:id="checkNormal" mnemonicParsing="false" text="CheckBox" /> </children> </HBox> </children> </GridPane> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
package fundamentos; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.*; import javafx.scene.effect.DropShadow; import javafx.scene.image.*; import javafx.scene.image.Image; import javafx.scene.input.MouseEvent; import javafx.scene.layout.Background; import java.net.URL; import java.util.ResourceBundle; public class Controller implements Initializable { @FXML Button botonNormal; @FXML Button botonImagen; @FXML Button botonEfecto; @FXML RadioButton radioNormal; @FXML RadioButton radioImagen; @FXML RadioButton radioGrupo1; @FXML RadioButton radioGrupo2; @FXML Toggle toggleNormal; @FXML CheckBox checkNormal; @Override public void initialize(URL location, ResourceBundle resources) { configuracionBotones(); configuracionRadios(); configuracioToggle(); configuracionCheck(); } private void configuracionBotones() { javafx.scene.image.Image imagenOk = new Image(getClass().getResourceAsStream("recursos/ok.png")); javafx.scene.image.Image imagenCancel = new Image(getClass().getResourceAsStream("recursos/cancel.png")); botonNormal.setText("Normal"); botonNormal.setDefaultButton(true); botonNormal.setCancelButton(true); botonNormal.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { System.out.println("Botón pulsado"); } }); DropShadow sombra = new DropShadow(); botonEfecto.setGraphic(new ImageView(imagenOk)); botonEfecto.setBorder(null); botonEfecto.setBackground(Background.EMPTY); botonEfecto.addEventHandler(MouseEvent.MOUSE_ENTERED, new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent event) { botonEfecto.setEffect(sombra); } }); botonEfecto.addEventHandler(MouseEvent.MOUSE_EXITED, new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent event) { botonEfecto.setEffect(null); } }); botonImagen.setGraphic(new ImageView(imagenCancel)); botonImagen.setBorder(null); botonImagen.setBackground(Background.EMPTY); botonImagen.setDefaultButton(true); botonImagen.addEventHandler(MouseEvent.MOUSE_ENTERED, new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent event) { botonImagen.setEffect(sombra); } }); botonImagen.addEventHandler(MouseEvent.MOUSE_EXITED, new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent event) { botonImagen.setEffect(null); } }); } private void configuracionRadios() { javafx.scene.image.Image imagenDeseleccionado = new Image(getClass().getResourceAsStream("recursos/unselected.png")); javafx.scene.image.Image imagenSeleccionado = new Image(getClass().getResourceAsStream("recursos/selected.png")); javafx.scene.image.Image imagenSobre = new Image(getClass().getResourceAsStream("recursos/over.png")); radioImagen.setGraphic(new ImageView(imagenDeseleccionado)); radioNormal.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { System.out.println("Radio pulsado"); } }); radioImagen.addEventHandler(MouseEvent.MOUSE_ENTERED, new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent event) { if (!radioImagen.isSelected()) { radioImagen.setGraphic(new ImageView(imagenSobre)); } } }); radioImagen.addEventHandler(MouseEvent.MOUSE_EXITED, new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent event) { if (!radioImagen.isSelected()) { radioImagen.setGraphic(new ImageView(imagenDeseleccionado)); } } }); radioImagen.selectedProperty().addListener(new ChangeListener<Boolean>() { @Override public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) { if (newValue) { radioImagen.setGraphic(new ImageView(imagenSeleccionado)); } else { radioImagen.setGraphic(new ImageView(imagenDeseleccionado)); } } }); ToggleGroup grupoRadios = new ToggleGroup(); grupoRadios.getToggles().addAll(radioGrupo1, radioGrupo2); radioGrupo1.setUserData("Radio 1"); radioGrupo2.setUserData("Radio 2"); grupoRadios.selectedToggleProperty().addListener(new ChangeListener<Toggle>() { @Override public void changed(ObservableValue<? extends Toggle> observable, Toggle oldValue, Toggle newValue) { System.out.println("El radio seleccionado es el " + newValue.getUserData().toString()); } }); } private void configuracioToggle() { toggleNormal.isSelected(); toggleNormal.selectedProperty().addListener(new ChangeListener<Boolean>() { @Override public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) { if (newValue){ System.out.println("El toggle está activado"); } else System.out.println("El toggle está desactivado"); } }); } private void configuracionCheck() { javafx.scene.image.Image imagenOn = new Image(getClass().getResourceAsStream("recursos/togOn.png")); javafx.scene.image.Image imagenOff = new Image(getClass().getResourceAsStream("recursos/togOff.png")); checkNormal.setGraphic(new ImageView(imagenOff)); checkNormal.selectedProperty().addListener(new ChangeListener<Boolean>() { @Override public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) { if (newValue){ checkNormal.setGraphic(new ImageView(imagenOn)); } else checkNormal.setGraphic(new ImageView(imagenOff)); } }); } } |