How to set menu bar with child window in javafx? - java

vbox2.setPadding(new Insets(3));
vbox2.setSpacing(3);
vbox2.getChildren().addAll( browser1,browser);
HBox.setHgrow(vbox2, Priority.ALWAYS);
hbox.setPadding(new Insets(20));
// StackPane.setMargin(hbox, new Insets(20));
hbox.getChildren().addAll(vbox, vbox2);
root.getChildren().add(hbox);
Scene scene = new Scene(root, 500, 300); // the stack pane is the root node
//scene.setCursor(Cursor.CROSSHAIR);
MenuBar menuBar = new MenuBar();
Menu menu = new Menu("Window");
menu.getItems().add(new MenuItem("browser"));
menu.getItems().add(new MenuItem("img"));
menuBar.getMenus().add(menu);
menuBar.prefWidthProperty().bind(primaryStage.widthProperty());
BorderPane borderPane = new BorderPane();
borderPane.prefHeightProperty().bind(scene.heightProperty());
borderPane.prefWidthProperty().bind(scene.widthProperty());
borderPane.setTop(menuBar);
root.getChildren().add(borderPane);
primaryStage.setScene(scene);
primaryStage.show();
}
here is the code part where is im adding menu bar with border pane but its hang my application as im not able to login or do anythng and i had to add child window also for reference im attaching the image

This is a very basic and minimal example of handling views in the center of a BorderPane by MenuItems:
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.layout.BorderPane;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
BorderPane root = new BorderPane();
// create the menu bar with a menu and its items
MenuBar menuBar = new MenuBar();
Menu mainMenu = new Menu("Window");
MenuItem browserItem = new MenuItem("browser");
MenuItem imageItem = new MenuItem("image");
MenuItem closeItem = new MenuItem("exit");
// create some different contents for the center of the border pane
Label imagePlaceHolder = new Label("IMAGE TO BE SHOWN");
WebView browser = new WebView();
WebEngine browserEngine = browser.getEngine();
// set the actions for the different items
closeItem.setOnAction(action -> {
System.exit(0);
});
imageItem.setOnAction(action -> {
root.setCenter(imagePlaceHolder);
});
browserItem.setOnAction(action -> {
root.setCenter(browser);
browserEngine.load("http://www.google.com");
});
// add items to the menu, then the menu to the menu bar
mainMenu.getItems().addAll(closeItem, browserItem, imageItem);
menuBar.getMenus().add(mainMenu);
// set the scene
Scene scene = new Scene(root,400,400);
root.setTop(menuBar);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
I hope it helps…
EDIT
I just saw your newest edit… In case you really need different windows (scenes or stages), the approach will get more complex. Readers have to get more information about the different windows (like how you create them, handle their contents and more).

Related

How do i display my MenuBar across all my scenes in JavaFX

I am new to JavaFX
I wrote this code however, I dont know how to Display the Menu Bar in all my Scenes. Also I would like to create/fill my scenes with the Layout in my HelloApplication (however thats another issue).
I have a controller, for setting the Stage and launching it.
My MenuBar is in the class MenuLeiste, but I would like it to appear in my Credits class aswell. Im very sorry for the lack of comments and the Layout of this comment.
public class HelloApplication extends Application {
public class Main {
public static void main(String[] args) {
launch(args);
}
}
#Override
public void start(Stage primaryStage) throws Exception {
//set window as primaryStage
Stage window = primaryStage;
//Layout of MenuLeiste is put in l1 and setted as scene1
MenuLeiste l1 = new MenuLeiste();
//menuscene gets its objects fromsceneViewMenu
Scene menuscene = new Scene(l1.sceneViewMenu());
window.setScene(menuscene);
window.setHeight(600);
window.setWidth(800);
window.setTitle("Game Title");
window.show();
}
}
My MenuLeiste class
import javafx.scene.Scene;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class MenuLeiste {
public VBox sceneViewMenu() {
MenuBar menuBar = new MenuBar();
VBox menuBox = new VBox(menuBar);
Menu dataMenu = new Menu("Data");
MenuItem exitItem = new MenuItem("Exit");
exitItem.setOnAction(e -> System.exit(0));
Menu extrasMenu = new Menu("Extras");
MenuItem creditsItem = new MenuItem("Credits");
creditsItem.setOnAction(e -> {
Credits c = new Credits();
Scene scene3 = new Scene(c.sceneView3());
Stage window = (Stage) menuBox.getScene().getWindow();
window.setScene(scene3);
});
extrasMenu.getItems().addAll(creditsItem);
dataMenu.getItems().addAll( exitItem);
menuBar.getMenus().addAll(dataMenu,extrasMenu);
//the scenes layout is saved in layout1
VBox layout1 = new VBox(20);
layout1.getChildren().addAll(menuBox);
return layout1;
}
}
My Credits Class
package view;
import javafx.scene.Scene;`
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;`
public class Credits {
public VBox sceneView3()
{
Label label = new Label("Thanks");
Button backButton = new Button("Back");
backButton.setOnAction(e -> {
MenuLeiste l1 = new MenuLeiste();
Scene menuscene = new Scene(l1.sceneViewMenu());
Stage window = (Stage) backButton.getScene().getWindow();
window.setScene(menuscene);
});
VBox layout1 = new VBox(20);
layout1.getChildren().addAll(label, backButton);
return layout1;
}
}
When you want a node, or a group of nodes, to exist between different "scenes", often the best solution is to not replace the Scene. Instead, you'll want to modify the nodes displayed in the current scene. For example, in your case, you could have a BorderPane as the root of the scene with the MenuBar set as the top node. Then you replace the center node when you want to change the "view".
Here's a minimal runnable example demonstrating this concept. It makes use of "callbacks" to modify the center node of the BorderPane, while using the same MenuBar instance throughout. Though note the example only consists of views. If you have a backing model (i.e., data, business logic, etc.), you'll want to modify the code so you can pass it around. Also, if you write your application similarly to this example, it might be prudent to have all the views implement a common interface in a real application.
I don't have a separate "view class" for the menu bar, but that doesn't mean you can't have one (might even be better that way).
Main.java:
import java.util.function.Consumer;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
var root = new BorderPane();
root.setTop(createMenuBar(root::setCenter));
root.setCenter(new TitleView().getNode());
primaryStage.setScene(new Scene(root, 600, 400));
primaryStage.setTitle("Demo");
primaryStage.show();
}
private MenuBar createMenuBar(Consumer<Node> onUpdateView) {
var exitItem = new MenuItem("Exit");
exitItem.setOnAction(e -> Platform.exit());
var creditsItem = new MenuItem("Credits");
creditsItem.setOnAction(e -> {
e.consume();
var view = new CreditsView();
view.setOnGoBack(() -> onUpdateView.accept(new TitleView().getNode()));
onUpdateView.accept(view.getNode());
});
return new MenuBar(
new Menu("File", null, exitItem),
new Menu("Extras", null, creditsItem)
);
}
}
TitleView.java:
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
public class TitleView {
private Node node;
public Node getNode() {
if (node == null) {
node = new StackPane(new Label("Welcome!"));
}
return node;
}
}
CreditsView.java:
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
public class CreditsView {
private Runnable onGoBack;
private Node node;
public Node getNode() {
if (node == null) {
var stack = new StackPane();
stack.setPadding(new Insets(10));
var label = new Label("Credits View");
stack.getChildren().add(label);
var goBackBtn = new Button("Go back");
goBackBtn.setOnAction(e -> {
e.consume();
if (onGoBack != null) {
onGoBack.run();
}
});
stack.getChildren().add(goBackBtn);
StackPane.setAlignment(goBackBtn, Pos.TOP_LEFT);
node = stack;
}
return node;
}
public void setOnGoBack(Runnable action) {
onGoBack = action;
}
}
Here is some basic code that should be easy for a beginner to understand.
The main layout and the potential views to be displayed within it are created upfront.
A menu bar is placed at the top of the border pane in the main layout.
Menu items can be used to switch between views by setting the node to be currently displayed in the center of the border pane.
The existing views are reused rather than being recreated on each navigation.
You could not store references to existing views and create new views on each navigation if preferred.
The views themselves are just nodes, so the example could easily be adapted to use FXML because the output of the FXML loader is also a node. The same goes for anything else which may generate a node to be used as a view in this fashion.
Operation
The scene is initially displayed and the user clicks on the "View" menu to show the list of available views.
The user selects the "View Two" menu item and the second view is displayed. The application menu remains visible and can be used for future operations.
Sample Code
import javafx.application.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;
public class ViewSwitcherApp extends Application {
private BorderPane layout;
private final Node viewOne = new ViewOne();
private final Node viewTwo = new ViewTwo();
#Override
public void start(Stage stage) throws Exception {
// View menu
MenuItem viewOneMenuItem = new MenuItem("View One");
viewOneMenuItem.setOnAction(e -> setView(viewOne));
MenuItem viewTwoMenuItem = new MenuItem("View Two");
viewTwoMenuItem.setOnAction(e -> setView(viewTwo));
Menu viewMenu = new Menu(
"View", null,
viewOneMenuItem, viewTwoMenuItem
);
// File menu
MenuItem exitMenuItem = new MenuItem("Exit");
exitMenuItem.setOnAction(e -> Platform.exit());
Menu fileMenu = new Menu(
"File", null,
exitMenuItem
);
MenuBar menuBar = new MenuBar(
fileMenu, viewMenu
);
menuBar.setMinSize(MenuBar.USE_PREF_SIZE, MenuBar.USE_PREF_SIZE);
// Layout scene
layout = new BorderPane();
layout.setTop(menuBar);
setView(viewOne);
stage.setScene(
new Scene(layout, 300, 200)
);
stage.show();
}
private void setView(Node view) {
layout.setCenter(view);
}
public static void main(String[] args) {
launch(args);
}
}
class ViewOne extends StackPane {
public ViewOne() {
setStyle("-fx-background-color: lightblue; -fx-font-size: 30px;");
getChildren().add(new Label("View One"));
}
}
class ViewTwo extends StackPane {
public ViewTwo() {
setStyle("-fx-background-color: cornsilk; -fx-font-size: 30px;");
getChildren().add(new Label("View Two"));
}
}

JavaFX ChoiceBox in a MenuBar

I make an application with JavaFX.
I want to have a ChoiceBox in my top MenuBar to select the language.
I want to disable the blue surrounding when the language control is selected. How do I do this?
Set the Id of the Menu that contains the ChoiceBox to transparent and use the following CSS:
#transparent:hover,
#transparent:focused,
#transparent:showing {
-fx-background: transparent;
}
Unfortunately I couldn't figure out how to do this with transparent as a class yet.
Example
Output:
Code:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class Foo extends Application {
#Override
public void start(Stage stage) throws Exception {
Menu fileMenu = new Menu("File");
ChoiceBox<String> languageBox = new ChoiceBox<String>();
languageBox.getItems().addAll("English", "Deutsch");
Menu languageMenu = new Menu();
languageMenu.setId("transparent");
languageMenu.setGraphic(languageBox);
MenuBar menuBar = new MenuBar();
menuBar.getMenus().addAll(fileMenu, languageMenu);
BorderPane root = new BorderPane();
root.setTop(menuBar);
Scene scene = new Scene(root);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
stage.setScene(scene);
stage.setTitle("MCVE");
stage.setWidth(640);
stage.setHeight(480);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}

JavaFX setTabcontent dynamically

I have made an application which uses tabpane. I am able to set tooltip and title of each tab dynamically. But how do I set its contents dynamically. I am sure that I can maintain a list of Node object and add it to tab during iteration, but I feel there are other ways to do it. Here is what I have done so far.
public class Index extends Application {
public static void main(String[] args) {
launch(args);
}
final String[] tabContent={"title1"
,"title2"
,"title3"
,"title4"
,"title5"};
final String[] tabToolTip={"tooltip1"
,"tooltip2"
,"tooltip3"
,"tooltip4"
,"tooltip5"};
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Ipas Utility");
Group root = new Group();
Scene scene = new Scene(root, 1000, 600, Color.ALICEBLUE);
TabPane tabPane = new TabPane();
tabPane.setTooltip(new Tooltip("Hover on each tab for an overview"));
BorderPane borderPane = new BorderPane();
for (int i = 0; i < 5; i++) {
Tab tab = new Tab();
tab.setText(tabContent[i]);
tab.setClosable(false);
tab.setTooltip(new Tooltip(tabToolTip[i]));
HBox hbox = new HBox();
hbox.getChildren().add(new Label(tabContent[i]));
hbox.setAlignment(Pos.CENTER);
tab.setContent(hbox);;
tabPane.getTabs().add(tab);
}
// bind to take available space
borderPane.prefHeightProperty().bind(scene.heightProperty());
borderPane.prefWidthProperty().bind(scene.widthProperty());
borderPane.setCenter(tabPane);
root.getChildren().add(borderPane);
primaryStage.setScene(scene);
primaryStage.show();
}
}
How I can maintain tabcontent in a list/array outside start block?
That's quite okay what you did. Here's a modified version of your code which allows you to add a tab on button click:
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class Main extends Application {
private static int tabCount = 0;
#Override
public void start(Stage primaryStage) {
TabPane tabPane = new TabPane();
tabPane.getTabs().add(createTab());
tabPane.getTabs().add(createTab());
tabPane.getTabs().add(createTab());
Button addTabButton = new Button( "Add Tab");
addTabButton.setOnAction(e -> {
tabPane.getTabs().add(createTab());
});
Button logButton = new Button( "Log");
logButton.setOnAction(e -> {
for( Tab tab: tabPane.getTabs()) {
System.out.println( "Tab " + tab.getText() + " has content " + tab.getContent());
}
});
HBox toolbar = new HBox();
HBox.setMargin(addTabButton, new Insets(5,5,5,5));
HBox.setMargin(logButton, new Insets(5,5,5,5));
toolbar.getChildren().addAll( addTabButton, logButton);
BorderPane root = new BorderPane();
root.setTop(toolbar);
root.setCenter(tabPane);
Scene scene = new Scene(root, 640, 480);
primaryStage.setScene(scene);
primaryStage.show();
}
public static Tab createTab() {
tabCount++;
Tab tab = new Tab();
tab.setText("Tab " + tabCount);
tab.setTooltip( new Tooltip( "Tooltip Tab " + tabCount));
Node content = new Label( "Content Tab " + tabCount);
tab.setContent(content);
return tab;
}
public static void main(String[] args) {
launch(args);
}
}
In order to access the tabs you can use getTabs. And in order to change the content, i. e. the node that represents the content, you can use setContent.
The example code shows you how to iterate through the tabs by pressing the log button.

Bookmarks and History Buttons not showing up in my Browser using JavaFX

I am making a web browser in JavaFX and I thought everything was good and dandy. I ran the application and now the History and Bookmarks buttons will not appear. I looked through the code and saw no errors. How do I fix this?
package javafxapplication3;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.application.Application;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.scene.web.WebHistory;
public class CreateAsIGo2 extends Application{
public static void main(String[] args){
launch(args);
}
public void start(Stage primaryStage){
BorderPane ap = new BorderPane();
BorderPane ap2 = new BorderPane();
BorderPane ap3 = new BorderPane();
Scene scene = new Scene(ap, 700, 700);
Scene scene2 = new Scene(ap2, 700, 700);
Scene scene3 = new Scene(ap3, 700, 700);
VBox sp = new VBox();
VBox sp2 = new VBox();
VBox sp3 = new VBox();
Button HistoryButton = new Button("History");
Button BookmarksButton = new Button("Bookmarks");
Button RefreshButton = new Button("Refresh");
Button BackButton = new Button("Back");
Button BackToBrowser = new Button("Back to surfing the web");
Button ForwardButton = new Button("Forward");
TextField tf = new TextField();
tf.setPromptText("URL");
WebView browser = new WebView();
WebEngine webEngine = browser.getEngine();
webEngine.load("http://www.google.com");
webEngine.setJavaScriptEnabled(true);
WebHistory history = webEngine.getHistory();
HistoryButton.setOnAction(e -> primaryStage.setScene(scene2));
BookmarksButton.setOnAction(e -> primaryStage.setScene(scene3));
RefreshButton.setOnAction(e -> webEngine.reload());
BackButton.setOnAction(e -> webEngine.executeScript("history.back()"));
BackToBrowser.setOnAction(e -> primaryStage.setScene(scene));
ForwardButton.setOnAction(e -> webEngine.executeScript("history.forward()"));
tf.setOnKeyPressed((KeyEvent ke) -> {
KeyCode key = ke.getCode();
if(key == KeyCode.ENTER){
webEngine.load("http://" + tf.getText());
}
});
sp.getChildren().addAll(HistoryButton, BookmarksButton, RefreshButton, BackButton, ForwardButton);
sp2.getChildren().addAll(BookmarksButton, BackToBrowser);
sp3.getChildren().addAll(HistoryButton, BackToBrowser);
ap.setRight(sp);
ap2.setRight(sp2);
ap3.setRight(sp3);
ap.setTop(tf);
ap.setCenter(browser);
browser.setPrefSize(700, 700);
primaryStage.setTitle("JTG Browser Alpha");
primaryStage.setScene(scene);
primaryStage.show();
}
}
See the node documentation:
If a program adds a child node to a Parent (including Group, Region, etc) and that node is already a child of a different Parent or the root of a Scene, the node is automatically (and silently) removed from its former parent.
You are adding your HistoryButton (and other buttons) to different scenes and, when you do so, they are automatically removed from the previous scenes. You need to create new button instances if you want them visible in every scene.
Small aside: it is best to follow Java naming conventions, e.g. historyButton instead of HistoryButton.

How to align a button into the bottom right corner in JavaFX?

I'm extremely new to JavaFX, and I'm attempting to get a button(specifically scrapeBtn) into the bottom right corner of an application. Here is what I have so far:
package main;
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.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class Driver extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
Button scrapeBtn = new Button();
scrapeBtn.setText("Scrape!");
scrapeBtn.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
System.out.println("Scrape button pressed.");
}
});
TextField console = new TextField();
GridPane root = new GridPane();
GridPane.setConstraints(scrapeBtn, 2, 2, 1, 1);
root.getChildren().add(scrapeBtn);
root.getChildren().add(console);
Scene scene = new Scene(root, 600, 400);
primaryStage.setTitle("Wiki Scraper");
primaryStage.setScene(scene);
primaryStage.show();
}
}
Any ideas as to how I could accomplish this? Some tips in general to aligning and formatting things with JavaFX would also be really appreciated.
Thanks.
I often use a BorderPane for similar purposes (e.g. a Dialog with some text and controls etc. at the center and one or more buttons at the bottom). Therefore, I use the BorderPane as root and a HBox as "button container" at the bottom. Finally, I set the botton alignment to "RIGHT".
Here an example based on your code:
#Override
public void start(Stage primaryStage) {
// center
VBox vbCenter = new VBox(); // use any container as center pane e.g. VBox
TextField console = new TextField();
vbCenter.getChildren().add(console);
// bottom respectively "button area"
HBox hbButtons = new HBox();
Button scrapeBtn = new Button();
scrapeBtn.setText("Scrape!");
scrapeBtn.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
System.out.println("Scrape button pressed.");
}
});
hbButtons.getChildren().add(scrapeBtn);
hbButtons.setAlignment(Pos.CENTER_RIGHT);
// root
BorderPane root = new BorderPane();
root.setPadding(new Insets(20)); // space between elements and window border
root.setCenter(vbCenter);
root.setBottom(hbButtons);
Scene scene = new Scene(root, 600, 400);
primaryStage.setTitle("Wiki Scraper");
primaryStage.setScene(scene);
primaryStage.show();
}
This code leads to this (after resizing the window a little bit):
You can use two BorderPanes to place a control bottom right
#Override
public void start(Stage primaryStage) throws Exception {
BorderPane root = new BorderPane();
BorderPane bottom = new BorderPane();
bottom.setRight(new Button("I am placed bottom right"));
root.setBottom(bottom);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.setWidth(400);
primaryStage.setHeight(400);
primaryStage.show();
}

Categories

Resources