I'm very new to JavaFX. I am using a grid pane to keep my items centered on the page regardless of how the window is resized. I want to add a menu that runs along the top. I quickly found out grid.setTop(menuBar) is not a member function of grid pane. Is there a way to this?
Can I create two different types of panes in one scene? IE, a GridPane to center items and a BorderPane to get the menu up top? Or should I use CSS styling to get the menubar at the top?
Here is some code I'm using:
public void start(Stage primaryStage) {
try {
primaryStage.setTitle("Bapu Inventory");
BorderPane root = new BorderPane();
GridPane grid = new GridPane();
grid.setAlignment(Pos.CENTER);
grid.setHgap(10);
grid.setVgap(10);
grid.setPadding(new Insets(25, 25, 25, 25));
Text scenetitle = new Text("Welcome");
grid.add(scenetitle, 0, 0, 1, 1);
MenuBar menuBar = new MenuBar();
menuBar.prefWidthProperty().bind(primaryStage.widthProperty());
//This is the line I can't figure out. How do I get this to position at top left?
grid.setTop(menuBar);
Any help would be greatly appreciated here. I looked through the documentation Oracle provides but didn't find this feature listed anywhere.
Check if this is what you want:
public void start(Stage primaryStage) {
try {
BorderPane root = new BorderPane();
//Create your menu
final Menu menu1 = new Menu("File");
final Menu menu2 = new Menu("Options");
final Menu menu3 = new Menu("Help");
MenuBar menuBar = new MenuBar();
menuBar.getMenus().addAll(menu1, menu2, menu3);
//Your GridPane
GridPane grid = new GridPane();
grid.setAlignment(Pos.CENTER);
grid.setHgap(10);
grid.setVgap(10);
grid.setPadding(new Insets(25, 25, 25, 25));
Text scenetitle = new Text("Welcome");
grid.add(scenetitle, 0, 0, 1, 1);
//Add them to root (BorderPane)
root.setTop(menuBar);
root.setCenter(grid);
Scene scene = new Scene(root,400,400);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
Related
I am testing the JavaFX ScrollPane class and realized that it is not working as I expect, I don't know why. I have the following code:
public class Client3 extends Application {
int indexMsg = 0;
Button send;
GridPane root;
ScrollPane msgPane;
GridPane msgPaneContent;
FlowPane writePane;
TextField writeMsg;
Scene scene;
#Override
public void start(Stage primaryStage) {
root = new GridPane();
root.setAlignment(Pos.CENTER);
root.setVgap(10);
root.setPadding(new Insets(10, 10, 10, 10));
msgPane = new ScrollPane();
msgPane.setPrefSize(280, 280);
msgPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
msgPaneContent = new GridPane();
msgPaneContent.setPrefWidth(270);
msgPaneContent.setVgap(10);
writePane = new FlowPane(10, 10);
writePane.setAlignment(Pos.CENTER);
writePane.setPrefWidth(280);
writeMsg = new TextField();
writeMsg.setPrefWidth(150);
writeMsg.setPromptText("Write your message");
writePane.getChildren().add(writeMsg);
GridPane.setConstraints(msgPane, 0, 0);
GridPane.setConstraints(writePane, 0, 1);
msgPane.setContent(msgPaneContent);
root.getChildren().addAll(msgPane, writePane);
writeMsg.setOnAction((ev) -> {
if (!writeMsg.getText().isEmpty()) {
TextArea msg = new TextArea(writeMsg.getText());
msg.setMaxWidth(135);
msg.setPrefRowCount(msg.getLength() / 21 + 1);
msg.setWrapText(true);
GridPane.setConstraints(msg, 0, indexMsg);
indexMsg++;
writeMsg.deleteText(0, writeMsg.getText().length());
msgPaneContent.getChildren().add(msg);
msgPane.setVvalue(1.0);
}
});
scene = new Scene(root, 300, 300);
primaryStage.setTitle("Chat App");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Basically, I have a GridPane as the root with a ScrollPane and a GridPane as its children. The ScrollPane has a children GridPane. There is a TextField with an EventHandler which generates a TextArea inside the GridPane (the ScrollPane's children). Each TextArea object is created in the vertical direction, downwards. I want to set the scrollbar always at its maximum value (setVvalue(1.0)) each time a new TextArea is added. The thing is that it doesn't seem to work as it should because the vertical value is never set to the maximum after handling the event, but it seems to be set to the maximum value that it had before handling it (the bottom of the previous TextArea added).
Any solution for this? Thanks in advance.
I would like to declare a JavaFX GridPane of two panels, the left one containing a push button. When the push button is clicked a LineChart is displayed in the right hand panel. The coding would presumably look like this:
public class FormLineChart extends Application {
#Override
public void start(Stage stage) {
stage.setTitle("A Title");
//Create the grid for defining the GUI
GridPane grid = new GridPane();
// add gui objects to grid
...
//Create the chart
final LineChart<Number, Number> lineChart = new LineChart<>(xAxis, yAxis);
...
// Create the series and display the lineChart
lineChart.getData().add(series);
stage.setScene(scene);
Scene scene = new Scene(grid, 427, 319);
//How do we add 'lineChart' to scene as well as keeping 'grid'?
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Specifically is it possible to combine 'grid' and 'lineChart' in one scene? At the moment only the GUI is displayed because on is forced to set the scene to the grid.
As #James_D said you simply need another container to achieve that. A Pane can contain GUI controls as well as another Pane.
In the example below I put a GridPane with few buttons inside a BorderPane that divides the window into right and left part.
#Override
public void start(Stage stage) {
stage.setTitle("A Title");
// Root element
BorderPane root = new BorderPane();
// GridPane
GridPane grid = new GridPane();
grid.setPadding(new Insets(10,10,10,10));
grid.setVgap(10);
grid.add(new Button("Button 1"), 0, 0);
grid.add(new Button("Button 2"), 0, 1);
grid.add(new Button("Button 3"), 0, 2);
// Chart
final NumberAxis xAxis = new NumberAxis();
final NumberAxis yAxis = new NumberAxis();
final LineChart<Number, Number> lineChart = new LineChart<>(xAxis, yAxis);
XYChart.Series series = new XYChart.Series();
series.setName("Chart");
series.getData().add(new XYChart.Data(1, 5));
series.getData().add(new XYChart.Data(2, 10));
lineChart.getData().add(series);
root.setLeft(grid);
root.setRight(lineChart);
Scene scene = new Scene(root, 600, 300);
stage.setScene(scene);
stage.show();
}
I'm trying to get two tabs, each with their own little form that contain labels and textfields/textareas. I thought my making a "Master" VBox that should display everything but nothing other than the tabs are showing and neither am i getting any errors.
How do I add them to the scene?
// Label and Button variables
private Label fname,lname, appt, AppointmentInfo;
protected String input;
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("Person Appointments");
primaryStage.setWidth(500);
primaryStage.setHeight(500);
//Create and set Tab Names
Tab InfoTab = new Tab();
Tab ApptTab = new Tab();
InfoTab.setText("PersonInfo");
ApptTab.setText("Appointments");
// VBoxes
VBox personInfoBox = new VBox();
VBox FirstBox = new VBox();
VBox appointmentBox = new VBox();
// Setup labels and fields
fname = new Label();
lname = new Label();
appt = new Label();
AppointmentInfo = new Label();
fname.setText("First Name");
lname.setText("Last Name");
appt.setText("Appt Count");
AppointmentInfo.setText("Appt Info");
// Text Fields
TextField firstNameText = new TextField();
TextField lastNameText = new TextField();
TextField appointmentText = new TextField();
TextArea apptInfo = new TextArea();
firstNameText.setText("First Name Here");
lastNameText.setText("Last Name Here");
appointmentText.setText("Appointment Here");
personInfoBox.getChildren().add(fname);
personInfoBox.getChildren().addAll(firstNameText);
personInfoBox.getChildren().add(lname);
personInfoBox.getChildren().addAll(lastNameText);
appointmentBox.getChildren().add(AppointmentInfo);
appointmentBox.getChildren().addAll(apptInfo);
// Grid for Tabs
GridPane grid = new GridPane();
GridPane grid2 = new GridPane();
grid.add(fname, 0, 0);
grid.add(firstNameText, 0, 1);
grid.add(lname, 1, 0);
grid.add(lastNameText, 1, 1);
grid.add(appt, 2, 0);
grid.add(appointmentText, 2, 1);
grid2.add(AppointmentInfo, 0, 0);
grid2.add(apptInfo, 0, 1);
InfoTab.setContent(grid);
ApptTab.setContent(grid2);
// TabPane
TabPane tabPane = new TabPane();
tabPane.getTabs().add(InfoTab);
tabPane.getTabs().add(ApptTab);
InfoTab.setClosable(false);
ApptTab.setClosable(false);
InfoTab.setContent(personInfoBox);
ApptTab.setContent(appointmentBox);
VBox one = new VBox(tabPane, personInfoBox);
Scene scene = new Scene(one, 500, 500);
primaryStage.setScene(scene);
primaryStage.show();`
You can't assign a Node more than once to the SceneGraph:
A node may occur at most once anywhere in the scene graph. Specifically, a node must appear no more than once in all of the following: as the root node of a Scene, the children ObservableList of a Parent, or as the clip of a Node.
http://docs.oracle.com/javase/8/javafx/api/javafx/scene/Node.html
You assigned e.g. lname to personInfoBox AND grid. So finally lname will be assigned to grid only. Then you set grid as content for a Tab and after that you set personInfoBox as content, which is now empty
I have a GridPane that i fill dynamically, then I display it, the problem is: if the rows are so many, then the rows in the bottom don't get displayed, what i want is to add a scrollbar so that I can display all of the rows, here is the code but it's not working:
BudgetManager bManager = new BudgetManager();
List<Debt> debts = bManager.getDebts();
GridPane topLevel = new GridPane();
topLevel.setAlignment(Pos.TOP_CENTER);
int row = 0;
double totatB = 0, totalS = 0;
for (Debt d : debts) {
//fill GridPane
}
ScrollBar sc = new ScrollBar();
sc.setMin(0);
sc.setMax(350);
sc.setVisibleAmount(20);
sc.setOrientation(Orientation.VERTICAL);
sc.setUnitIncrement(10);
sc.setBlockIncrement(50);
sc.setPrefWidth(20);
sc.valueProperty().addListener((ObservableValue<? extends Number> ov, Number old_val, Number new_val) -> {
topLevel.setLayoutY(-new_val.doubleValue());
}
});
HBox box = new HBox();
box.getChildren().addAll(topLevel, sc);
HBox.setHgrow(topLevel, Priority.ALWAYS);
Scene scene = new Scene(box, 1200, 600);
stage.setScene(scene);
stage.show();
SOLVED
here is the solution, thanks to keuleJ, using ScrollPane instead of ScrollBar:
ScrollPane scroll = new ScrollPane();
GridPane topLevel = new GridPane();
scroll.setContent(topLevel);
scroll.setHbarPolicy(ScrollBarPolicy.ALWAYS);
scroll.setVbarPolicy(ScrollBarPolicy.AS_NEEDED);
scroll.setFitToWidth(true);
scroll.setFitToHeight(true);
Scene scene = new Scene(scroll, 1200, 600); // Manage scene size
Use fitToWidth or fitToHeight properties.
See the docs:
https://docs.oracle.com/javafx/2/api/javafx/scene/control/ScrollPane.html
I am having a resize issue when content is added and removed from a JavaFX BorderPane. The BorderPane content is not being resized until the window is manually resized. I have written a small test app to model this behavior. The application builds a BorderPane that contains a rectangle embedded within a StackPane at the center of the BorderPane. Along the bottom of the BorderPane there is a VBox and HBox that contain text and a separator. There is a menu item that removes the content from the bottom of the BorderPane (MoveText -> Right) and adds similar content to the right position of the BorderPane.
When the text is added to the right position of the BorderPane, the rectangle overlaps the text. In otherwords the content of the BorderPane center is overlapping the content in the BorderPane right.
I saw the following link -
https://stackoverflow.com/questions/5302197/javafx-bug-is-there-a-way-to-force-repaint-this-is-not-a-single-threading-pr
Calling requestLayout does not seem to help. I have also tried calling impl_updatePG and impl_transformsChanged on various nodes in the graph. I got this idea from this thread - https://forums.oracle.com/forums/thread.jspa?threadID=2242083
public class BorderPaneExample extends Application
{
private BorderPane root;
private StackPane centerPane;
#Override
public void start(Stage primaryStage) throws Exception
{
root = new BorderPane();
root.setTop(getMenu());
root.setBottom(getBottomVBox());
centerPane = getCenterPane();
root.setCenter(centerPane);
Scene scene = new Scene(root, 900, 500);
primaryStage.setTitle("BorderPane Example");
primaryStage.setScene(scene);
primaryStage.show();
}
private MenuBar getMenu()
{
MenuBar menuBar = new MenuBar();
MenuItem rightMenuItem = new MenuItem("Right");
rightMenuItem.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
root.setRight(getRightHBox());
root.setBottom(null);
root.requestLayout();
}
});
MenuItem bottomMenuItem = new MenuItem("Bottom");
bottomMenuItem.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
root.setRight(null);
root.setBottom(getBottomVBox());
}
});
Menu menu = new Menu("Move text");
menu.getItems().add(rightMenuItem);
menu.getItems().add(bottomMenuItem);
menuBar.getMenus().addAll(menu);
return menuBar;
}
private HBox getRightHBox()
{
HBox hbox = new HBox();
VBox vbox = new VBox(50);
vbox.setPadding(new Insets(0, 20, 0, 20));
vbox.setAlignment(Pos.CENTER);
vbox.getChildren().addAll(new Text("Additional Info 1"),
new Text("Additional Info 2"), new Text("Additional Info 3"));
hbox.getChildren().addAll(new Separator(Orientation.VERTICAL), vbox);
return hbox;
}
private VBox getBottomVBox()
{
VBox vbox = new VBox();
HBox hbox = new HBox(20);
hbox.setPadding(new Insets(5));
hbox.setAlignment(Pos.CENTER);
hbox.getChildren().addAll(new Text("Footer Item 1")
, new Text("Footer Item 2"), new Text("Footer Item 3"));
vbox.getChildren().addAll(new Separator(), hbox);
return vbox;
}
private StackPane getCenterPane()
{
StackPane stackPane = new StackPane();
stackPane.setAlignment(Pos.CENTER);
final Rectangle rec = new Rectangle(200, 200);
rec.setFill(Color.DODGERBLUE);
rec.widthProperty().bind(stackPane.widthProperty().subtract(50));
rec.heightProperty().bind(stackPane.heightProperty().subtract(50));
stackPane.getChildren().addAll(rec);
return stackPane;
}
public static void main(String[] args)
{
Application.launch(args);
}
}
Any suggestions would be appreciated.
Thanks
For the sake of having an answer:
The StackPane needs to have its minimum size set in order to do clipping. So if you explicitly add stackPane.setMinSize(0, 0); to the getCenterPane() method, it should fix your problem.
So your getCenterPane() method would now look like this:
private StackPane getCenterPane()
{
StackPane stackPane = new StackPane();
stackPane.setMinSize(0, 0);
stackPane.setAlignment(Pos.CENTER);
final Rectangle rec = new Rectangle(200, 200);
rec.setFill(Color.DODGERBLUE);
rec.widthProperty().bind(stackPane.widthProperty().subtract(50));
rec.heightProperty().bind(stackPane.heightProperty().subtract(50));
stackPane.getChildren().addAll(rec);
return stackPane;
}