I am building a JavaFX application through E(fx)clipse and Java Scene Builder.
The basic functionality is a login window. Once logged in, new window opens and the login window disapears. Right now it's just at the prototype stage.
When running out of ecplise, the functionality I want is all there. Login window shows up on start (code looking as such)
#Override
public void start(Stage primaryStage) {
try {
Parent root = FXMLLoader.load(getClass().getResource("view/login.fxml"), ResourceBundle.getBundle("ca.sportstats.resources.labels"));
primaryStage.setTitle("SportStats Live Update Tool : Login");
primaryStage.setScene(new Scene(root, 450, 300));
primaryStage.show();
} catch (IOException e) {
//Change this to open a small popup window.
System.out.println("Could not deploy");
}
}
public static void main(String[] args) {
launch(args);
}
There is one button on this window that simply opens another (the login logic will come later and not an issue here).
btnLogin.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
//TODO: Login logic.
//On success allow to open the tool (aka main window);
Parent root;
try {
root = FXMLLoader.load(getClass().getResource("../view/selector.fxml"), resources);
Stage stage = new Stage();
stage.setTitle("Selector");
stage.setScene(new Scene(root, 450, 450));
stage.show();
//hide this current window
((Node)(event.getSource())).getScene().getWindow().hide();
} catch (IOException e) {
e.printStackTrace();
}
}
});
This works no problem in Ecplise. BUT! When I build this (in the fashion described on the e(fx)clipse tutorials I get an executable jar, but only get the login window. When I click my button the 2nd window doesn't show up.
The problem I think is that in jars you can't do relative paths. Inside Eclipse you are running on the filesystem where this is not a problem
Related
I'm having a JavaFX-GUI that enables the user to scan.
This process is taking a while. So the user should neither keep clicking around, nor should anyone think the program hung itself.
My solution was a modal window that is just in front of the whole GUI and and disappears itself when everything is finished.
The interface consists of a FXML-Controller, the FXML-File and the MainApp.
So far I'm calling it in the Controller:
Stage stage = Messages.beforeScan(event);
s.scan(filename);
stage.close();
The beforeScan-Method looks like that (Taken from How to create a modal window in JavaFX 2.1 ):
public static Stage beforeScan(Event event) {
Stage stage = new Stage();
try {
Parent root = FXMLLoader.load(
FXMLController.class.getResource("/fxml/Scene.fxml"));
stage.setScene(new Scene(root));
stage.setTitle("My modal window");
stage.initModality(Modality.WINDOW_MODAL);
stage.initOwner(((Node)event.getSource()).getScene().getWindow());
stage.show();
} catch (IOException ex) {
Logger.getLogger(Meldungen.class.getName()).log(Level.SEVERE, null, ex);
}
return stage;
}
Yet this is not successful. If I comment out stage.close(); I can still use my main GUI.
So a different approach:
Instead of importing the Scene from the controller I tired to obtain it from the MainApp-Class:
public static Stage beforeScan(Event event) {
Stage stage = new Stage();
stage.setScene(MainApp.getStage.getScene());
stage.setTitle("My modal window");
stage.initModality(Modality.WINDOW_MODAL);
stage.initOwner(((Node) event.getSource()).getScene().getWindow());
stage.show();
return stage;
}
But this just crashes everything with a StackOverflow.
The Popup (Taken from the example here ) is not helpful either. It is even only opened after the scan.
Using an Alert seemed like a good idea, but doing it that way is not only locking the screen but the program itself:
public Alert beforeScan(Event event) {
javafx.scene.control.Alert alert = new Alert(Alert.AlertType.NONE, "Scan in progress");
alert.showAndWait();
return alert;
}
How should a screen-locking modal window/popup be done properly?
I'm creating a JavaFX application (on OSX) which consists of a stage.
It should neither be allowed to resize it manually nor to enter full screen via the maximize button. This is currently achieved by stage.setResizable(false) which works fine.
The problem occurs when adding an Alert: After closing the Alert, the maximize button becomes targetable again, making it possible to enter full screen.
Here's a simple example of code:
// imports
public class MyApplication extends Application {
public static void main(String[] args) { launch(args); }
#Override
public void start(Stage primaryStage) {
primaryStage.setScene(new Scene(new StackPane()));
primaryStage.setResizable(false);
primaryStage.setOnCloseRequest(event -> {
Alert alert = new Alert(AlertType.CONFIRMATION, "Close?");
if (alert.showAndWait().get().equals(ButtonType.CANCEL)) {
event.consume();
}});
primaryStage.show();
}
}
Does anyone know why this is happening?
I have a swing application where I need to run and open JavaFX Scene/stage. I have to run it without extends Application. I've tried most of the solutions posted on Stackoverflow, none of them are working in my situation.
Here is my latest try and I am getting NullPointerException. My stage is getting NULL. This line -> [stage.setScene(new Scene(root, SCENEWIDTH, SCENEHEIGHT));]
How to resolve this issue at this point? Or is there any elegant way to resolve this issue? Here is the block of code:
case ADMIN:
new JFXPanel();
Platform.runLater(new Runnable() {
#Override
public void run() {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/AdminView.fxml"));
Parent root = loader.load();
stage.setScene(new Scene(root, SCENEWIDTH, SCENEHEIGHT));
// Give the controller access to the main app
AdminController controller = loader.getController();
controller.setMainApp();
stage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
});
break;
Any help would be greatly appreciated.
Don't use a Stage in a Swing application; instead, use a JFrame and embed the JavaFX content inside it using a JFXPanel:
case ADMIN:
// I'm assuming this code is on the AWT Event Dispatch thread
JFrame window = new JFrame();
JFXPanel jfxPanel = new JFXPanel();
Platform.runLater(() -> {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/AdminView.fxml"));
Parent root = loader.load();
jfxPanel.setScene(new Scene(root, SCENEWIDTH, SCENEHEIGHT));
// Give the controller access to the main app
AdminController controller = loader.getController();
controller.setMainApp();
SwingUtilities.invokeLater(() -> {
window.add(jfxPanel);
window.pack();
window.setVisible(true);
});
} catch (Exception e) {
e.printStackTrace();
}
});
break;
Most probably stage is null at that point. Where is the initialization of stage?
If stage is null, stage.setScene(...) will throw a nullpointer exception.
Here is solution I've found from Oracle's tutorial suggested by #d.j.brown. Tested. It's working. Thought, if any one need it.
But I am now running in some other problems in my Application. Since I've used Stage.
Here in this solution I've used JFrame. If any one knows how to use Stage in Swing application, please let me know. Thanks.
JFrame frame = new JFrame();
frame.setUndecorated(true);
final JFXPanel fxPanel = new JFXPanel();
frame.add(fxPanel);
frame.setSize(FRAMEWIDTH, FRAMEHEIGHT);
frame.setVisible(true);
frame.setResizable(false);
Platform.runLater(new Runnable() {
#Override
public void run() {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/AdminViewSwing.fxml"));
try {
Parent root = loader.load();
Scene scene = new Scene(root, FRAMEWIDTH, FRAMEHEIGHT);
fxPanel.setScene(scene);
AdminController controller = loader.getController();
controller.setMainApp();
} catch (IOException e) {
e.printStackTrace();
}
}
});
I have a Java Swing application. For one of javax.swing.JFrame, I use JFXPanel to embed JavaFX content. In JFXPanel, there is ListView (JFrame => JFXPanel => ListView). Double click on ListView's item, will open new JavaFX browser Window, to load HTML content of it's URL.
Assuming 3 windows:
Window-A: Main application window (Swing).
Window-B: JFrame with JFXPanel (contain's ListView).
Window-C: JavaFX browser window
Once Window-C is open, it always stay on top of any other Windows (Window-A, Window-B, & even Netbean IDE Window). When click on Window-A / Window-B, the Window is actived but always stay behind Window-C. The only way to have complete view on Window-A / Window-B, is to move Window-C away so not to overlap with them.
I tried setting these for Window-C, but with no effect:
stage.initOwner(((Node)event.getSource()).getScene().getWindow());
stage.initModality(Modality.NONE);
The intended behaviour is, whenever Window-A / Window-B / Window-C is clicked, it should stay on top, all the other windows should go behind it.
Any idea how to make this work? Is it a mistake to invoke pure JavaFX Window (Window-C) from Swing application?
Below is my code snippet:
public class StockNews extends JFrame {
private final JFXPanel jfxPanel = new JFXPanel();
Scene scene;
VBox vbox;
java.util.List<FeedItem> messages;
ListView<FeedItem> newsListView;
ObservableList<FeedItem> messages_o;
public StockNews(java.util.List<FeedItem> messages) {
super();
this.messages = messages;
initComponents();
}
private void initComponents() {
Platform.runLater(new Runnable() {
#Override
public void run() {
vbox = new VBox();
scene = new Scene(vbox, 500, 500);
jfxPanel.setScene(scene);
messages_o = FXCollections.observableArrayList (messages);
newsListView = new ListView<>(messages_o);
newsListView.setCellFactory(new Callback<ListView<FeedItem>,
ListCell<FeedItem>>() {
#Override
public ListCell<FeedItem> call(ListView<FeedItem> list) {
// draw single cell
return new DisplaySingleNews();
}
}
);
// Double-clicked ListView's item, will open new JavaFX browser Window, loading HTML content of it's URL
newsListView.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
if (event.getClickCount() > 1) {
FeedItem msg = newsListView.getSelectionModel().getSelectedItem();
URL link = msg.getLink();
Stage stage = new Stage(StageStyle.UTILITY);
// This window always stay on top, even not active. below 2 lines have no effect
stage.initOwner(((Node)event.getSource()).getScene().getWindow());
stage.initModality(Modality.NONE);
WebView browser = new WebView();
stage.setScene(new Scene(browser));
stage.show();
WebEngine webEngine = browser.getEngine();
webEngine.load(link.toString());
}
}
});
vbox.getChildren().addAll(newsListView);
}
});
this.add(jfxPanel, BorderLayout.CENTER);
this.setVisible(true);
}
}
I'm launching my JavaFX scene as:
Applicaiton.launch(Main.class);
form my java code.
How to return to my code after I'm done with JavaFX!
Example:
public String Method()
{
Stirng s = "MyName";
Application.launch(Main.class);//here I lauch JavaFX scene
s.trim();//how to come back here after I'm done with that scene.
}
It's not supposed to work that way. You start by extending javafx.application.Application, then the entry point is start(Stage), which you must override. That method is the place where you have to set up the Scene for your stage, build the layout with Node's (buttons, layout managers, text fields, checkboxes), and register event handlers. You can access startup parameters with getParameters().
The application can be launched by providing the usual main() that calls launch(), a facility of JavaFX. So the minimal JavaFX application looks like:
public class MyApp extends Application {
#Override
public void start(Stage primaryStage) {
VBox root = new VBox();
root.getChildren().setAll(new Label("Hello world!"));
Scene scene = new Scene(root, 600, 400);
// Add widgets and set up event handlers
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String... args) {
launch(args);
}
}
Platform.exit(); will do it click here for javafx2.2 documentation