I am attempting to make a simple editor in JavaFX 2.2. I downloaded Ace Editor repository and created a test page which works fine when double clicked.
However, it does not work when I try to embed it into the WebView.
SSCCE:
package web;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.SceneBuilder;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.StackPaneBuilder;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.scene.web.WebViewBuilder;
import javafx.stage.Stage;
public class EditorTrial extends Application{
WebView webView;
WebEngine engine;
StackPane stack;
Scene scene;
#Override
public void start(Stage primStage) throws Exception {
stack = StackPaneBuilder
.create()
.alignment(Pos.CENTER)
.build();
webView = WebViewBuilder
.create()
.build();
engine = webView.getEngine();
engine.setJavaScriptEnabled(true);
engine.load("/home/little/Downloads/AceEditor/ace-builds-master/MyTrial.html");
stack.getChildren().add(webView);
scene = SceneBuilder
.create()
.root(stack)
.build();
primStage.setScene(scene);
primStage.sizeToScene();
primStage.show();
}
public static void main(String[] args) {
Application.launch("web.EditorTrial");
}
}
Can someone please tell me what is wrong?
It works for me when the absolute file path :
try
File f = new File("/home/little/Downloads/AceEditor/ace-builds-master/MyTrial.html");
String StrURL = f.toURI().toURL().toString();
engine.load(StrURL);
Related
I am trying to print "Hello" whenever I press "A", however the console doesn't show up anything. I have found many ways to fix this but couldn't. Can you guys help me?
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.stage.Stage;
import java.io.IOException;
public class HelloApplication extends Application {
#Override
public void start(Stage stage) throws IOException {
Group root = new Group();
Scene scene = new Scene(root);
scene.setOnKeyPressed(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
switch(event.getCode()) {
case A:
System.out.println("Hello");
}
}
});
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
my apologies if this is an easy thing for you, but my mind boggles. After several years of not programming at all, I am working on a pet project (2d tile based game engine) where I would like to use Java FX headless in order to make use of the graphics capabilities.
I have understood from here and here
that you need to a Java FX Application in order to have the graphics system initialized.
So I basically took the ImageViewer example and implemented Runnable:
package net.ck.game.test;
import java.io.BufferedReader;
import java.util.ArrayList;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.Logger;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class ImageTest extends Application implements Runnable {
protected static final Logger logger = (Logger) LogManager.getLogger(ImageTest.class);
BufferedReader x;
#Override public void start(#SuppressWarnings("exports") Stage stage) {
logger.error(Thread.currentThread().getName() + ", executing run() method!");
Image standardImage = new Image("file:graphics/image1.png");
logger.error("image height image1: "+ standardImage.getHeight());
logger.error("image width image1:" + standardImage.getWidth());
Image movingImage = new Image("file:graphics/image2.png");
ArrayList<Image> images = new ArrayList<Image>();
images.add(movingImage);
images.add(standardImage);
ImageView iv1 = new ImageView();
iv1.setImage(standardImage);
ImageView iv2 = new ImageView();
iv2.setImage(movingImage);
Group root = new Group();
Scene scene = new Scene(root);
scene.setFill(Color.BLACK);
HBox box = new HBox();
box.getChildren().add(iv1);
box.getChildren().add(iv2);
root.getChildren().add(box);
stage.setTitle("ImageView");
stage.setWidth(415);
stage.setHeight(200);
stage.setScene(scene);
stage.sizeToScene();
stage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
#Override
public void run()
{
Application.launch(ImageTest.class);
}
}
When I run this as its own application, this works fine and displays the two images I want it to display.
When I run it like this in the "game" constructor:
public class Game {
private boolean animated;
public boolean isAnimated() {
return animated;
}
public void setAnimated(boolean animated) {
this.animated = animated;
}
public Game() {
setAnimated(true);
if (isAnimated() == true)
{
ImageTest imageTest = new ImageTest();
new Thread(imageTest).start();
}
}
There are no errors, ImageTest runs in its own thread, the application window opens, but it is empty.
I do not understand this at all, why is that?
Can someone pleaese shed some light on this?
UPDATE:
I had different working contexts by accident. Fixing this fixed the problem.
UPDATE: I had different working contexts by accident. Fixing this fixed the problem.
I am creating a dialog and call Platform.runLater() in the controller initialize() method.
When I try to open the dialog with showAndWait() it loads the FXML (I know it does because the warning is printed before Running Later and After first showAndWait) but doesn't open the dialog. Only a second call to showAndWait() will open it. It there a reason for this wired behavior or is this a bug?
The console output is:
Starting dialog creation
Running Later
After first showAndWait
Closing
After second showAndWait
but is should be:
Starting dialog creation
Init
Running Later
Closing
After first showAndWait
Closing
After second showAndWait
There is also this warning:
Apr 20, 2018 12:20:32 AM javafx.fxml.FXMLLoader$ValueElement processValue
WARNING: Loading FXML document with JavaFX API of version 9.0.1 by JavaFX runtime of version 8.0.161
But as far as I know this just means that my JavaFX version is outdated.
Main class:
import java.io.IOException;
import java.util.List;
import java.util.Optional;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Dialog;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class Main extends Application{
public static void main(String[] args) {
launch();
}
#Override
public void start(Stage stage) throws Exception {
stage.setScene(new Scene(new BorderPane()));
stage.show();
System.out.println("Starting dialog creation");
Dialog<Optional<List<String>>> popup = new Dialog<>();
FXMLLoader loader = new FXMLLoader(Main.class.getClassLoader().getResource("Dialog.fxml"));
try {
popup.setDialogPane(loader.load());
} catch (IOException e) {
e.printStackTrace();
}
Controller controller = loader.getController();
controller.dialog = popup;
popup.getDialogPane().getButtonTypes().add(ButtonType.CLOSE);
popup.showAndWait();
System.out.println("After first showAndWait");
popup.showAndWait();
System.out.println("After second showAndWait");
}
}
Controller:
import java.net.URL;
import java.util.List;
import java.util.Optional;
import java.util.ResourceBundle;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.scene.control.Dialog;
public class Controller {
#FXML
private ResourceBundle resources;
#FXML
private URL location;
public Dialog<Optional<List<String>>> dialog;
#FXML
void initialize() {
System.out.println("Init");
Platform.runLater(() -> {
System.out.println("Running Later");
dialog.setResult(Optional.empty());
dialog.setOnCloseRequest(e -> {
System.out.println("Closing");
});
});
}
}
FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.DialogPane?>
<DialogPane contentText="This is a text" headerText="Test" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Controller" />
I've recently started playing around with JavaFX :) I'm working on a little pet project and one of the issues I'm currently having is animating the resize of a VBox when a child is added or removed to/from the VBox.
I've got "the kids" fading out and then being removed from the VBox already. Once that animation completes I need the VBox height to resize preferably as an animation and not like the instant change it currently does.
The other threads that I've found are similar but I think they aren't quite exactly what I'm looking for.
Animation upon layout changes
Adding Node's animated to a VBox
Main Class:
package application;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.input.KeyCombination;
import javafx.scene.paint.Color;
import application.notifier.*;
public class Main extends Application
{
#Override
public void start(Stage stage)
{
try
{
stage.setTitle("Test");
Group root = new Group();
Scene scene = new Scene(root, (Screen.getPrimary().getBounds().getWidth()-100), (Screen.getPrimary().getBounds().getHeight()-100), Color.WHITE);
Notifier notice = new Notifier();
Notifier.addNotice("Testing Add Notice");
Notifier.addNotice("Testing Add Notice again!");
root.getChildren().add(Notifier.container);
stage.setFullScreen(true);
stage.setScene(scene);
stage.setFullScreenExitHint("");
//stage.setFullScreenExitKeyCombination(KeyCombination.NO_MATCH);
stage.show();
Button test = new Button("Remove");
test.setLayoutX(500.0);
test.setLayoutY(500.0);
test.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent e) {
Notifier.removeNotice();
}
});
root.getChildren().add(test);
}
catch(Exception e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
launch(args);
}
}
Notifier Class:
import java.util.ArrayList;
import javafx.animation.FadeTransition;
import javafx.animation.Timeline;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.stage.Screen;
import javafx.util.Duration;
public class Notifier
{
private static int maxVisibleNotices = 5;
private static int currentVisible = 0;
private static ArrayList<String> msgOverflow;
public static VBox container;
public Notifier()
{
BackgroundFill bkgrndFill = new BackgroundFill(Color.rgb(0, 0, 0, .65), new CornerRadii(10.0), new Insets(0));
Background bkgrnd = new Background(bkgrndFill);
Notifier.container = new VBox();
Notifier.container.backgroundProperty().set(bkgrnd);
Notifier.container.setAlignment(Pos.TOP_CENTER);
Notifier.container.setMinWidth(Screen.getPrimary().getBounds().getWidth() - 50);
Notifier.container.setMaxWidth(Screen.getPrimary().getBounds().getWidth() - 50);
Notifier.container.setLayoutX((Screen.getPrimary().getBounds().getWidth() - (Screen.getPrimary().getBounds().getWidth() - 50))/2);
Notifier.container.setLayoutY(5.0);
Notifier.container.setSpacing(5.0);
Notifier.container.setPadding(new Insets(5.0));
Notifier.msgOverflow = new ArrayList<String>();
}
public static void addNotice(String msg)
{
if(Notifier.currentVisible < Notifier.maxVisibleNotices)
{
Text txt = new Text(msg);
txt.setFill(Color.rgb(255,255,255));
Notifier.container.getChildren().add(txt);
Notifier.currentVisible++;
}
else
{
Notifier.msgOverflow.add(msg);
}
}
public static void removeNotice()
{
if(Notifier.currentVisible > 0)
{
FadeTransition ft = new FadeTransition(Duration.millis(1000), Notifier.container.getChildren().get(0));
ft.setFromValue(1.0);
ft.setToValue(0.0);
ft.setCycleCount(0);
ft.setAutoReverse(false);
ft.play();
ft.setOnFinished(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent e) {
Notifier.container.getChildren().remove(0);
Notifier.currentVisible--;
}
});
}
}
}
I hope this is clear enough.
And thanks in advance for help or suggestions.
Probably not very helpful any more. I am currently working on the same thing.
You just need:
1. Add the same animation(if they all supposed to be same) to each of the remaining children in the VBox.
2. Use ParallelAnimation to make them run at the same time.
3. Use again a SequentialAnimation for you "kids" fading out animation and the parallel animation. This ensures they will not happen concurrently since multiple threads could run simultaneously.
4. To reach still the same view as what the instant update does, use animation/timeline.setonFinished(EventHandler()) to updates the screen
I want to snap a picture of a webpage using the JavaFX "snapshot" method. My problem is that the WebView doesn't load the webpage before I snap the snapshot. Putting the call to snapshot inside a listener that tests when the webview's getLoadWorker succeeds doesn't work. I get inside the "if" of the listener (see below) before the page actually loads.
To demonstrate this, the following standalone code both attempts to snap the snapshot upon "success" and allows you to click a button to do the same. The button click (marked "BUTTON") works, because you click it after the webpage loads. However the automatic snapshot (marked "AUTOMATIC") produces a blank image, because for some reason the worker state is reaching "SUCCEEDED" before the page is actually loaded.
Can someone tell me what I'm doing wrong with the getLoadWorker listener? Thank you for any help!
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import javax.imageio.ImageIO;
import javafx.concurrent.Worker;
import javafx.concurrent.Worker.State;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.embed.swing.SwingFXUtils;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.control.Button;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.VBox;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class OpenHTML extends Application {
#Override
public void start(Stage primaryStage) {
final VBox vbox = new VBox(2);
final Button btn = new Button();
WebView webView = new WebView();
webView.setMaxWidth(600);
final WebEngine webEngine = webView.getEngine();
File myHTMLFile = new File("C:/Temp/test.html");
try {
webEngine.load(myHTMLFile.toURI().toURL().toString());
} catch (MalformedURLException e1) {
e1.printStackTrace();
}
webEngine.getLoadWorker().stateProperty()
.addListener(new ChangeListener<State>() {
#Override
public void changed(ObservableValue<? extends State> ov, State oldState,
State newState) {
if (newState == Worker.State.SUCCEEDED) {
System.out.println("succeeded");
// AUTOMATIC
snapit(vbox, "snapshot_auto.png");
}
}
});
vbox.getChildren().add(btn);
vbox.getChildren().add(webView);
btn.setText("Snap a picture");
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
// BUTTON
snapit(vbox, "snapshot_by_btn.png");
}
});
Scene scene = new Scene(new Group(vbox), 600, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void snapit(VBox vbox, String filename) {
WritableImage snapshot = vbox.snapshot(new SnapshotParameters(), null);
File file = new File("C:/Temp/" + filename);
RenderedImage renderedImage = SwingFXUtils.fromFXImage(snapshot, null);
try {
ImageIO.write(renderedImage, "png", file);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
OpenHTML.launch(args);
}
}