I have a question on the Event Handling in JavaFX. As per the tutorial (and other examples that I came across), event handling is carried the following way in JavaFX:
Button addBtn = new Button("Add");
addBtn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
System.out.println("Add Clicked");
}
});
But, I am wondering, if I can "handle" the button click the following way:
Button addBtn = new Button("Add");
addBtn.setOnAction(new addButtonClicked());
where addButtonClicked() is my own Class (with it's own set of methods and functionality) that I have defined and written to handle the actions for the button click.
Is there a way to attach my own event handler classes for buttons in JavaFX?
The EventHandler is an interface class.
So, it should be "implements" not "extends"
private static class AddButtonClicked implements EventHandler<ActionEvent> {
#Override
public void handle(ActionEvent event) {
System.out.println("My Very Own Private Button Handler");
}
}
Sure.
private static class AddButtonClicked extends EventHandler<ActionEvent> {
#Override
public void handle(ActionEvent event) {
System.out.println("My Very Own Private Button Handler");
}
}
Related
I am trying to create a dialog inside a fragment.when I am trying to press on the button and enter the dialog the app collaspe.
I guess the code is not right can you please help me with that?
Here is my code:
private void openDialog(){
Dialog dialog=new Dialog(getContext());
//AlertDialog.Builder builder=new AlertDialog.Builder(getContext());
LayoutInflater layoutInflater=this.getLayoutInflater();
View custom_dialog=getActivity().getLayoutInflater().inflate(R.layout.geo_dialog,null);
dialog.setContentView(custom_dialog);
// add_geofence_radius= custom_dialog.findViewById(R.id.radius_size);
save_btn=custom_dialog.findViewById(R.id.save_btn);
cancel_btn=custom_dialog.findViewById(R.id.cancel_btn);
/* save_btn.setOnClickListener(new View.OnClickListener() {
#Override
}
});
*/
/*cancel_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialog.cancel();
}
});
*/
// dialog.setTitle("hello");
dialog.show();
}
The best way to show dialog in android is to use "DialogFragments" since they are aware of the lifecycle of the view it is attached on (ie. fragments/activities).
Here is an examples provided in Android docs:
public class PurchaseConfirmationDialogFragment extends DialogFragment {
#NonNull
#Override
public Dialog onCreateDialog(#Nullable Bundle savedInstanceState) {
return new AlertDialog.Builder(requireContext())
.setMessage(getString(R.string.order_confirmation))
.setPositiveButton(getString(R.string.ok), (dialog, which) -> {} )
.create();
}
public static String TAG = "PurchaseConfirmationDialog";
}
To show the dialog use:
new PurchaseConfirmationDialogFragment().show(
getChildFragmentManager(), PurchaseConfirmationDialog.TAG);
For more reference on dialogFragments, checkout : Create a DialogFragment
The following is my Task initialization
final Task<Void> vt=voiceTask();
Button btn = new Button();
btn.setText("Say");
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
new Thread(vt).start();
}
});
And here is the task coding
public Task<Void> voiceTask() {
return new Task<Void>(){
#Override
protected Void call() throws Exception {
HelloWorld hw=new HelloWorld();// HelloWorld is simple .java class getting voice through sphinx
updateMessage(hw.Hello());
return null;
}
};
}
Now on clicking the btn Button for the first time,the task functions normally, but on clicking for subsequent times the task is not called.
I want task to be called on every click.
Please advice me how to modify my code to do so...
See the JavaDocs.
As with FutureTask, a Task is a one-shot class and cannot be reused.
You need to create a new Task each time the button is pressed.
final Button btn = new Button();
btn.setText("Say");
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
final Task<Void> vt=voiceTask();
vt.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
#Override
public void handle(WorkerStateEvent event) {
btn.setDisable(false);
}
});
btn.setDisable(true);
new Thread(vt).start();
}
});
I want to disable a button for a specific time in JavaFX application. Is there any option to do this? If not, is there any work around for this?
Below is my code in application. I tried Thread.sleep, but i know this is not the good way to stop the user from clicking on next button.
nextButton.setDisable(true);
final Timeline animation = new Timeline(
new KeyFrame(Duration.seconds(delayTime),
new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
nextButton.setDisable(false);
}
}));
animation.setCycleCount(1);
animation.play();
You could use the simple approach of a thread that provides the relevant GUI calls (through runLater() of course):
new Thread() {
public void run() {
Platform.runLater(new Runnable() {
public void run() {
myButton.setDisable(true);
}
}
try {
Thread.sleep(5000); //5 seconds, obviously replace with your chosen time
}
catch(InterruptedException ex) {
}
Platform.runLater(new Runnable() {
public void run() {
myButton.setDisable(false);
}
}
}
}.start();
It's perhaps not the neatest way of achieving it, but works safely.
You could also be using the Timeline:
final Button myButton = new Button("Wait for " + delayTime + " seconds.");
myButton.setDisable(true);
final Timeline animation = new Timeline(
new KeyFrame(Duration.seconds(delayTime),
new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent actionEvent) {
myButton.setDisable(false);
}
}));
animation.setCycleCount(1);
animation.play();
The method to disable a JavaFX control is:
myButton.setDisable(true);
You can implement the time logic programmatically in any way you wish, either by polling a timer or by having this method invoked in response to some event.
If you have created this button instance through FXML in SceneBuilder, then you should assign the button an fx:id so that its reference is automatically injected into your controller object during the loading of the scene graph. This will make it easier for you to work with in your controller code.
If you have created this button programmatically, then you'll already have its reference available in your code.
Or you could use a Service and bind the running property to the disableProperty of the button do you want to disable.
public void start(Stage stage) throws Exception {
VBox vbox = new VBox(10.0);
vbox.setAlignment(Pos.CENTER);
final Button button = new Button("Your Button Name");
button.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
Service<Void> service = new Service<Void>() {
#Override
protected Task<Void> createTask() {
return new Task<Void>() {
#Override
protected Void call() throws Exception {
Thread.sleep(5000);//Waiting time
return null;
}
};
}
};
button.disableProperty().bind(service.runningProperty());
service.start();
}
});
vbox.getChildren().addAll(button);
Scene scene = new Scene(vbox, 300, 300);
stage.setScene(scene);
stage.show();
}
But the Timeline solution given by Uluk Biy, looks more elegant.
How to make checkbox/combobox readonly in javaFX but not disabled.
I tried consuming onAction event but it didn't work.
checkBox.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
event.consume();
}
});
Consuming all events like in code below works but I don't think it's a good solution:
checkBox.addEventFilter(KeyEvent.ANY, new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
event.consume();
}
});
checkBox.addEventFilter(MouseEvent.ANY, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEventevent) {
event.consume();
}
});
You can set the check box to disabled but set the the look of it using CSS. If you are using the default style you can make the check box look 'normal' by setting full opacity.
checkbox.setStyle("-fx-opacity: 1");
It is probably a similar deal with the combo box.
You can override method CheckBox#arm() with an empty one:
CheckBox cb = new CheckBox("hi") {
#Override
public void arm() {
// intentionally do nothing
}
};
If you do not want to overwrite the CheckBok class, you can use the selectedProperty.
CheckBox cb = new CheckBox("hi");
cb.selectedProperty().addListener(new NCL());
class NCL implements ChangeListener<Boolean> {
#Override
public void changed(ObservableValue<? extends Boolean> ov, Boolean old_val, Boolean new_val) {
cb.setSelected(false);
}
}
I am planning to create a single EventHandler Class that will handle all Types of events for all my controls in my JavaFX class.
For example, I added my custom event handler class to handle the Action Event the following way and it just works fine:
userNameText.addEventHandler(ActionEvent.ACTION, new DataChangeHandler());
cmbBox.addEventHandler(ActionEvent.ACTION, new DataChangeHandler());
btn.addEventHandler(ActionEvent.ACTION, new DataChangeHandler());
Here is my custome event handler class code:
public class DataChangeHandler implements EventHandler<ActionEvent> {
public void handle(ActionEvent event) {
System.out.println("My Very Own Private Button Handler");
}
}
But when I try to change one of the addEventHandlers to MouseEvent and modify the main EventHandler class the following way, it shows an error "The Interface eventhandler cannot be implemented more than once with different arguements":
userNameText.addEventHandler(ActionEvent.ACTION, new DataChangeHandler());
cmbBox.addEventHandler(MouseEvent.CLICKED, new DataChangeHandler());
btn.addEventHandler(ActionEvent.ACTION, new DataChangeHandler());
public class DataChangeHandler implements EventHandler<ActionEvent>, EventHandler<MouseEvent> {
public void handle(ActionEvent event) {
System.out.println("My Very Own Private Button Handler - ACTIONEVENT");
}
#Override
public void handle(MouseEvent arg0) {
System.out.println("My Very Own Private Button Handler - MOUSEEVENT");
}
}
Is there any other way to achieve this? Please help. Thanks in advance.
Try this
public class DataChangeHandler implements EventHandler<Event>{
#Override
public void handle(Event event) {
System.out.println("My Very Own Private Handler For All Kind Of Events");
}
}