JavaFX - setOnAction not applicable - java

I am trying to learn JavaFX, and I've written the code shown down below, however I seem to be having trouble with this line of code:
btn.setOnAction(new EventHandler<ActionEvent>()
where it underlines setOnAction, and prints this Error:
The method setOnAction(EventHandler<ActionEvent>) in the type ButtonBase is not applicable for the arguments (new EventHandler<ActionEvent>(){})
import java.awt.event.ActionEvent;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class Test extends Application{
public static void main(String[] args){
launch(args);
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Hello World!");
Button btn = new Button();
btn.setText("Say 'Hello World' ");
btn.setOnAction(new EventHandler<ActionEvent>(){
#Override
public void handle(ActionEvent event) {
System.out.println("Button clicked");
}
});
StackPane root = new StackPane();
root.getChildren().add(btn);
primaryStage.setScene(new Scene(root, 300, 250));
primaryStage.show();
}
}
What am I doing wrong?

You have imported awt event listener just change this line of code
import java.awt.event.ActionEvent;
with this
import javafx.event.ActionEvent;
and you can also use lambda expression like this
btn.setOnAction((event) -> {
System.out.println("Button clicked");
});

You're mixing up Javafx with Swing. Replace
import java.awt.event.ActionEvent;
with
import javafx.event.ActionEvent;

Related

JavaFX throws ERROR_MEDIA_INVALID when playing certain mp3 files

I keep getting an ERROR_MEDIA_INVALID error when trying to play some .mp3 files via the JavaFX media player. Previous google searches have just led to old bug reports, and I'm not sure if this an actual bug or something I missed.
Example:
package sample;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.stage.Stage;
import java.io.File;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
primaryStage.setTitle("Hello World!");
Button btn = new Button();
btn.setText("Say 'Hello World'");
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
//change filename as needed
var file = new File("C:/Users/tgaravaglia/Downloads/test.mp3");
var media = new Media(file.toURI().toString());
var player = new MediaPlayer(media);
player.setOnError(new Runnable()
{
#Override
public void run()
{
//ERROR_MEDIA_INVALID here
player.getError().printStackTrace();
}
});
player.play();
}
});
StackPane root = new StackPane();
root.getChildren().add(btn);
primaryStage.setScene(new Scene(root, 300, 250));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Stack trace:
MediaException: UNKNOWN : [com.sun.media.jfxmediaimpl.platform.gstreamer.GSTMediaPlayer#6f4b481f] ERROR_MEDIA_INVALID: ERROR_MEDIA_INVALID
at javafx.media/javafx.scene.media.MediaException.getMediaException(MediaException.java:160)
at javafx.media/javafx.scene.media.MediaPlayer$_MediaErrorListener.onError(MediaPlayer.java:2623)
at javafx.media/com.sun.media.jfxmediaimpl.NativeMediaPlayer$EventQueueThread.HandleErrorEvents(NativeMediaPlayer.java:692)
at javafx.media/com.sun.media.jfxmediaimpl.NativeMediaPlayer$EventQueueThread.run(NativeMediaPlayer.java:426)
Working file: https://drive.google.com/file/d/1e3k9gVhV_hDehWHwhHElXC2jU4aKn6oc/view?usp=sharing
Broken file: https://drive.google.com/file/d/1_VKx4zLH6lFLv6VJdDvrP6IP3c-TjOYo/view?usp=sharing
So... I figured it out. That bad "mp3" file is actually a .wav file in disguise. I ran it through a cloud-based wav->mp3 converter and now it works fine. Hopefully this helps someone in the future with the same problem!

Update JavaFX stage within method

I am writing a program that uses a lot of data to do several calculations and it takes quite a while to finish. This is why I want to update and inform the user on the current percentage of the program being done. However I don't know how I can update the stage within the calculation method.
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class Main extends Application {
public void calculate() {
//Here I want to change the "percentage text"
//and update the stage.
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Hello World!");
Text percentage = new Text();
Button btn = new Button();
btn.setText("Say 'Hello World'");
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
calculate();
}
});
final GridPane inputGridPane = new GridPane();
GridPane.setConstraints(btn, 0, 0);
GridPane.setConstraints(percentage, 1, 0);
inputGridPane.setHgap(6);
inputGridPane.setVgap(6);
inputGridPane.getChildren().addAll(btn, percentage);
final Pane rootGroup = new VBox(12);
rootGroup.setPrefWidth(400);
rootGroup.setPrefHeight(225);
rootGroup.getChildren().addAll(inputGridPane);
rootGroup.setPadding(new Insets(12,12,12,12));
primaryStage.setScene(new Scene(rootGroup));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
This is what my code roughly looks like. Thank you in advance.
JavaFx provides a class called "Task" which can be used for background calculations while keeping the progression syncronised!
I would suggest doing it that way:
Create a second class extending Task for doing the heavy calculation:
import javafx.concurrent.Task;
public class CalculationTask extends Task<String> {
#Override
protected String call() throws Exception {
for (int i = 0; i < 100000000;i++) {
updateProgress(i, 100000000);
}
succeeded();
return "This is the computed result... Datatype can be changed by generics if you are calculation numbers";
}
}
This is one way how you could use it in your application class:
import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.concurrent.WorkerStateEvent;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.Dialog;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Hello World!");
Button btn = new Button();
btn.setText("Say 'Hello World'");
Task<String> calculationTask = new CalculationTask();
ProgressBar progressBar = new ProgressBar(); //ProgressIndicator could also be used
progressBar.progressProperty().bind(calculationTask.progressProperty());
progressBar.visibleProperty().bind(calculationTask.runningProperty());
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
calculationTask.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
#Override
public void handle(WorkerStateEvent workerStateEvent) {
new Alert(Alert.AlertType.CONFIRMATION, calculationTask.getValue()).show();
}
});
new Thread(calculationTask).start();
}
});
final GridPane inputGridPane = new GridPane();
GridPane.setConstraints(btn, 0, 0);
GridPane.setConstraints(progressBar, 1, 0);
inputGridPane.setHgap(6);
inputGridPane.setVgap(6);
inputGridPane.getChildren().addAll(btn, progressBar);
final Pane rootGroup = new VBox(12);
rootGroup.setPrefWidth(400);
rootGroup.setPrefHeight(225);
rootGroup.getChildren().addAll(inputGridPane);
rootGroup.setPadding(new Insets(12,12,12,12));
primaryStage.setScene(new Scene(rootGroup));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
I hope that helped, otherwise feel free to ask questions!

JFXtras MonologFX - How to detect which button was pressed

I was testing the MonologFX from JFXtras (v8.0-r5), but I got stuck with it!
Can anyone tell me how to check what was the button in the dialog that was pressed by the user? I tried in many ways, but no luck at all.
package javafx_jfxtras_monologfx;
import javafx.application.Application;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.event.EventHandler;
import javafx.event.ActionEvent;
import jfxtras.labs.dialogs.MonologFX;
import jfxtras.labs.dialogs.MonologFXButton;
import jfxtras.labs.dialogs.MonologFX.Type;
public class JavaFX_JFXtras_MonologFX extends Application
{
#Override
public void start(Stage stage)
{
MonologFX m = new MonologFX();
m.setModal(true);
m.setType(Type.QUESTION);
m.setTitleText("JFXtras MonologFX");
m.setMessage("Do you want to continue?");
m.setPos(698, 450);
MonologFXButton mb1 = new MonologFXButton();
mb1.setType(MonologFXButton.Type.YES);
mb1.setLabel("Continue");
m.addButton(mb1);
MonologFXButton mb2 = new MonologFXButton();
mb2.setType(MonologFXButton.Type.NO);
mb2.setLabel("Exit");
m.addButton(mb2);
Button btn = new Button();
btn.setText("Click the Button");
btn.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent event)
{
System.out.println("Hello :)");
}
});
StackPane root = new StackPane();
root.getChildren().add(btn);
Scene scene = new Scene(root, 300, 250);
stage.setTitle("JavaFX - JFXtras MonologFX");
stage.setScene(scene);
stage.show();
m.show();
}
public static void main(String[] args)
{
launch(args);
}
}
But the controls in labs are experimental and Mark has not worked on this one for a long time. We don't take them out because someone may use them, but as of version 8u40 JavaFX has a dialog itself. https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/Dialog.html|

addAll() method not working?

so maybe I'm not using the method how it's intended to be used but a video I watched by youtube user thenewboston used it exactly like this and it worked just fine. Help would be appreciated
package checkers;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.FlowLayout;
import javafx.scene.Scene ;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.application.*;
import javafx.stage.*;
public class Checkers extends Application {
Stage window;
public void start(Stage primaryStage) throws Exception {
window = primaryStage;
window.setTitle("Title");
HBox layout = new HBox();
Button startButton = new Button("Start");
Button quitButton = new Button("Quit");
layout.getChildren().addAll(startButton, quitButton);
Scene startScene = new Scene(layout, 400, 300);
window.setScene(startScene);
window.show();
}
public static void main(String[] args) {
launch(args);
}
}
`
The error I am receiving is as follows -
"The method addAll(int, Collection) in the type List is not applicable for the arguments (Button, Button)"
You imported the wrong type of Button. You want import javafx.scene.control.Button; not import java.awt.Button;

Javafx Button With EventHandler. Getting cannot find symbol error

I am trying to get a button to print out Java is fun after being clicked and I keep getting a Cannot find symbol error when I run it. I'm not sure whether it is my import statements or an actual error in the code itself. I was wondering if someone could help me figure out why I'm getting the error?
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
public class ButtonHandler extends Application {
#Override // Override the start method in the Application class
public void start(Stage primaryStage) {
Pane pane = new Pane();
Button btOK = new Button("OK");
pane.getChildren().add(btOK);
btOK.setOnAction((ActionEvent e) -> {
System.out.println("Java is Fun");
});
// Create a scene and place it in the stage
Scene scene = new Scene(Pane);
primaryStage.setTitle("Button Demo"); // Set title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.show(); // Display the stage
}
public static void main(String[] args) {
launch(args);
}
}

Categories