Javafx button event needs double clicking - java

I have a javafx scene with several buttons within. The only way that the events of the button will be activated is by double cliking. In fxml the button is using the following action method onAction="#Button1Action". How can I change the functionality of the button1Action event from double click to just one click?
The function onAction:
#FXML
private void Button1Action(ActionEvent event) {
}
and the fxml code:
<Button id="button1" fx:id="button1" maxHeight="1.79.." maxWidth="1.79.." mnemonicParsing="false" onAction="#Button1Action" text="Answer" GridPane.columnIndex="3" GridPane.columnSpan="3" GridPane.halignment="CENTER" GridPane.rowIndex="7" GridPane.valignment="CENTER">
<GridPane.margin>
<Insets bottom="30.0" left="30.0" right="30.0" top="30.0" />
</GridPane.margin>
</Button>

You did not posted the body of Button1Action, but most probably it is looking like:
#FXML
private void Button1Action(ActionEvent event) {
button1.setOnAction(e -> System.out.println("Button clicked"));
}
What happens here, that you assign the listener inside the listener, so the actual listener body will be executed on the second click.
Trivial fix is:
#FXML
private void Button1Action(ActionEvent event) {
System.out.println("Button clicked");
}

Related

Button EventHandler in Controller class is not working [duplicate]

This question already has an answer here:
Handle event on disabled Node
(1 answer)
Closed 4 years ago.
Hello I have two problems.
First one:
When I start my app, I can press my ToggleButton with spacebar.
Second one:
(Even without ToggleButton) My EventHandler on my button is not working, on pressing spacebar nothing is going on.
Main class:
public class Main extends Application {
#Override
public void start(Stage stage) throws IOException {
Parent parent = (Parent) FXMLLoader.load(getClass().getResource("/application/MainView.fxml"));
Scene scene = new Scene(parent);
scene.getRoot().setFocusTraversable(true);
stage.setScene(scene);
stage.setTitle("Login Page");
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Fxml file:
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="501.0" prefWidth="597.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.MainController">
<children>
<Button fx:id="button" layoutX="136.0" layoutY="184.0" mnemonicParsing="false" prefHeight="133.0" prefWidth="127.0" text="Button" />
<Label fx:id="label" layoutX="199.0" layoutY="106.0" prefHeight="61.0" prefWidth="198.0" text="Label" />
<ToggleButton fx:id="toggleButton" layoutX="318.0" layoutY="186.0" mnemonicParsing="false" prefHeight="133.0" prefWidth="127.0" text="ToggleButton" />
</children>
</AnchorPane>
Controller class:
public class MainController implements Initializable {
#FXML
private Button button;
#FXML
private Label label;
#FXML
private ToggleButton toggleButton;
#Override
public void initialize(URL arg0, ResourceBundle arg1) {
button.setDisable(true);
button.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
if (event.getCode() == KeyCode.SPACE) {
System.out.println("space pressed");
button.setDisable(false);
}
}
});
button.addEventFilter(KeyEvent.KEY_RELEASED, new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
if (event.getCode() == KeyCode.SPACE) {
System.out.println("space pressed");
button.setDisable(true);
}
}
});
}
}
At first as #c0der mentioned you hasn't been assined event handler
as the button is disabled via button.setDisabled(true) so it can't receive any events such as mouse and key events see that javafx doc
Edit with some search i found another similar question in stackoverflow

Getting NullPointerException when button is clicked (JavaFX and FXML) [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
What's the difference between fx:id and id: in JavaFX?
(4 answers)
Closed 5 years ago.
After finally getting the gui to run without problems whenever i click on a designated button the IDE (Eclipse) putting out a long massage with this error in its end.
Caused by: java.lang.NullPointerException
at ui.IOTabController.handleSourceFolderPathSubmit(IOTabController.java:32)
... 62 more
Here is the IOTab.fxml (relevent part):
<AnchorPane fx:id="IOTab" minHeight="0.0" minWidth="0.0"
prefHeight="282.0" prefWidth="676.0" xmlns="http://javafx.com/javafx/9"
xmlns:fx="http://javafx.com/fxml/1" fx:controller="ui.IOTabController">
<children>
<Pane layoutX="12.0" layoutY="50.0" prefHeight="37.0" prefWidth="625.0">
<children>
<TextField id="sourceFolderFullPath" layoutX="167.0" layoutY="1.0" prefHeight="26.0"
prefWidth="391.0"/>
<Button id="sourceFolderPathSubmit" layoutX="567.0" mnemonicParsing="false" text="Enter"
onAction="#handleSourceFolderPathSubmit"/>
<Text layoutY="18.0" strokeType="OUTSIDE" strokeWidth="0.0"
text="Source folder's full path:" />
</children>
</Pane>
...
</AnchorPane>
Its controller IOTabController.java:
public class IOTabController implements Initializable{ // IOTab.fxml controller
#FXML private MainController Main;
// variables from fxml file to inject.
#FXML private AnchorPane IOTab;
#FXML private TextField sourceFolderFullPath;
#FXML private Button sourceFolderPathSubmit;
#FXML private TextField csvFileName;
#FXML private Button csvFileNameSubmit;
#FXML private Button deleteExistingData;
#FXML private Button convertCsvToKml;
#FXML
protected void handleSourceFolderPathSubmit(ActionEvent event) { // handles path submit.
if (sourceFolderFullPath.getText().isEmpty()) { // if empty field
AlertHelper.showAlert(Alert.AlertType.ERROR, "Form Error!", "Please enter path.");
return;
}
AlertHelper.showAlert(Alert.AlertType.CONFIRMATION, "SUCCESS","Path inserted.");
}
// class for creating alerts.
public static class AlertHelper {
public static void showAlert(Alert.AlertType alertType, String title, String message) {
Alert alert = new Alert(alertType);
alert.setTitle(title);
alert.setHeaderText(null);
alert.setContentText(message);
alert.showAndWait();
}
}
#Override
public void initialize(URL arg0, ResourceBundle arg1) {
// TODO Auto-generated method stub
}
}
The main controller:
public class MainController { // main.fxml controller.
#FXML private IOTabController IOTabController;
#FXML public void initialize() {
System.out.println("Application started");
IOTabController.initialize(null, null);
}
}
The gui is running fine until I click on "sourceFolderPathSubmit" button which pops the warning above every click (no matter if i put text in the TextField or not). I cant seem to find what to add or remove to make the button work.

javafx keytyped event not working

I have a JAVAFX editable combobox on which key typed and key pressed events are not firing while key released event is firing. However, If I change the combobox to textfield, it works.
FXML:
<ComboBox fx:id="combo_box" editable="true" layoutX="311.0" layoutY="194.0" prefHeight="26.0" prefWidth="300.0" promptText="Enter your name" onKeyTyped="#keyAction" />
FXMLController:
public void keyAction(KeyEvent event)
{
System.out.println("Works");
}
Help?
I found something which works. You can use the "getEditor" method of the combobox, to get the KEY_TYPED event works. Put this code in your controller :
this.combo_box.getEditor().setOnKeyTyped((KeyEvent e) -> {
System.out.println("Works");
});
Hope it helps

javafx 8 order children in custom control

I'm writing a custom control which displays an error icon and a message in a tooltip if the validation in a form fails. My version without the custom control looks like this:
<HBox>
<TextField fx:id="name"></TextField>
<Label fx:id="error" focusTraversable="false" visible="false">
<graphic>
<ImageView fitHeight="24.0" fitWidth="24.0" pickOnBounds="true" preserveRatio="true"/>
</graphic>
<tooltip>
<Tooltip fx:id="errorTooltip"/>
</tooltip>
</Label>
</HBox>
The result is this:
My efforts to create a custom control lead to this:
<fx:root type="javafx.scene.layout.HBox" xmlns:fx="http://javafx.com/fxml">
<children/>
<Label fx:id="error" focusTraversable="false" visible="false">
<graphic>
<ImageView fitHeight="24.0" fitWidth="24.0" pickOnBounds="true" preserveRatio="true"/>
</graphic>
<tooltip>
<Tooltip fx:id="errorToolTip"/>
</tooltip>
</Label>
</fx:root>
This is the code behind the fxml:
package control;
[imports omitted for brevity]
#DefaultProperty(value = "children")
public final class ValidatedControl extends HBox implements Initializable {
#FXML
private Label error;
#FXML
private Tooltip errorToolTip;
private StringProperty errorToolTipProperty;
public ValidatedControl() {
final FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("ValidatedControl.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
}
public void setErrorToolTip(final String errorToolTip) {
this.getErrorToolTipProperty().setValue(errorToolTip);
}
public String getErrorToolTip() {
return this.getErrorToolTipProperty().getValueSafe();
}
#Override
public void initialize(final URL location, final ResourceBundle resources) {
this.errorToolTip.textProperty().bind(this.getErrorToolTipProperty());
this.error.visibleProperty().bind(this.getErrorToolTipProperty().isNotEmpty());
}
public StringProperty getErrorToolTipProperty() {
if (this.errorToolTipProperty == null) {
this.errorToolTipProperty = new SimpleStringProperty();
}
return this.errorToolTipProperty;
}
}
I can use the control in fxml but the child component I add is always the last child which means the error icon is displayed to its left.
My control is used like this:
<ValidatedControl>
<TextField>
</TextField>
</ValidatedControl>
How do I get it to display the icon on the right side?
Now I do understand your problem. This might not fix your problem when you add your ValidatedControl in FXML, but when you do it programmatically try this:
ValidatedControl vc = new ValidatedControl();
TextField textField = new TextField();
vc.getChildren().add(textField);
textField.toBack();
Another way would be to go ItachiUchiha's way and add a Pane in your FXML as first child. But instead of overwriting the getChildren() method, write a new Method addNode(Node n) and add the node to the Pane.
forget about my first answer ;)

JavaFX Thread with progressindicator not spinning, work done in non FXThread

I would like to indicate a loading process with the JavaFX progressindicator.
The problem is that the indicator isn't rotating when the code is executed the first time.
On the second time it is rotating that means the bindings are working, both the disable and the visible-property.
I also change the state in the FX thread and do the work on a seperate thread so i can
see no error here.
Does anyone see the problem?
Controller:
//vars
#FXML private ProgressIndicator loadingIndicator;
private BooleanProperty isSaving = new SimpleBooleanProperty(false);
#Override
public void initialize(URL location, ResourceBundle resources) {
parentToDisable.disableProperty().bind(isSaving);
loadingIndicator.visibleProperty().bind(isSaving);
}
#FXML
void onSave(ActionEvent event) {
isSaving.set(true); //<<<<<<<<<problem
// separate non-FX thread
new Thread() {
// runnable for that thread
public void run() {
//++++++++++//long running task......+++++++++++++++
// update ProgressIndicator on FX thread
Platform.runLater(new Runnable() {
public void run() {
isSaving.set(false); //<<<<<<<<<problem
}
});
}
}.start();
}
Fxml:
<ScrollPane fitToHeight="true" fitToWidth="true" prefHeight="600.0"
prefWidth="500.0" xmlns="http://javafx.com/javafx/8"
xmlns:fx="http://javafx.com
/fxml/1">
<content>
<StackPane>
<children>
<VBox fx:id="parentToDisable">
<!-- shortened -->
<Button fx:id="btnSave" mnemonicParsing="false" onAction="#onSave"
text="Speichern" />
<!-- shortened -->
</VBox>
<ProgressIndicator fx:id="loadingIndicator"
maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity"
minWidth="-Infinity" prefHeight="60.0" prefWidth="60.0"
visible="false" />
</children>
</StackPane>
</content>
</ScrollPane>
That looks like a bug: RT-33261. It seems to be fixed in the latest pre-release of JDK 8u20.
My guess is it's to do with the progress indicator not being visible when the scene graph is first constructed. As a workaround, remove the visible="false" attribute from the ProgressIndicator in the fxml file, and wrap the binding in a Platform.runLater(...) call:
public void initialize(...) {
Platform.runLater(() -> loadingIndicator.visibleProperty().bind(isSaving));
}

Categories

Resources