I want to create several work spaces which can be switched with toggle buttons. I created this example
package menunavigation;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.Toggle;
import javafx.scene.control.ToggleButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class MenuNavigation extends Application
{
#Override
public void start(Stage primaryStage)
{
final VBox vbox = new VBox();
MenuBar menuBar = new MenuBar();
// --- Menu File
Menu menuFile = new Menu("File");
// --- Menu Edit
Menu menuEdit = new Menu("Edit");
// --- Menu View
Menu menuView = new Menu("View");
menuBar.getMenus().addAll(menuFile, menuEdit, menuView);
// buttons
String pillButtonCss = MenuNavigation.class.getResource("PillButton.css").toExternalForm();
// create 3 toggle buttons and a toogle group for them
ToggleButton tb1 = new ToggleButton("Left Button");
tb1.setId("pill-left");
ToggleButton tb2 = new ToggleButton("Center Button");
tb2.setId("pill-center");
ToggleButton tb3 = new ToggleButton("Right Button");
tb3.setId("pill-right");
final ToggleGroup group = new ToggleGroup();
tb1.setToggleGroup(group);
tb2.setToggleGroup(group);
tb3.setToggleGroup(group);
// select the first button to start with
group.selectToggle(tb1);
final Rectangle rect1 = new Rectangle(300, 300);
rect1.setFill(Color.ALICEBLUE);
final Rectangle rect2 = new Rectangle(300, 300);
rect2.setFill(Color.AQUA);
final Rectangle rect3 = new Rectangle(300, 300);
rect3.setFill(Color.AZURE);
tb1.setUserData(rect1);
tb2.setUserData(rect2);
tb3.setUserData(rect3);
group.selectedToggleProperty().addListener(new ChangeListener<Toggle>()
{
#Override
public void changed(ObservableValue<? extends Toggle> ov, Toggle toggle, Toggle new_toggle)
{
if (new_toggle == null)
{
//rect.setFill(Color.WHITE);
}
else
{
//rect.setFill((Color) group.getSelectedToggle().getUserData());
vbox.getChildren().setAll((Node) group.getSelectedToggle().getUserData());
}
}
});
HBox hBox = new HBox();
hBox.getChildren().addAll(tb1, tb2, tb3);
hBox.setPadding(new Insets(10, 10, 10, 10));
hBox.getStylesheets().add(pillButtonCss);
// end buttons
vbox.getChildren().addAll(menuBar, hBox, new Text("Test Space"));
StackPane root = new StackPane();
root.getChildren().add(vbox);
Scene scene = new Scene(root, 800, 850);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args)
{
launch(args);
}
}
This is the visual result:
When I press the second button I get this:
I want to use the toggle buttons to create different work spaces on which I want to place one main BorderPane or GridPane in which I want to insert many other components. Can you help me to get this result.
Is there a reason to not use a TabPane?
Edit:
Replace:
vbox.getChildren().setAll((Node) group.getSelectedToggle().getUserData());
With:
vbox.getChildren().set(2,(Node) group.getSelectedToggle().getUserData());
to show the rectangle instead of the Text.
This replaces the node with index 2 (the text) of your vbox with the node from ToggleButtons UserData (instead of replacing all elements in your current code).
Related
I want to know how to clear the webview's content just by clicking on a button with javaFX? So how I can do that? For example: WebView1 contains google web page while clicking on a button should this page clear
You can clear the web view by loading some empty content:
webView.getEngine().loadContent("");
Complete example:
import java.util.regex.Pattern;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class WebBrowser extends Application {
private TextField textField ;
private WebView webView ;
#Override
public void start(Stage primaryStage) {
webView = new WebView();
textField = new TextField("https://www.google.com");
textField.setOnAction(e -> load());
load();
Button clearButton = new Button("Clear");
clearButton.setOnAction(e -> webView.getEngine().loadContent(""));
BorderPane root = new BorderPane(webView, new HBox(10, textField, clearButton), null, null, null);
textField.setPadding(new Insets(5));
root.setPadding(new Insets(5));
Scene scene = new Scene(root, 800, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
private void load() {
String url = makeUrl(textField.getText()) ;
webView.getEngine().load(url);
textField.setText(url);
}
private String makeUrl(String text) {
if (Pattern.matches("[a-zA-Z]+:.+", text)) {
return text ;
} else return "http://"+text ;
}
public static void main(String[] args) {
launch(args);
}
}
i'd like to have a StackPane as the root node, it makes overlay effects easy.
But by using a stackpane as the root, inner controls can move out of the window.
In the following example you can see the controls moving out of the window ,
if you shrink the window small enough, e.g. both the menubar and the listview go out to the left. I want to prevent this, how can i do that?
package test;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.collections.FXCollections;
import javafx.scene.Scene;
import javafx.scene.control.ListView;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class App extends Application {
#Override
public void start(Stage stage) throws Exception {
stage.setTitle("controls move out of window :(");
Menu menu = new Menu("Menu");
MenuBar menubar = new MenuBar(menu);
ListView<String> listView = new ListView<>(FXCollections.observableArrayList("Args, it moves away."));
BorderPane borderPane = new BorderPane();
borderPane.setTop(menubar);
borderPane.setLeft(listView);
StackPane rootStackPane = new StackPane(borderPane);
Scene scene = new Scene(rootStackPane);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Update:
setting the alignment for the BorderPane inside the StackPane seems to help:
public void start(Stage stage) throws Exception {
stage.setTitle("controls stay in window :)");
Menu menu = new Menu("Menu");
MenuBar menubar = new MenuBar(menu);
ListView<String> listView = new ListView<>(FXCollections.observableArrayList("it stays!"));
BorderPane borderPane = new BorderPane();
borderPane.setTop(menubar);
borderPane.setLeft(listView);
StackPane rootStackPane = new StackPane(borderPane);
StackPane.setAlignment(borderPane, Pos.TOP_LEFT);
Scene scene = new Scene(rootStackPane);
stage.setScene(scene);
stage.show();
}
Place your stack in a Group and bind the stack's preferred size to the scene's preferred size.
As you can see from the second image, the overlay is not centered on the visible screen, it is centered on the StackPane. The StackPane's minimum size will be the minimum size of it's largest component (even if it overflows the screen), so the overlay is centered on that. To find out minimum sizes of things, you could use either design the UI in SceneBuilder or debug the UI using ScenicView.
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;
public class App extends Application {
#Override
public void start(Stage stage) throws Exception {
stage.setTitle("controls stay in window :)");
Menu menu = new Menu("Menu");
MenuBar menubar = new MenuBar();
menubar.getMenus().add(menu);
ListView<String> listView = new ListView<>(FXCollections.observableArrayList("Args, it moves away."));
BorderPane borderPane = new BorderPane();
borderPane.setTop(menubar);
borderPane.setLeft(listView);
borderPane.setStyle("-fx-background-color: palegreen;");
Node overlayContent = new Label("centered");
StackPane stack = new StackPane(borderPane, overlayContent);
Scene scene = new Scene(new Group(stack));
stage.setScene(scene);
stage.show();
stack.prefWidthProperty().bind(scene.widthProperty());
stack.prefHeightProperty().bind(scene.heightProperty());
}
public static void main(String[] args) {
launch(args);
}
}
I want my JavaFX program to be able to dynamically change the accelerator for menu items. However, I can't seem to get it to work in JavaFX 2.2. In the code below, the first menu item has an accelerator "Ctrl+M" and it works fine. "Ctrl+M" is printed every time the menu item is selected using a mouse or with the keyboard accelerator Ctrl+M. The second menu item attempts to change the first men item's accelerator to "Ctrl+L". After choosing the second menu item, I can click on the first menu item again and it shows that its new accelerator is "Ctrl+L", but I cannot use the keyboard accelerator Ctrl+L to activate the first menu item. Instead, I still need to use Ctrl+M to activate the first menu item. Any suggestions on what is going wrong here?
/*
* from code at <http://java-buddy.blogspot.com/2012/02/javafx-20-set-accelerator.html>
*/
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.input.KeyCombination;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class AcceleratorExample extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Accelerator example");
Group root = new Group();
Scene scene = new Scene(root, 400, 300, Color.WHITE);
MenuBar menuBar = new MenuBar();
Menu FileMenu = new Menu("File");
final MenuItem item1 = new MenuItem("Select me");
item1.setAccelerator(KeyCombination.keyCombination("Ctrl+M"));
item1.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
System.out.println(item1.getAccelerator());
}
});
final MenuItem item2 = new MenuItem("New accel");
item2.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent e) {
item1.setAccelerator(KeyCombination.keyCombination("Ctrl+L"));
}
});
FileMenu.getItems().add(item1);
FileMenu.getItems().add(item2);
menuBar.getMenus().add(FileMenu);
menuBar.prefWidthProperty().bind(primaryStage.widthProperty());
root.getChildren().add(menuBar);
primaryStage.setScene(scene);
primaryStage.show();
}
}
Dynamically changing the accelerator has iffy behaviour at present, but this is a bug which has been fixed for 8u20:
https://javafx-jira.kenai.com/browse/RT-35182
I want to implement this example: http://docs.oracle.com/javafx/2/ui_controls/toggle-button.htm#
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Toggle;
import javafx.scene.control.ToggleButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class test extends Application
{
private void init(Stage primaryStage)
{
Group root = new Group();
primaryStage.setScene(new Scene(root));
String pillButtonCss = DX57DC.class.getResource("PillButton.css").toExternalForm();
// create 3 toggle buttons and a toogle group for them
ToggleButton tb1 = new ToggleButton("Left Button");
tb1.setId("pill-left");
ToggleButton tb2 = new ToggleButton("Center Button");
tb2.setId("pill-center");
ToggleButton tb3 = new ToggleButton("Right Button");
tb3.setId("pill-right");
final ToggleGroup group = new ToggleGroup();
tb1.setToggleGroup(group);
tb2.setToggleGroup(group);
tb3.setToggleGroup(group);
// select the first button to start with
group.selectToggle(tb1);
//////////////////////////////////////////
tb1.setUserData(Color.LIGHTGREEN);
tb2.setUserData(Color.LIGHTBLUE);
tb3.setUserData(Color.SALMON);
final Rectangle rect = new Rectangle(300, 300);
group.selectedToggleProperty().addListener(new ChangeListener<Toggle>()
{
#Override
public void changed(ObservableValue<? extends Toggle> ov,
Toggle toggle, Toggle new_toggle)
{
if (new_toggle == null)
{
rect.setFill(Color.WHITE);
}
else
{
rect.setFill(
(Color) group.getSelectedToggle().getUserData());
}
}
});
///////////////////////////////////////////
rect.setArcHeight(10);
rect.setArcWidth(10);
HBox hBox = new HBox();
hBox.getChildren().addAll(tb1, tb2, tb3);
hBox.setPadding(new Insets(20, 20, 260, 20));
hBox.getStylesheets().add(pillButtonCss);
VBox vbox = new VBox();
vbox.getChildren().add(hBox);
vbox.getChildren().add(rect);
root.getChildren().add(vbox);
}
#Override
public void start(Stage primaryStage) throws Exception
{
init(primaryStage);
primaryStage.show();
}
public static void main(String[] args)
{
launch(args);
}
}
But for some reason I can see the buttons but the rectangle is not displayed when I try to switch the buttons. Can you help me to find where is my mistake? And also how I can implement this example with several rectangles holding different content?
You have to add rect to your scene graph :
root.getChildren().addAll(hBox, rect);
Also, think of using an appropriate layout for your root, BorderPane instead of Group for example.
I want to create a borderpane what is transparent.I tried setting background color to transparent but it appears white. plz let me know if there is a way.
Code i tried.
BorderPane root=new BorderPane();
root.setStyle("-fx-background-color:transparent");
Scene scene=new Scene(root);
stage.setScene(scene);
stage.show();
Thank you...
Try setting the stage to transparent:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class TransparentStage extends Application {
#Override
public void start(Stage stage) {
// important line
stage.initStyle(StageStyle.TRANSPARENT);
Text text = new Text("Transparent!");
text.setFont(new Font(40));
VBox box = new VBox();
box.getChildren().add(text);
final Scene scene = new Scene(box,300, 250);
scene.setFill(null);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}