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.
Related
I am completly lost atm. I have been working with scenebuilder and javaFX in the past but I am stuck like 5 hours now and I didnt get a step further. Let me explain:
I have a working java Eclipse Project, using maven dependencies
The Main is where I want to use JavaFX or load a fxml into
The programm takes many many VCC Files and extracts the data to put it all together in an excel
The programm works but I cant load a FXML file into the main or even show a pane in there
Now does my Java Main class has to extend Application? I tried both ways - doenst work.
Some example code:
public void start(Stage primaryStage) {
try {
bpmain = new BorderPane(FXMLLoader.load(new File("src\\fxml\\UserInterface.fxml").toURI().toURL()));
primaryStage.setScene(new Scene(bpmain));
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
or this (from original Docs)
public void start(Stage stage) {
Circle circ = new Circle(40, 40, 30);
Group root = new Group(circ);
Scene scene = new Scene(root, 400, 300);
stage.setTitle("My JavaFX Application");
stage.setScene(scene);
stage.show();
}
but this start method is just not getting called... where do I put that?
What my Programm should look like is pretty simple actually. I want a small UI Windows that lets you pick a Folder where the VCC data lives in and a OK Button that basically should run the Main method.
So a TextField that when its picked a Path in the Main gets replaced (filepath) and just a simple OK Button that says: yeah run the main - because the main works perfectly it is just that I cant show that ui and I dont know how to really connect it to the Main.java
Any help is appreciated - Ty
Option 1
public class Launch extends Application {
public static Stage stage = null;
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("/fxml/Main.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
this.stage = stage;
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Option 2:
public class SidebarController implements Initializable {
#Override
public void initialize(URL url, ResourceBundle rb) {
}
#FXML
void btnHome_OnMouseClicked(MouseEvent event) throws IOException {
BorderPane borderPane = (BorderPane) ((Node) event.getSource()).getScene().getRoot();
Parent sidebar = FXMLLoader.load(getClass().getResource("/fxml/ContentArea.fxml"));
borderPane.setCenter(sidebar);
}
}
I am making a simple todolist app. Here is a watered-down version of it:
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
ListView<Label> todoListView = new ListView();
Label doneTodo = new Label ("This todo is meant to be finished and struck through");
doneTodo.getStyleClass().add("done"); // Add the "done" class to this to-do
Label undoneTodo = new Label("This todo is meant to be undone and therefore isn't struck through");
// Add both to-dos to the listview
addTodo(doneTodo, todoListView);
addTodo(undoneTodo, todoListView);
// Set the listview as the scene, and add the stylesheet
Scene scene = new Scene(todoListView, 600, 550);
scene.getStylesheets().add(getClass().getResource("styles.css").toExternalForm());
primaryStage.setTitle("Label not taking on Strikethrough");
primaryStage.setScene(scene);
primaryStage.show();
}
// Adds the to-do (in this case just a simple Label) to the listview
private static void addTodo(Label todo, ListView<Label> todoList) {
todoList.getItems().add(todo);
}
public static void main(String[] args) {
launch(args);
}
}
Here is my CSS class:
.done {
-fx-strikethrough: true;
}
When I run the code, the -fx-strikethrough property does not show up on my Label. Note that although this is a simplified version of my app, the issue remains the same: The text inside the JavaFX Label is not being struck through.
Again, sorry for any inadequacies in my question. I am fairly new to Stack Overflow!
Thanks in advance.
The CSS rule should apply to the text node under the label node:
.done .text {
-fx-strikethrough: true;
}
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.
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.
This is something I like that I have seen in a few different softwares. I don't know where it originates from or what it really is called but here is an example of the pane system in Visual Studio.
Note how I can easily attach the pane anywhere with ease. Is such a thing possible with Javafx?
I recognize this question is old but others may be interested to know. I created a lightweight docking library for JavaFX for both proprietary and non-proprietary uses under the LGPL license.
https://github.com/RobertBColton/DockFX
There is no built-in docking framework for JavaFX 8.
There are some 3rd party solutions such as Drombler FX. I haven't used any of them.
A simple home-built system to dock and undock panels is pretty easy to create, but a comprehensive system would be quite difficult. The following code is adapted from zonski's answer to a docking framework discussion is in the Oracle JavaFX forum threads.
import javafx.application.Application;
import javafx.geometry.Orientation;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.*;
public class SimpleDocking extends Application {
public void start(final Stage stage) throws Exception {
final SplitPane rootPane = new SplitPane();
rootPane.setOrientation(Orientation.VERTICAL);
final FlowPane dockedArea = new FlowPane();
dockedArea.getChildren().add(new Label("Some docked content"));
final FlowPane centerArea = new FlowPane();
final Button undockButton = new Button("Undock");
centerArea.getChildren().add(undockButton);
rootPane.getItems().addAll(centerArea, dockedArea);
stage.setScene(new Scene(rootPane, 300, 300));
stage.show();
final Dialog dialog = new Dialog(stage);
undockButton.disableProperty().bind(dialog.showingProperty());
undockButton.setOnAction(actionEvent -> {
rootPane.getItems().remove(dockedArea);
dialog.setOnHidden(windowEvent -> {
rootPane.getItems().add(dockedArea);
});
dialog.setContent(dockedArea);
dialog.show(stage);
});
}
private class Dialog extends Popup {
private BorderPane root;
private Dialog(Window parent) {
root = new BorderPane();
root.setPrefSize(200, 200);
root.setStyle("-fx-border-width: 1; -fx-border-color: gray");
root.setTop(buildTitleBar());
setX(parent.getX() + 50);
setY(parent.getY() + 50);
getContent().add(root);
}
public void setContent(Node content) {
root.setCenter(content);
}
private Node buildTitleBar() {
BorderPane pane = new BorderPane();
pane.setStyle("-fx-background-color: burlywood; -fx-padding: 5");
final Delta dragDelta = new Delta();
pane.setOnMousePressed(mouseEvent -> {
dragDelta.x = getX() - mouseEvent.getScreenX();
dragDelta.y = getY() - mouseEvent.getScreenY();
});
pane.setOnMouseDragged(mouseEvent -> {
setX(mouseEvent.getScreenX() + dragDelta.x);
setY(mouseEvent.getScreenY() + dragDelta.y);
});
Label title = new Label("My Dialog");
title.setStyle("-fx-text-fill: midnightblue;");
pane.setLeft(title);
Button closeButton = new Button("X");
closeButton.setOnAction(actionEvent -> hide());
pane.setRight(closeButton);
return pane;
}
}
private static class Delta {
double x, y;
}
public static void main(String[] args) throws Exception {
launch(args);
}
}
If you have extensive need for such a framework, you might want to look into the NetBeans platform, which is a Swing based framework into which you can embed JavaFX.
A simple docking framework for JavaFX:
https://github.com/andy-goryachev/FxDock
public void start(Stage s) throws Exception
{
// plug in custom windows and dockable panes.
FxDockFramework.setGenerator(new DemoPanes());
// load saved layout
int ct = FxDockFramework.loadLayout();
if(ct == 0)
{
// when no saved layout exists, open the first window
DemoWindow.openBrowser("https://github.com/andy-goryachev/FxDock");
}
}
As the previous answer says, JavaFX does not have built-in support for dockable tabs. There is an OpenJDK issue requesting support for draggable and dockable tabs.
A recent third-party solution that may be worth looking into is DockFX which is in active development at the time of writing (September 2015)