I have a Webview (JavaFX 8) that load an article from Wikipedia.
I put a refresh button to allow a refresh, basically, it does another call to the load method of the webEngine of the WebView with the same URL. But about 50% of the time the article is never rendered. In this case, I can right-click on the web view to manually refresh, then it will be rendered successfully.
I tried to look at the LoadWorker state, it always says "SUCCEED"...
Below is a short runnable Test class that demonstrates my point.
public class Test1 extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
final WebView webView = new WebView();
webView.getEngine()
.load("http://fr.wikipedia.org/wiki/Sp%C3%A9cial:Page_au_hasard");
Tab tab = new Tab("webView", webView);
TabPane tabPane = new TabPane(tab);
BorderPane borderPane = new BorderPane(tabPane);
Button buttonRefresh = new Button("Refresh");
buttonRefresh.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
webView.getEngine()
.load("http://fr.wikipedia.org/wiki/Sp%C3%A9cial:Page_au_hasard");
}
});
borderPane.setBottom(buttonRefresh);
Scene scene = new Scene(borderPane);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main (String[] args) {
launch(args);
}
}
Am I doing something wrong? Does anyone know where this problem might come from?
EDIT
I added a few lines to bypass the problem, I check the header in the DOM when the state of the loadWorker becomes SUCCESS. If it is empty, I reload. Now it (looks) 100% ok, but still I am very curious why it didn't simply work all the time first.
Some thoughts that may be useful
The link http://fr.wikipedia.org/wiki/Sp%C3%A9cial:Page_au_hasard redirects to a random article (that's why my refresh button can't use webView.getEngine.reload()).
Putting a ChangeListener on the stateProperty of the workLoader to call the reload method of webEngine actually works. Each page is rendered successfully, but already rendered page will also be re-rendered, which is terrible.
Related
The issue I'm having is that the mxGraph object does not load correctly on startup. It requires me to click a cell inside of it for it to appear, and even then it does not reveal the entire graph, just the cell that was clicked. In order to reveal all of it I have to refresh the graph via another control or drag a cell around the entire graph area.
When I initially developed this I was working with Java 8 and this was not an issue. This has only occurred since updating to Java 11 (OpenJDK). Everything else was kept the same when upgrading to 11, only the updated dependencies changed.
I am wrapping the mxGraphComponent inside of a SwingNode in order to place it inside of a JavaFX node. I've had issues in the past with Swing nodes inside JavaFX but I am creating all of the Swing components using the SwingUtilities.invokeLater() method. I am using the 3.9.8.1 version of JGraphX from Maven, but I have also tried the updated 4.0.0 from GitHub with no success.
Here's my MCVE:
public final class Main {
public static void main(final String[] args) {
Application.launch(JGraphExample.class);
}
}
public final class JGraphExample extends Application {
private mxGraph graph;
#Override
public void start(final Stage primaryStage) {
final SwingNode value = new SwingNode();
final BorderPane root = new BorderPane();
root.setCenter(value);
root.setBottom(createRefreshButton());
SwingUtilities.invokeLater(() -> value.setContent(buildGraphComponent()));
primaryStage.setWidth(500);
primaryStage.setHeight(500);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
private mxGraphComponent buildGraphComponent() {
graph = buildGraph();
return new mxGraphComponent(graph);
}
private mxGraph buildGraph() {
final mxGraph graph = new mxGraph();
graph.insertVertex(graph.getDefaultParent(), "x", "Hello", 100, 100, 100, 100);
return graph;
}
private Button createRefreshButton() {
final Button refresh = new Button("Refresh");
refresh.setOnAction(actionEvent -> graph.refresh());
return refresh;
}
}
Until clicking the refresh button the graph will not render correctly. This was not the case with Java 8 as it worked as intended. It seems the update to 11 has teased this issue out.
Has anyone come across this before or have any ideas? Thanks in advance.
I have tried searching for this many times with no luck. I am writing a software where I want the user to input their resolution before moving on to the main UI, as the main UI will change size based on the resolution given. How would I open a popup window without a button event handler and then proceed to the main application?
You can just open the popup window in your start() method:
public class MyApp extends Application {
#Override
public void start(Stage primaryStage) {
// make sure application doesn't exit when we close the dialog window:
Platform.setImplicitExit(false);
Stage popup = new Stage();
TextField resolutionField = new TextField();
// ... populate popup, etc...
popup.setOnHidden(() -> {
int resolution = Integer.parseInt(resolutionField.getText());
// now create main UI...
primaryStage.show();
});
popup.show();
}
}
I am very new to using JavaFX and have having some trouble using JavaFX with FXML. I am creating a program with a "Setup" button that when clicked, opens a new window with the connection (to an Arduino) settings. On the menu is another button ("Connect") that connects to the board. This closes the window. I'm looking to have this change the text of the original "setup" button to "disconnect", however, I don't seem to be able to access the button from the "setup window". Whenever I click "connect" I get the following error:
Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
I read online that this is a wrapper for a null pointer exception. I assume that the "setup" button is null and that's why I can't change it, but I can't work out why.
Here is an excerpt from MainController.java:
#FXML
protected void setUpConnection(ActionEvent e) {
SetupController setupController = new SetupController();
setupController.init(this);
}
The above method gets called when the "setup" button is clicked (set in the file: setupMenu.fxml). This then opens up the separate window. Here is the code in SetupController.java that opens the window:
private void openSetupWindow() {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("setupMenu.fxml"));
Parent root1 = (Parent)loader.load();
Stage stage = new Stage();
stage.setTitle("Setup Connection");
stage.setScene(new Scene(root1));
stage.show();
} catch(Exception exc) {
exc.printStackTrace();
}
}
When the connect button is clicked, the following method (in SetupController.java) is called:
private void changeButtonText(ConnectionEventType e) {
Button b = main.getSetupButton();
if(e == ConnectionEventType.CONNECT) {
b.setText("Disconnect");
}
else {
b.setText("Setup Connection...");
}
}
(main is the MainController object that was passed in to setupController.init() )
The above code is where I am getting the error.
Just to clarify, I have 2 separate fxml files, one for the main window and one for the pop up. sample.fxml(the main window) has its controller set to MainController and is set up in Main.java (below):
#Override
public void start(Stage primaryStage) throws Exception{
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("sample.fxml"));
GridPane root = loader.load();
Scene scene = new Scene(root, 1200, 900);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setTitle("Nest Control");
primaryStage.setScene(scene);
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
Am I trying to access the button incorrectly? Is anyone able to help? Like I said, I don't have much experience with using JavaFX or FXML.
I think the answer you are looking for is to store the controllers for each window you open so you can access the variables within the controllers, however without the rest of your code would be hard to advise you, but heres an example of what i mean:
private SetupController yourController;
#Override
public void start(Stage primaryStage) throws Exception{
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("sample.fxml"));
GridPane root = loader.load();
this.yourController=loader.<SetupController>getController();
Scene scene = new Scene(root, 1200, 900);
}
}
You could then pass the variable yourController to other instances in a Model-view-controller type way and access its methods.
or something like this in your case :
private void changeButtonText(ConnectionEventType e) {
Button b = this.yourController.getButton(); //a method that returns your #FXML button object in your controller
if(e == ConnectionEventType.CONNECT) {
b.setText("Disconnect");
}
else {
b.setText("Setup Connection...");
}
}
Or alternatively have a specific method within the controller that will set the text of the button without having to return the button object.
See the examples here and here
However please note the error you get seems to typically attributed to missing #FXML annotations so maybe make sure in this instance that you have annotated all the variables in any controllers also. See here for more details.
I'm not really sure how to ask this question but here is what I am trying to do. I am looking for the ability to load a website in java application and being able to click the buttons, text, box, etc and get the underlying DOM code.
For example:
-It loads google.com the webpage as well as the LIVE DOM under it, different frame. It can't be HTML since google is javascript.
-I want to click the google search box, or anything on the page, and application will print any attribute, such as name="q" or just q.
I've looked into XULrunner but it is deprecated for java.
You can use JavascriptExecutor for that. It is implemented by all WebDrivers. See JavaDoc for details. Use documentto refer to the DOM.
You can use JavaFX WebView.
You can call back to your Java code from Javascript. So you could write a small amount of Javascript that detects when the user clicked on element, and call some Java code that shows attribute value, for example. See "Calling back to Java from Javascript" in the WebEngine API docs.
Sample code:
public class HTMLMouseOverTest extends Application {
#Override
public void start(Stage primaryStage) {
final BorderPane root = new BorderPane();
final WebView webView = new WebView();
final WebEngine engine = webView.getEngine();
final BooleanProperty mouseOver = new SimpleBooleanProperty();
engine.getLoadWorker().stateProperty().addListener(new ChangeListener<State>() {
#Override
public void changed(ObservableValue<? extends State> observable,
State oldValue, State newValue) {
if (newValue == State.SUCCEEDED) {
// Here's how to add the Javascript if you don't have
// direct access to the HTML:
// final Document doc = engine.getDocument();
// Element div = doc.getElementById("important-div");
// div.setAttribute("onmouseover", "mouseOverProperty.set(true)");
// div.setAttribute("onmouseout", "mouseOverProperty.set(false)");
final JSObject window = (JSObject) engine.executeScript("window");
window.setMember("mouseOverProperty", mouseOver);
}
}
});
engine.loadContent("<html><body style='font-family:sans-serif';><h2>Hello World</h2>"+
"<div id='important-div' onmouseover='mouseOverProperty.set(true)'"+
"onmouseout='mouseOverProperty.set(false)' style='background: #ffd; padding:40px;'>"+
"Move mouse here</div>"+
"<h3>Thanks and good night</h3></body></html>");
root.setCenter(webView);
final Label label = new Label();
label.textProperty().bind(Bindings.when(mouseOver).then("Mouse in position").otherwise("Mouse out of area"));
root.setBottom(label);
final Scene scene = new Scene(root, 400, 250);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
I have the last version of java(8_40) and javaFX.
I have a checkbox with 10 items.
I compile and run the program.
If i move the program window to the bottom of the monitor screen, the dropdown list go out from the monitor screen. It is impossible to click the items out the screen.
Instead, if I try to do the same layout with scenes builder 2.0, click on preview, the dropdown is moved automatically up for not exit the screen.
Why with scenes builder is properly displayed, instead with "compile and run" not?
The problem is the same that if I do graphics via code is that if I use the files fxml.
I put below a small program example that gives me this error:
Component CustomControl.java
public class CustomControl extends VBox {
public CustomControl() {
ComboBox<String> asd = new ComboBox<String>();
ObservableList<String> data = FXCollections.observableArrayList();
asd.setItems(data);
data.add("1");
data.add("2");
data.add("3");
data.add("4");
data.add("5");
data.add("6");
data.add("7");
data.add("8");
data.add("9");
data.add("10");
getChildren().add(asd);
}
}
Main.java
public class CustomControlExample extends Application {
public static void main(String[] args) {
launch(args);
}
String address = " ";
#Override public void start(Stage stage) {
stage.setTitle("ComboBoxSample");
Scene scene = new Scene(new CustomControl());
stage.setScene(scene);
stage.show();
}
}
EDIT:
Screen-shot on the left the pop-up go out of the screen border (eclipse)
While, on the right the pop-up is automatically moved (Scene builder)
See this image:
It is easy to solve, just change the visible row count.