JAVAFX secondary panels - java

Hi guys a little programmer java Swing and I'm trying a new technology like JavaFx just that I just can not figure out how to make operations for navigation between views, in particular.
How can I replace a main view on the stage? for example I have a view that I associate with the calback start method in the scene in the following way
#Override
public void start(Stage primaryStage) {
vistaPrincipale.load();
Scene scene = new Scene(vistaPrincipale.getRoot());
primaryStage.setScene(scene);
primaryStage.show();
}
and during the execution of the program I would like to change the view one with the view two, only that I could not really understand how I did not even find enough material to solve the problem, in swing it was enough to change the frame content bread
another problem that I have encountered is to launch a secondary panel like a jdialog in swing, I solved this problem by creating a new stage and using it in the following way, but to be honest it really seems like a very bad solution
public class InfoAutori {
private static final Logger LOGGER = LoggerFactory.getLogger(InfoAutori.class);
private Stage stage;
public void init(){
FXMLLoader load = new FXMLLoader();
Parent root = new AnchorPane();
try {
root = load.load(getClass().getResourceAsStream("InfoAutori.fxml"));
} catch (Exception e) {
LOGGER.error("Si e' verificato un errore del tipo: " +
e.getLocalizedMessage());
e.printStackTrace();
}
stage = new Stage();
Scene scene = new Scene(root);
stage.setScene(scene);
}
public void visualizza(){
stage.showAndWait();
}
}

Related

How to have a button open one scene and close the other (JavaFX)?

I have two scenes for Donuts and Coffee. On a clicking on button_orderDonuts it should open the scene for Donuts but close the scene for Coffee. While clicking on button_orderCoffee it should open the scene for Coffee but close the scene for Donuts. How can I have a button to have two functionalities. Also, I'm using SceneBuilder.
#FXML
private Button button_orderCoffee;
#FXML
private Button button_orderDonuts;
/**
* Go to Coffee UI
* #param event
*/
#FXML
void goToCoffee(ActionEvent event)
{
try
{
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setLocation(getClass().getResource("CoffeeView.fxml"));
Scene coffeeView = new Scene(fxmlLoader.load(), 445, 464);
Stage coffeeViewStage = new Stage();
coffeeViewStage.setTitle("Order Coffee");
coffeeViewStage.setScene(coffeeView);
coffeeViewStage.show();
CoffeeController coffeeController = fxmlLoader.getController();
coffeeController.setMainController(this);
}
catch (IOException e)
{
e.printStackTrace();
}
}
/**
* Go to Donut UI
* #param event
*/
#FXML
void goToDonut(ActionEvent event)
{
try
{
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setLocation(getClass().getResource("DonutView.fxml"));
Scene scene = new Scene(fxmlLoader.load(), 445, 464);
Stage stage = new Stage();
stage.setTitle("Order Donut");
stage.setScene(scene);
stage.show();
DonutController donutController = fxmlLoader.getController();
donutController.setMainController(this);
}
catch (IOException e)
{
e.printStackTrace();
}
}
So considering that you only need to create a new scene once it is often best practice to just load the scenes once, make a stage, and then modify which scene is loaded into the stage. Something like this would be better in essence, though it is even better still to have a class which loads the scenes and then passes them to a view to handle switching. I see that you are trying to getController() and then set it. From my experience it is best to load the fxml without a controllew ant then set it before calling load. Like mentioned previously, I spent time doing this recently (like hours and hours) and got a very reliable MVC system working, feel free to ask more, I am happy to share (it took a while so better to share the knowledge heh)
That said here is a hopefully working example.
#FXML
private Button button_orderCoffee;
#FXML
private Button button_orderDonuts;
private Scene coffeeScene;
private Scene donutScene;
private Stage stage;
void loadScenes() {
// Load coffee scene and set controller
FXMLLoader coffeeLoader = new FXMLLoader(getClass().getResource("CoffeeView.fxml"));
coffeeLoader.setController(this)
coffeeScene = new Scene(coffeeLoader.load());
// Load donut scene and set controller
FXMLLoader donutLoader = new FXMLLoader(getClass().getResource("DonutView.fxml"));
donutLoader.setController(this)
donutScene = new Scene(donutLoader.load());
}
/**
* Go to Coffee UI
* #param event
*/
#FXML
void goToCoffee(ActionEvent event) {
try {
stage.setTitle("Order Coffee");
stage.setScene(coffeeScene);
sStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Go to Donut UI
* #param event
*/
#FXML
void goToDonut(ActionEvent event) {
try {
stage.setTitle("Order Donut");
stage.setScene(donutScene);
stage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
This way you call load scenes once and create a single stage, just changing which scene is set each time. Again you will need to make sure fx:controller="..." in the fxml files is removed. Do not make them empty, remove it entirely. On any buttons where a function is called, lets say on the button_orderCoffee where onAction="#goToCoffee" is called, this will appear red like an error. That is simply because it cannot see a controller, but since a controller is being set before the scene is loaded the actions will work on compile and run. This allows you to make a single instance of the controller and set it, allowing you to reference the controller and other classes.
The scene loading does not have to be in its own function, it can just be called on load depending how things are setup. If this is in the MVC style I recommend putting this code in the view or the initial setup and referencing the controller.
As #Kleopatra mentioned, it is better practice to use seperate controllers for each scene. I would advise using a model or some other class to mediate between the two if you need to share data amongst the two

How to use JavaFX in Main

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);
}
}

Java FX crash when changing scene

I'm trying to make a POS using javaFX but whenever I try to change the scene it keeps crasing. Any ideas of how to fix?
Main class: https://pastebin.com/4bspSL9N
SceneManager: https://pastebin.com/SU99DVgf
OutputHelper.log() is just a system.out.println()
output log: https://pastebin.com/GZTPRgNp
You have not initialized your primaryStage in the SceneManager. Try adding this.primaryStage = primaryStage; in your setup method.
Try this in your SceneManager class:
public static void loadScreen(Parent parent) throws IOException {
Platform.runLater(() -> {
Stage stage = new Stage(StageStyle.UNDECORATED);
// stage.setMaximized(true);
stage.setFullScreen(true);
// stage.setFullScreenExitKeyCombination(KeyCombination.NO_MATCH);
Scene scene = new Scene(parent);
stage.setScene(scene);
stage.show();
});
}
Then to Load new screen use it like :
String Screen = "YourScreen.fxml";
Parent root = FXMLLoader.load(getClass().getResource(Screen));
SceneManager.loadScreen(root);
hope this will help
This a bit late to the party but we will post for posterity
We name all our Anchor Pane's so we know who they are ie mynamePane
Then when you click a Button to go somewhere you only need to know where you are and where you want to go
private void doSEARCH() throws IOException{
stage = (Stage)searchPane.getScene().getWindow();// pane you are ON
viewtxPane = FXMLLoader.load(getClass().getResource("tableview.fxml"));// pane you are GOING TO
Scene scene = new Scene(viewtxPane);// pane you are GOING TO
scene.getStylesheets().add(getClass().getResource("checkbook.css").toExternalForm());
stage.setScene(scene);
stage.setTitle("Check Book Transactions");
stage.show();
stage.sizeToScene();
stage.centerOnScreen();
}

Manage multiple screens JavaFX [duplicate]

This seems like it should be easy, so I must be missing something obvious: I have 4 standalone applications in the same package, us.glenedwards.myPackage,
myClass1 extends Application
myClass2 extends Application
etc...
I need each class to act as its own standalone application. Yet I want to be able to start the other 3 classes from the one I'm in by clicking a link. Android allows me to do this using Intents:
Intent intent = new Intent(this, EditData.class);
overridePendingTransition(R.layout.edit_data_scrollview, R.layout.state);
startActivity(intent);
I've tried starting myClass2 from myClass1 using
myClass2.launch("");
But I get an error, "Application launch must not be called more than once". The only way I can get it to work is if I remove both "extends application" and the start() method from myClass2, which means that myClass2 is no longer a standalone application.
How can I start myClass2, myClass3, or myClass4 from myClass1 with all 4 of them being standalone applications?
You can make this work by calling start(...) directly on a new instance of one of the Application subclasses, but it kind of feels like a bit of a hack, and is contrary to the intended use of the start(...) method. (Just semantically: a method called start in a class called Application should be executed when your application starts, not at some arbitrary point after it is already running.)
You should really think of the start method as the replacement for the main method in a traditional Java application. If you had one application calling another application's main method, you would (hopefully) come to the conclusion that you had structured things incorrectly.
So I would recommend refactoring your design so that your individual components are not application subclasses, but just plain old regular classes:
public class FirstModule {
// can be any Parent subclass:
private BorderPane view ;
public FirstModule() {
// create view; you could also just load some FXML if you use FXML
view = new BorderPane();
// configure view, populate with controls, etc...
}
public Parent getView() {
return view ;
}
// other methods as needed...
}
and, similarly,
public class SecondModule {
private GridPane view ;
public SecondModule {
view = new GridPane();
// etc etc
}
public Parent getView() {
return view ;
}
}
Now you can just do things like
FirstModule firstModule = new FirstModule();
Scene scene = new Scene(firstModule.getView());
Stage stage = new Stage();
stage.setScene(scene);
stage.show();
anywhere you need to do them. So you can create standalone applications for each module:
public class FirstApplication extends Application {
#Override
public void start(Stage primaryStage) {
Scene scene = new Scene(new FirstModule().getView());
primaryStage.setScene(scene);
primaryStage.show();
}
}
or you can instantiate them as part of a bigger application:
public class CompositeModule {
private HBox view ;
public CompositeModule() {
Button first = new Button("First Module");
first.setOnAction(e -> {
Parent view = new FirstModule().getView();
Scene scene = new Scene(view);
Stage stage = new Stage();
stage.initOwner(first.getScene().getWindow());
stage.setScene(scene);
stage.show();
});
Button second = new Button("Second Module");
second.setOnAction(e -> {
Parent view = new SecondModule().getView();
Scene scene = new Scene(view);
Stage stage = new Stage();
stage.initOwner(second.getScene().getWindow());
stage.setScene(scene);
stage.show();
});
HBox view = new HBox(10, first, second);
view.setAlignment(Pos.CENTER);
}
public Parent getView() {
return view ;
}
}
and
public class CompositeApplication extends Application {
#Override
public void start(Stage primaryStage) {
Scene scene = new Scene(new CompositeModule().getView(), 360, 150);
primaryStage.setScene(scene);
primaryStage.show();
}
}
The way I think of this is that Application subclasses represent an entire running application. Consequently it makes sense only to ever instantiate one such class once per JVM, so you should consider these inherently not to be reusable. Move any code you want to reuse into a different class somewhere.
have you tried this?
Runtime.getRuntime().exec("myClass1 [args]"); //put all args as you used in command
Also, handle/catch the exceptions, as needed.
I was right; it was a no-brainer. That's what I get for writing code on 4 hours of sleep:
myClass2 class2 = new myClass2();
try {
class2.start(stage);
} catch (Exception e) { e.printStackTrace(); } }

JavaFX UNDECORATED Stage not showing

I've got problem with may e(fx)clipse application. I want to show a splash screen upon application startup. I successfully created class implementing StartupProgressTrackerService, and got my stateReached method invoked. However I've got problems with javafx itself. I want to create Stage with StageStyle.UNDECORATED. However when i invoke stage.show() method stage isn't rendered immediately and appears just after main window is created. It works fine e.g. with StageStyle.UTILITY. It also renders correctly when i use showAndWait() method, but it stops my app from loading until i close the stage.
Here is my code:
public class MyStartupProgressTrackerService implements StartupProgressTrackerService {
private Stage stage;
public MyStartupProgressTrackerService() {
}
#Override
public OSGiRV osgiApplicationLaunched(IApplicationContext applicationContext) {
applicationContext.applicationRunning();
return StartupProgressTrackerService.OSGiRV.CONTINUE;
}
#Override
public void stateReached(ProgressState state) {
if (DefaultProgressState.JAVAFX_INITIALIZED.equals(state)) {
stage = new Stage(StageStyle.UNDECORATED);
stage.initModality(Modality.WINDOW_MODAL);
stage.setAlwaysOnTop(true);
ImageView view = null;
try {
view = new ImageView(SPLASH_IMAGE);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
BorderPane bp = new BorderPane();
bp.getChildren().add(view);
Scene scene = new Scene(bp, 400, 300);
stage.setScene(scene);
stage.show();
}
}
}
I found an ugly solution, but, at least, it works. I noticed that method stage.showAndWait() as a side effect finishes building all controls which haven't been rendered yet. So the trick is to initialize splash screen, and then create dummy stage, showAndWait() it and close() immediately. I know that this solution is far from ideal, so i would appreciate it if someone could show me alternate way to make it work :)
My code:
public void showSplash() {
splashScreen = createSplashScreen();
Stage stage2 = new Stage(StageStyle.TRANSPARENT);
splashScreen.show();
Platform.runLater(new Runnable() {
#Override
public void run() {
stage2.close();
}
});
stage2.showAndWait();
}
private Stage createSplashScreen() {
Stage stage = new Stage(StageStyle.UNDECORATED);
stage.setAlwaysOnTop(true);
VBox vbox = new VBox();
vbox.getChildren().add(new ImageView(splashImage));
Scene scene = new Scene(vbox, 400, 300);
stage.setScene(scene);
return stage;
}

Categories

Resources