JavaFX - Splitting GUI into separate classes while using tabs - java

I am trying to make a program with a tabbed GUI where each tab's contents are their own class. I essentially want to do what is done here, but with tabs. Mere is the Manager class:
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.stage.Stage;
public class Manager extends Application {
private TabPane tabPane;
private Tab dcTab;
public Manager() {
dcTab = new Tab();
tabPane = new TabPane();
DistributionCenter dcMenu = new DistributionCenter();
dcTab.setText("Distribution Center");
dcTab.setContent(dcMenu);
tabPane.getTabs().add(dcTab);
}
#Override
public void start(Stage primaryStage) throws Exception {
Group root = new Group();
Scene scene = new Scene(tabPane, 600, 500);
DistributionCenter dcMenu = new DistributionCenter();
root.getChildren().add(dcMenu);
dcTab.setContent(dcMenu);
primaryStage.setScene(scene);
primaryStage.setTitle("909th Wing");
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
And here is my DistributionCenter class:
import javafx.scene.control.Button;
import javafx.scene.layout.Pane;
public class DistributionCenter extends Pane {
private Button testBt1;
public DistributionCenter() {
Pane dcMenu = new Pane();
testBt1 = new Button("Button");
dcMenu.getChildren().addAll(testBt1);
testBt1.setLayoutX(30);
testBt1.setLayoutY(100);
}
}
Note that the contents of DistributionCenter are just a test at this point.

You are never adding your Button to the actual DistributionCenter pane. Instead, you are creating a new Pane within that class and adding the button to it.
Remember, DistributionCenter is a Pane so it has its own children. You do not need to create a new Pane within it.
Update your DistributionCenter class to just configure itself:
public DistributionCenter() {
testBt1 = new Button("Button");
getChildren().addAll(testBt1);
}
That will solve your problem, but you should never extend a class unless you need to implement different behavior. If you are just configuring a Node like this, you should just create an instance of a Pane and configure it properly.

Related

Is there a way to "autofit" elements on a page so they take up the entire canvas

In JavaFX, is there a way to "autofit" elements on a page so they take up the entire thing?
Currently, I'm trying to make the window have two buttons that together take up the entire canvas, but I am not sure how to do that, given that it is possible to stretch the window, etc. I've tried playing around with Button.setPrefSize, but the button size stays the same, it just shows you a window with two outsized buttons, the text of which is not visible.
What I currently have
What I want (but for any window size)
Here's one way (code here but also possible in Scene Builder and FXML):
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.stage.Stage;
public class TestApplication extends Application {
#Override
public void start(Stage stage) throws Exception {
Button button1 = new Button("Button1");
HBox.setHgrow(button1, Priority.SOMETIMES);
button1.setMaxWidth(Double.MAX_VALUE);
button1.setMaxHeight(Double.MAX_VALUE);
Button button2 = new Button("Button2");
HBox.setHgrow(button2, Priority.SOMETIMES);
button2.setMaxWidth(Double.MAX_VALUE);
button2.setMaxHeight(Double.MAX_VALUE);
HBox hBox = new HBox(button1, button2);
AnchorPane.setLeftAnchor(hBox, 0.0);
AnchorPane.setRightAnchor(hBox, 0.0);
AnchorPane.setTopAnchor(hBox, 0.0);
AnchorPane.setBottomAnchor(hBox, 0.0);
AnchorPane rootContainer = new AnchorPane(hBox);
Scene scene = new Scene(rootContainer, 600, 600);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}

How to display some values of javafx combo box before any click on it?

I use a combo that works nice. The only thing i would like to add is to diplay some items(~10) of this box by default at start . I tried to find this property but a hell to find this among all methods.
If somebody knows how to to that
I have the same question for Menubutton
Thanks
Just call show() on the ComboBox. Here is an example:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class ComboTest extends Application {
#Override
public void start(Stage stage) {
ComboBox<String> combo = new ComboBox<>();
for (int i = 1 ; i <= 20 ; i++) combo.getItems().add("Item "+i);
BorderPane root = new BorderPane();
root.setTop(combo);
Scene scene = new Scene(root, 650, 400);
stage.setScene(scene);
stage.show();
combo.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
The same thing works for MenuButton.

problem when trying JavaFX EventHandler ActionEvent with JOptionPane on Mac

after run this and press {play} button java stops and not respond on Mac
so I don't know what is the problem , I tried it in another another device (macOS )and same result.
any one have an idea !
import javafx.application.Application;
import javafx.event.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.*;
import javax.swing.*;
public class MyFX_event_1 extends Application{
public static void main(String[] args) { Application.launch(args); }
public void start(Stage primaryStage){
// Create a pane and set its properties
HBox pane = new HBox(10);
Button btn1 = new Button("PLAY");
MyHandlerClass handler1 = new MyHandlerClass();
btn1.setOnAction(handler1);
pane.getChildren().addAll(btn1);
// Create a scene and place it in the stage
Scene scene = new Scene(pane, 100, 100);
primaryStage.setTitle("HandleEvent"); // Set the stage title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.show(); // Display the stage
}
class MyHandlerClass implements EventHandler<ActionEvent> {
#Override
public void handle(ActionEvent e) {
JOptionPane.showMessageDialog(null , "game will start");}
}
}

JavaFx - Method Undefined

I have to create a program using JavaFX that creates a pane with a ball in it. There are four buttons that move the ball either left, right, up, or down. I don't understand why when I go to define each method (like .left() shown) the method call above remains an error that tells me it is undefined.
Main class:
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
public class MoveTheBall extends Application {
#Override
public void start(Stage primaryStage) {
StackPane pane = new StackPane();
Circle circle = new Circle(20);
circle.setStroke(Color.BLACK);
circle.setFill(Color.WHITE);
pane.getChildren().add(circle);
HBox hBox = new HBox();
hBox.setSpacing(10);
hBox.setAlignment(Pos.CENTER);
Button btLeft = new Button("Left");
Button btRight = new Button("Right");
Button btUp = new Button("Up");
Button btDown = new Button("Down");
hBox.getChildren().add(btLeft);
hBox.getChildren().add(btRight);
hBox.getChildren().add(btUp);
hBox.getChildren().add(btDown);
BorderPane borderPane = new BorderPane();
borderPane.setCenter(pane);
borderPane.setBottom(hBox);
BorderPane.setAlignment(hBox, Pos.CENTER);
Scene scene = new Scene(borderPane, 300, 200);
primaryStage.setTitle("Move The Ball");
primaryStage.setScene(scene);
primaryStage.show();
}
}
Buttons class:
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
public class ControlBall extends Application {
private MoveTheBall moveTheBall = new MoveTheBall();
#Override
public void start(Stage primaryStage) {
HBox hBox = new HBox();
hBox.setSpacing(5);
hBox.setAlignment(Pos.CENTER);
Button btLeft = new Button("Left");
Button btRight = new Button("Right");
Button btUp = new Button("Up");
Button btDown = new Button("Down");
hBox.getChildren().add(btLeft);
hBox.getChildren().add(btRight);
hBox.getChildren().add(btUp);
hBox.getChildren().add(btDown);
btLeft.setOnAction(new LeftHandler());
btRight.setOnAction(new RightHandler());
btUp.setOnAction(new UpHandler());
btDown.setOnAction(new DownHandler());
BorderPane borderPane = new BorderPane();
borderPane.setCenter(moveTheBall);
borderPane.setBottom(hBox);
BorderPane.setAlignment(hBox, Pos.CENTER);
Scene scene = new Scene(borderPane, 200, 150);
primaryStage.setTitle("Move The Ball");
primaryStage.setScene(scene);
primaryStage.show();
}
class LeftHandler implements EventHandler<ActionEvent> {
#Override
public void handle(ActionEvent e) {
moveTheBall.left(); // error because no class yet
}
}
class RightHandler implements EventHandler<ActionEvent> {
#Override
public void handle(ActionEvent e) {
moveTheBall.right(); // error because no class yet
}
}
class UpHandler implements EventHandler<ActionEvent> {
#Override
public void handle(ActionEvent e) {
moveTheBall.up(); // error because no class yet
}
}
class DownHandler implements EventHandler<ActionEvent> {
#Override
public void handle(ActionEvent e) {
moveTheBall.down(); // error because no class yet
}
}
}
class moveTheBall extends StackPane {
private Circle ball = new Circle(20);
public moveTheBall() {
getChildren().add(ball);
ball.setStroke(Color.BLACK);
ball.setFill(Color.WHITE);
}
public void left() {
ball.setCenterX(-2.0);
ball.setCenterY(-2.0);
}
}
The line borderPane.setCenter(moveTheBall); is giving me problems as well. "The method setCenter(Node) in the type BorderPane is not applicable for the arguments (MoveTheBall)"
I'm pretty new to JavaFX, but I'm gonna do the best I can here.
I would suggest instead of doing totally separate classes for controlling the ball, moving the ball, and handling each button, look into using lambda expressions to simplify the code and reduce your room for error. For example, you can set what the btRight button does by writing a line like this:
btRight.setOnAction(e -> {
//if the ball is inside the right limit
//Move the ball to the right
});
You can write these expressions directly into your start() method, and avoid defining inner classes, as well as a separate class for the control.
As far as why you are getting an error, my best guess (as i said, I'm new to this) is that moveTheBall() is a constructor for the MoveTheBall class, but it is being called as a method.
Hope this helps.

MiGLayout sizing not working properly in JavaFX

Here's my snippet:
package javafxdemo;
import org.tbee.javafx.scene.layout.MigPane;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Stage;
public class FXDemo extends Application {
#Override
public void start (Stage stage) throws Exception {
MigPane root = new MigPane();
Scene scene = new Scene(root);
Button b = new Button("Hello");
root.getChildren().add(b);
stage.setScene(scene);
stage.setTitle("FX");
stage.show();
}
public static void main (String[] args) {
launch (args);
}
}
When running the gui doesn't show properly: the frame size is smaller than the button. Why does it happens? In HBox Layout when setting the scene it is automatically resized, so why with MiGLayout it doesn't work?
I'm using MigLayout 4.3
So, I filed an issue and later found out a workaround for this:
just add stage.sizeToScene() after stage.show().

Categories