I have been endeavouring to implement a JavaFX application using FXML which includes a WebView.
However, when run this results in a ClassNotFoundException:javafx.scene.web.WebView leading to a javafx.fxml.LoadException, but I am perplexed by this.
Consequently, I have created a simplified application as follows. The Controller is empty in this example. If anybody can inform me how to successfully implement a WebView it will be much appreciated.
Main.java
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("wv.fxml"));
primaryStage.setTitle("WebView Test");
primaryStage.setScene(new Scene(root, 500, 500));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
wv.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.FlowPane?>
<?import javafx.scene.web.WebView?>
<FlowPane fx:controller="sample.Controller"
xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">
<WebView fx:id="WV" prefWidth="200" prefHeight="200"></WebView>
</FlowPane>
module-info.java
module WebViewTest {
requires javafx.fxml;
requires javafx.controls;
opens sample;
}
Have a look at your module-info and wonder why you don't have javafx.web in there.
Related
I have been endeavouring to implement a JavaFX application which includes the display of an image using fxml.
However, it is unclear to me how to successfully create the image url.
I have tried using the ampersand annotation to create a relative path and also tried an absolute path but all are rejected by the IDE.
Consequently I have created a simplified application as follows:
Main.java
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Display an Image");
primaryStage.setScene(new Scene(root, 300, 200));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
sample.fxml
<?import javafx.scene.layout.FlowPane?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.image.Image?>
<FlowPane fx:controller="sample.Controller"
xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">
<ImageView fx:id="ivWoodland">
<image>
<Image fx:id="imgWoodland" url="file:///D:/TF/ImageDemo/woodland.jpg"/>
</image>
</ImageView
If anybody can inform me how to format the url it will be much appreciacted.
Thanks.
I am trying to create a button in JavaFX using Scene Builder but I am having some issues. Here is my code :
MainDesign.java
package application;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class MainDesign extends Application {
#Override
public void start(Stage primaryStage) {
try {
BorderPane root = (BorderPane) FXMLLoader.load(getClass().getResource("application/Design.fxml"));
Scene scene = new Scene(root, 400, 400);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
DesignController.java:-
package application;
import java.awt.Button;
import javafx.fxml.FXML;
public class DesignController {
#FXML private Button b1;
}
Design.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.BorderPane?>
<BorderPane xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.DesignController">
<center>
<Button fx:id="b1" mnemonicParsing="false" text="Button" BorderPane.alignment="CENTER" />
</center>
</BorderPane>
Error:
Exception in Application start method
java.lang.reflect.InvocationTargetException
Caused by: java.lang.RuntimeException: Exception in Application start method
Caused by: java.lang.IllegalAccessError: class com.sun.javafx.fxml.FXMLLoaderHelper (in unnamed module #0x22e6b9c) cannot access class com.sun.javafx.util.Utils (in module javafx.graphics) because module javafx.graphics does not export com.sun.javafx.util to unnamed module #0x22e6b9c
Exception running application application.MainDesign
Thus , it's generating an exception in MainDesign.java file , I guess its regarding FXML loader.
Please help me if anyone has a solution for such issue!!!
There is a confusion with the Button component; in Design.fxml you're using javafx.scene.control.Button and in DesignController.java you're using java.awt.Button. JavaFX and Java AWT are independant libraries, so it raises a problem when FXML loader is reading this line:
#FXML private Button b1;
because it cannot make a connection between b1 in your FXML file and b1 in your controller. You have to import javafx.scene.control.Button in your controller.
I would like to create a scrollpane and button from the controller and display it in fxml, is that possible? This my code but it doesn't work
controller
package application;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
public class controller {
ScrollPane scrollPane = new ScrollPane();
Button button = new Button("My Button");
public void initialize() {
button.setPrefSize(400, 300);
scrollPane.setContent(button);
scrollPane.setVbarPolicy(ScrollBarPolicy.AS_NEEDED);
scrollPane.setHbarPolicy(ScrollBarPolicy.AS_NEEDED);
}
}
main
package application;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
final Parent parent = FXMLLoader.load(getClass().getResource("ui.fxml"));
primaryStage.setTitle("ScrollPane Demo ");
primaryStage.setScene(new Scene(parent,600, 600));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);}
}
fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.VBox?>
<VBox id="vbox" prefHeight="400" prefWidth="400.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.controller">
<children>
<Pane prefHeight="200.0" prefWidth="200.0" />
</children>
</VBox>
You need to include your vbox in your controller, like this:
#FXML
private VBox vbox;
After that, add your scrollpane to your vbox's children:
vbox.getChildren().add(scrollPane);
Note that, you not added your button to your scrollpane's content, so your scrollpane is currently empty!
Edit: why you want to add nodes via fxml and from code too? Use this solution if it is really necessary, anyway use fxml to build your UI.
I had some problems in a project with KeyEvent. A combo box that switch values from one to another when key Enter is pressed.
After some attempts the problem showed was that the Enter key generates 2 times the event, so the combo box apparently didn't change.
Then, I tried to make a simple test project with this snippet:
window.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
if(event.getCode().equals(KeyCode.ENTER))
System.out.println("print");
}
});
The program prints twice every enter. Is it possible that KeyCode.ENTER refers to more than one key or something like this?
If i change KeyCode.ENTER in something else (tried with SPACE or some letters) it works properly.
Is possible to do something to solve this issue?
I made a simple project with 3 files :
Main
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
public class Main extends Application {
private static Stage window;
#Override
public void start(Stage primaryStage) throws Exception{
window = primaryStage;
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
public static Stage getWindow(){return window;}
public static void main(String[] args) {
launch(args);
}
}
Controller:
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.stage.Stage;
import java.net.URL;
import java.util.ResourceBundle;
public class Controller implements Initializable {
#FXML
TextField textField;
Stage window;
#Override
public void initialize(URL location, ResourceBundle resources) {
window = Main.getWindow();
window.addEventFilter(KeyEvent.KEY_RELEASED, new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
if (event.getCode().equals(KeyCode.ENTER))
System.out.println("print");
}
});
}
}
Sample :
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity"
minHeight="-Infinity" minWidth="-Infinity"
prefHeight="400.0" prefWidth="600.0"
fx:controller="Controller"
xmlns="http://javafx.com/javafx/8.0.121"
xmlns:fx="http://javafx.com/fxml/1">
<children>
<TextField fx:id="textField" layoutX="14.0" layoutY="14.0" />
</children>
</AnchorPane>
It prints twice when Enter is pressed. Before the insertion of the TextField instead worked as expected.
Change this line
window.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
to
window.addEventFilter(KeyEvent.KEY_RELEASED, new EventHandler<KeyEvent>() {
Edit code for #James_D
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyEvent;
import javafx.stage.Stage;
import java.net.URL;
import java.util.ResourceBundle;
public class Controller implements Initializable {
#FXML
TextField textField;
Stage window;
#Override
public void initialize(URL location, ResourceBundle resources) {
window = Main.getWindow();
window.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
System.out.println("Key Code:"+event.getCode()+" Target:"+event.getTarget());
});
// textField.setOnAction(event -> {});
}
}
When this runs you get the output of
Key Code:ENTER Target:TextField[id=textField, styleClass=text-input text-field]
Key Code:ENTER Target:AnchorPane#7a78d90b[styleClass=root]
If you uncomment the textField Line the output is
Key Code:ENTER Target:TextField[id=textField, styleClass=text-input text-field]
#James_D Initially I did not but after some looking around and I think it has to do with the preset setOnAction command the description is "The action handler associated with this text field, or null if no action handler is assigned. The action handler is normally called when the user types the ENTER key." So when you change the .setOnAction to consume or nothing it prevents this error which I think is because it is no longer kicking out the enter command to the anchorPane surrounding. Now as to why the KeyEvent.KEY_RELEASED works I think this is because the enter Key can only be released once per press down as opposed to the press which can send the command multiple times. This is all complete speculation because I have no proof of what I'm talking about if you can figure out a more reasonable explanation why I would love to know. This was supposed to be a comment but got to long.
I had the same issue. Every key would trigger the EventFilter once, except ENTER, which would trigger it twice.
A more simple and elegant solution was to simply add e.consume() into your block that respons to enter into the EventFilter.
if(e.getCode().toString().equals("ENTER")){
e.consume();
}
It seems there is an issue in setting focus (and handling keyboard events) on the JavaFX scenes that have only shapes (e.g. Rectangle, Circle, etc). Since formatting FXML is not easy at stackoverflow, I described the issue and a workaround in my blog:
http://yakovfain.com/2015/02/13/javafx-8-the-keyboard-events-are-not-being-processed-if-a-scene-has-only-shapes/
I'd appreciate if someone could find a better solution or explain what do I do wrong.
Thanks
This works for me.
The only change I made from Yakov's original solution is to remove the button work around hack and make the request focus call after the stage had been shown.
I think in Yakov's original implementation, the group containing the shapes was not shown on a stage at the time focus was requested for it - so it never got focus. By ensuring that we wait until the stage is displayed before requesting focus, everything works fine.
sample.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.Group?>
<?import javafx.scene.shape.Rectangle?>
<Group fx:id="theGroup" onKeyPressed="#keyHandler" focusTraversable="true"
xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="Controller">
<Rectangle fill="BLUE" height="300.0" stroke="BLACK"
strokeType="INSIDE" width="300.0"/>
</Group>
Main.java
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("sample.fxml"));
Parent root = loader.load();
primaryStage.setScene(new Scene(root, 300, 300));
primaryStage.show();
Controller controller = loader.<Controller>getController();
controller.focus();
}
public static void main(String[] args) {
launch(args);
}
}
Controller.java
import javafx.fxml.FXML;
import javafx.scene.Group;
import javafx.scene.input.KeyEvent;
public class Controller {
#FXML
private Group theGroup;
public void keyHandler(KeyEvent event) {
System.out.println("A Key was pressed");
}
public void focus() {
theGroup.requestFocus();
}
}