how to close other tabs except the selected tab - javafx

I want to implement TabPane with ContextMenu to close other tabs except the selected tab
public class MainApp extends Application
{
#Override
public void start(Stage primaryStage)
{
primaryStage.setTitle("Tabs");
Group root = new Group();
Scene scene = new Scene(root, 400, 250, Color.WHITE);
final TabPane tabPane = new TabPane();
BorderPane borderPane = new BorderPane();
for (int i = 0; i < 5; i++)
{
Tab tab = new Tab();
tab.setText("Tab" + i);
HBox hbox = new HBox();
hbox.getChildren().add(new Label("Tab" + i));
hbox.setAlignment(Pos.CENTER);
tab.setContent(hbox);
tabPane.getTabs().add(tab);
ContextMenu contextMenu = new ContextMenu();
MenuItem close = new MenuItem();
MenuItem closeOthers = new MenuItem();
MenuItem closeAll = new MenuItem();
close.setText("Close");
closeOthers.setText("Close Others");
closeAll.setText("Close All");
contextMenu.getItems().addAll(close, closeOthers, closeAll);
tab.setContextMenu(contextMenu);
final ObservableList<Tab> tablist = tabPane.getTabs();
close.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent event)
{
tabPane.getTabs().remove(tabPane.getSelectionModel().getSelectedItem());
}
});
closeOthers.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent event)
{
tabPane.getTabs().removeAll();
}
});
closeAll.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent event)
{
tabPane.getTabs().removeAll(tablist);
}
});
}
// 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();
}
}
But the code is not working. Can you help me to implement this solution.
Is there any better approach to implement this?

This is pretty simple. Just iterate through all Tab-Objects in the tablist and mark the ones which should be deleted. After the iteration remove the marked Tab-Objects.
closeOthers.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent event)
{
// ArrayList of Tab-Objects in which we store Tabs which should be deleted..
ArrayList<Tab> markedTabs = new ArrayList<>();
// Iterate through all Tabs in tablist
for (Tab tab : tablist) {
// Is the tab the current active tab? if not, add it to the markedTabs-ArrayList
if (tab != tabPane.getSelectionModel().getSelectedItem())
markedTabs.add(tab);
}
// Remove them from the tabPane..
tabPane.getTabs().removeAll(markedTabs);
}
});

Related

Adding multiple tree Branches and leafs in javafx

hi i post this question before but didn't get any answer. Adding tree Branches and leafs in TreeView
i need help, Please have a look at code,
public class Main extends Application
{
private BorderPane border;
#Override
public void start(Stage primaryStage)
{
border = new BorderPane();
Scene scene = new Scene(border,200,200);
primaryStage.setTitle("BorderPane");
primaryStage.setScene(scene);
primaryStage.show();
TreeItem<String> tree = new TreeItem<String>("Root");
TreeItem<String> item1 = new TreeItem<String>("Branch");
item1.getChildren().add(new TreeItem<String>("Leaf"));
item1.setExpanded(true);
tree.setExpanded(true);
tree.getChildren().addAll(item1);
TreeView<String> treeView = new TreeView<String>(tree);
treeView.setEditable(true);
treeView.setCellFactory(new Callback<TreeView<String>,TreeCell<String>>(){
#Override
public TreeCell<String> call(TreeView<String> arg0) {
return new AddMenuTreeCell();
}
});
VBox vbox =new VBox(2);
vbox.setPadding(new Insets(5));
VBox.setVgrow(treeView, Priority.ALWAYS);
vbox.getChildren().addAll(treeView);
border.setLeft(vbox);
}
private static class AddMenuTreeCell extends TextFieldTreeCell<String> {
private ContextMenu menu = new ContextMenu();
private TextField textField;
public AddMenuTreeCell() {
MenuItem addItem1 = new MenuItem("Insert Branch");
MenuItem addItem2 = new MenuItem("Insert Leaf");
menu.getItems().addAll(addItem1,addItem2);
addItem1.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent arg0) {
TreeItem<String> newBranch =
new TreeItem<String>("Brunch");
getTreeItem().getChildren().add(newBranch);
}
});
addItem2.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent arg0) {
TreeItem<String> newLeaf =
new TreeItem<String>("leaf");
getTreeItem().getChildren().add(newLeaf);
}
});
}
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (!empty && getTreeItem().getParent() == null){
setContextMenu(menu);
}
}
}
}
With this user can add multiple Branches and Leafs.
But the problem is, if user add a Branch it should be like "Branch1" next added branch should be "Branch2", "Branch3",...... same for leafs added in any branch have their numbers.
So that later on user can assign different task to different branches and leafs.
Thank you!
Replace AddMenuTreeCell class to below code and try now
private static class AddMenuTreeCell extends TextFieldTreeCell<String> {
private ContextMenu menu = new ContextMenu();
private TextField textField;
int i = 1, j = 1;
public AddMenuTreeCell() {
MenuItem addItem1 = new MenuItem("Insert Branch");
MenuItem addItem2 = new MenuItem("Insert Leaf");
menu.getItems().addAll(addItem1, addItem2);
addItem1.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent arg0) {
TreeItem<String> newBranch = new TreeItem<String>("Brunch" + i);
getTreeItem().getChildren().add(newBranch);
i++;
}
});
addItem2.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent arg0) {
TreeItem<String> newLeaf = new TreeItem<String>("leaf" + j);
getTreeItem().getChildren().add(newLeaf);
j++;
}
});
setContextMenu(menu);
}
}

Adding tree Branches and leafs in TreeView

i am working on treeView program in which, user need to add branches and leafs here is my example
public class Main extends Application
{
private BorderPane border;
#Override
public void start(Stage primaryStage)
{
border = new BorderPane();
Scene scene = new Scene(border,200,200);
primaryStage.setTitle("BorderPane");
primaryStage.setScene(scene);
primaryStage.show();
TreeItem<String> tree = new TreeItem<String>("Root");
TreeItem<String> item1 = new TreeItem<String>("Branch");
item1.getChildren().add(new TreeItem<String>("Leaf"));
item1.setExpanded(true);
tree.setExpanded(true);
tree.getChildren().addAll(item1);
TreeView<String> treeView = new TreeView<String>(tree);
treeView.setEditable(true);
treeView.setCellFactory(new Callback<TreeView<String>,TreeCell<String>>(){
#Override
public TreeCell<String> call(TreeView<String> arg0) {
return new AddMenuTreeCell();
}
});
VBox vbox =new VBox(2);
vbox.setPadding(new Insets(5));
VBox.setVgrow(treeView, Priority.ALWAYS);
vbox.getChildren().addAll(treeView);
border.setLeft(vbox);
}
private static class AddMenuTreeCell extends TextFieldTreeCell<String> {
private ContextMenu menu = new ContextMenu();
private TextField textField;
public AddMenuTreeCell() {
MenuItem addItem1 = new MenuItem("Insert Branch");
MenuItem addItem2 = new MenuItem("Insert Leaf");
menu.getItems().addAll(addItem1,addItem2);
addItem1.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent arg0) {
TreeItem<String> newBranch =
new TreeItem<String>("Brunch");
getTreeItem().getChildren().add(newBranch);
}
});
addItem2.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent arg0) {
TreeItem<String> newLeaf =
new TreeItem<String>("leaf");
getTreeItem().getChildren().add(newLeaf);
}
});
}
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (!empty && getTreeItem().getParent() == null){
setContextMenu(menu);
}
}
}
}
With this user can add Branch and Leaf.
But the question is, if user add a Branch it should be like "Branch1" next added branch should be "Branch2", "Branch3",...... same for leafs added in any branch have their numbers.
So that later on user can assign different task to different branches and leafs. Please
Thank you

Show Colorpicker from Contextmenu

I want to show Colorpicker from Context Menu:
ColorPicker colorssPicker = new ColorPicker();
final MenuItem resizeItem = new MenuItem("Option 1");
resizeItem.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent event)
{
}
});
final MenuItem resizesItem = new MenuItem();
resizesItem.setGraphic(colorssPicker);
resizesItem.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent event)
{
}
});
final ContextMenu menu = new ContextMenu();
menu.getItems().addAll(resizeItem, resizesItem);
sc.setOnMouseClicked(new EventHandler<MouseEvent>()
{
#Override
public void handle(MouseEvent event)
{
if (MouseButton.SECONDARY.equals(event.getButton()))
{
menu.show(primaryStage, event.getScreenX(), event.getScreenY());
}
}
});
This code is not working, I can't see Colorpicker when I click on the Contextmenu "Choose Color". What is the proper way to implement this?
I get this result:
This snippet will let you show a ColorPicker control embedded into a ContextMenu.
You can style it so it doesn't look like a button, by setting its backgound color.
#Override
public void start(Stage primaryStage) {
StackPane root = new StackPane();
final ColorPicker colorssPicker = new ColorPicker();
colorssPicker.setStyle("-fx-background-color: white;");
final MenuItem otherItem = new MenuItem(null, new Label("Other item"));
final MenuItem resizeItem = new MenuItem(null,colorssPicker);
resizeItem.setOnAction(new EventHandler<ActionEvent>(){
#Override
public void handle(ActionEvent event)
{
root.setBackground(new Background(new BackgroundFill(colorssPicker.getValue(),null,null)));
}
});
final ContextMenu menu = new ContextMenu(otherItem,resizeItem);
Scene scene = new Scene(root, 300, 250);
scene.setOnMouseClicked(new EventHandler<MouseEvent>(){
#Override
public void handle(MouseEvent event){
if (MouseButton.SECONDARY.equals(event.getButton())){
menu.show(primaryStage, event.getScreenX(), event.getScreenY());
}
}
});
primaryStage.setScene(scene);
primaryStage.show();
}

Tab is not showing after inserting into new TabPane

I have implemented drag'n'drop functionality very similar to How to drag and drop tab nodes between tab panes, which works fine so far, but i also add a new Stage (SideStage below) if the tab is dragged outside of the main-window/stage. The problem is, the Tab is only showing after i either drag a new Tab to the TabPane there or if i resize the window. The main part of that drag'n'drop action is happening in the GuiPartFactory in the EventHandler which get's assigned to the Label of the Tab that gets dragged. I tried all sorts of size assigning, requestLayout, etc.
Sidestage class:
private TabPane tabPane;
public SideStage(double xPos, double yPos) {
tabPane = initTabArea();
VBox root = new VBox(0,GuiPartFactory.initMenuAndTitle(this),tabPane);
Scene scene = new Scene(root, 800, 600);
setScene(scene);
scene.setOnDragExited(new DnDExitAndEntryHandler());
scene.setOnDragEntered(new DnDExitAndEntryHandler());
setX(xPos);
setY(yPos);
;
initCloseWindowHandler();
}
private void initCloseWindowHandler() {
setOnCloseRequest(new EventHandler<WindowEvent>() {
#Override
public void handle(WindowEvent event) {
System.out.println("closing this sidestage");
MainApp.sideStages.remove(SideStage.this);
}
});
}
private TabPane initTabArea() {
final TabPane tabPane = GuiPartFactory.createTabPane();
tabPane.addEventHandler(Tab.TAB_CLOSE_REQUEST_EVENT, new EventHandler<Event>() {
#Override
public void handle(Event event) {
System.out.println("tab got closed mon!");
if (tabPane.getTabs().isEmpty()) {
SideStage.this.close();
}
}
});
VBox.setVgrow(tabPane, Priority.ALWAYS);
return tabPane;
}
public void addTab(Tab tab) {
tabPane.getTabs().add(tab);
}
And the GuiPartFactory class:
public static ResourceBundle BUNDLE = ResourceBundle.getBundle("locales/Bundle", new Locale("en", "GB"));
public static TabPane createTabPane() {
final TabPane tabPane = new TabPane();
//This event gets fired when the cursor is holding a draggable object over this tabpane
tabPane.setOnDragOver(new EventHandler<DragEvent>() {
#Override
public void handle(DragEvent event) {
final Dragboard dragboard = event.getDragboard();
if (dragboard.hasString() && dragboard.getString().equals("tab") && ((Tab) MainApp.dndTemp).getTabPane() != tabPane) {
event.acceptTransferModes(TransferMode.MOVE);
event.consume();
}
}
});
//This event gets fired when the cursor is releasing a draggable object over this tabpane (this gets only called if it has been accepted in the previos dragover event!)
tabPane.setOnDragDropped(new EventHandler<DragEvent>() {
#Override
public void handle(DragEvent event) {
System.out.println("dropped");
Tab tab = (Tab) MainApp.dndTemp;
MainApp.dndHandled = true;
tab.getTabPane().getTabs().remove(tab);
tabPane.getTabs().add(tab);
tabPane.getSelectionModel().select(tab);
event.setDropCompleted(true);
event.consume();
}
});
return tabPane;
}
public static Tab createTab(String text) {
final Tab tab = new Tab();
final Label label = new Label("Tab" + text);
tab.setGraphic(label);
StackPane pane = new StackPane();
//need to set a real size here
pane.setPrefSize(500, 500);
tab.setContent(pane);
tab.getContent().setOnDragOver(new EventHandler<DragEvent>() {
#Override
public void handle(DragEvent event) {
final Dragboard dragboard = event.getDragboard();
if (dragboard.hasString() && dragboard.getString().equals("tab") && ((Tab) MainApp.dndTemp).getTabPane() != tab.getTabPane()) {
event.acceptTransferModes(TransferMode.MOVE);
event.consume();
}
}
});
tab.getContent().setOnDragDropped(new EventHandler<DragEvent>() {
#Override
public void handle(DragEvent event) {
System.out.println("dropped");
Tab transferTab = (Tab) MainApp.dndTemp;
MainApp.dndHandled = true;
transferTab.getTabPane().getTabs().remove(transferTab);
tab.getTabPane().getTabs().add(transferTab);
tab.getTabPane().getSelectionModel().select(transferTab);
event.setDropCompleted(true);
event.consume();
}
});
label.setOnDragDetected(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
Dragboard dragboard = label.startDragAndDrop(TransferMode.MOVE);
ClipboardContent clipboardContent = new ClipboardContent();
clipboardContent.putString("tab");
MainApp.dndTemp = tab;
MainApp.dndHandled = false;
dragboard.setContent(clipboardContent);
dragboard.setDragView(new Image("img/dragcursor.png"));
event.consume();
}
});
label.setOnDragDone(new EventHandler<DragEvent>() {
#Override
public void handle(DragEvent event) {
//our dragndrop failed
if (!MainApp.dndHandled) {
//lets see if it failed because we dropped outside of our java-windows
if (!MainApp.dndInside) {
if (!MainApp.dndTemp.equals(tab)) {
System.out.println("something is wrong here");
}
System.out.println("gotta make a new window!");
SideStage sideStage = new SideStage(event.getScreenX(), event.getScreenY());
MainApp.sideStages.add(sideStage);
//just a check to make sure we don't access a null variable
if (tab.getTabPane() != null) {
tab.getTabPane().getTabs().remove(tab);
}
sideStage.addTab(tab);
sideStage.sizeToScene();
tab.getTabPane().getSelectionModel().select(tab);
System.out.println("width: " + ((StackPane) tab.getContent()).getWidth());
System.out.println("height: " + ((StackPane) tab.getContent()).getHeight());
System.out.println("width: " + tab.getTabPane().getWidth());
System.out.println("height: " + tab.getTabPane().getHeight());
sideStage.show();
}
}
}
});
return tab;
}
public static Tab createTabRandomColor(String text) {
Random rng = new Random();
Tab tab = GuiPartFactory.createTab(text);
StackPane pane = (StackPane) tab.getContent();
int red = rng.nextInt(256);
int green = rng.nextInt(256);
int blue = rng.nextInt(256);
String style = String.format("-fx-background-color: rgb(%d, %d, %d);", red, green, blue);
pane.setStyle(style);
Label label = new Label("This is tab " + text);
label.setStyle(String.format("-fx-text-fill: rgb(%d, %d, %d);", 256 - red, 256 - green, 256 - blue));
pane.getChildren().add(label);
return tab;
}
public static MenuBar initMenuAndTitle(Stage stage) {
//setting up a window title
stage.setTitle(BUNDLE.getString("title.name"));
//adding the menubar
MenuBar menuBar = new MenuBar();
//adding the base menu entry
Menu menuStart = new Menu(BUNDLE.getString("menu.start"));
Menu menuView = new Menu(BUNDLE.getString("menu.view"));
Menu menuHelp = new Menu(BUNDLE.getString("menu.help"));
menuBar.getMenus().addAll(menuStart, menuView, menuHelp);
//adding the menuitems inside the menus
MenuItem aboutItem = new MenuItem(BUNDLE.getString("menu.about"));
aboutItem.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
Dialogs popup = Dialogs.create();
popup.title(BUNDLE.getString("menu.about.title"));
popup.message(BUNDLE.getString("menu.about.message"));
popup.showInformation();
}
});
menuHelp.getItems().add(aboutItem);
MenuItem exitItem = new MenuItem(BUNDLE.getString("menu.exit"));
exitItem.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
Dialogs popup = Dialogs.create();
popup.title(BUNDLE.getString("menu.exit.title"));
popup.message(BUNDLE.getString("menu.exit.message"));
popup.actions(new Action[]{YES, NO});
Action response = popup.showConfirm();
if(response.equals(YES)) {
System.exit(0);
}
}
});
menuStart.getItems().add(exitItem);
return menuBar;
}
And finally the MainApp class:
//for handling tag drag'n'drop outside of java windows
public static Object dndTemp = null;
public static boolean dndHandled = true;
public static boolean dndInside = true;
public static Set<SideStage> sideStages = new HashSet<>();
//holding the tabs (doe)
private TabPane tabPane;
#Override
public void start(Stage stage) {
tabPane = initTabs();
VBox root = new VBox(0, GuiPartFactory.initMenuAndTitle(stage), tabPane);
Scene scene = new Scene(root, 800, 600);
stage.setScene(scene);
stage.show();
scene.setOnDragExited(new DnDExitAndEntryHandler());
scene.setOnDragEntered(new DnDExitAndEntryHandler());
}
private TabPane initTabs() {
TabPane tabPane = GuiPartFactory.createTabPane();
Tab bedraggin = GuiPartFactory.createTab("be draggin");
Tab beraggin = GuiPartFactory.createTab("be raggin");
tabPane.getTabs().add(bedraggin);
tabPane.getTabs().add(beraggin);
for (int i = 0; i < 3; i++) {
Tab tab = GuiPartFactory.createTabRandomColor("" + i);
tabPane.getTabs().add(tab);
}
VBox.setVgrow(tabPane, Priority.ALWAYS);
return tabPane;
}
/**
* The main() method is ignored in correctly deployed JavaFX application.
* main() serves only as fallback in case the application can not be
* launched through deployment artifacts, e.g., in IDEs with limited FX
* support. NetBeans ignores main().
*
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
public boolean removeSideStage(SideStage sideStage) {
return sideStages.remove(sideStage);
}
public void addTab(Tab tab) {
tabPane.getTabs().add(tab);
}
public void removeTab(Tab tab) {
tabPane.getTabs().remove(tab);
}
edit: A temporary workaround is to put the actual adding of the tab into the new TabPane into a runnable. But i think this is a rather bad solution:
Platform.runLater(new Runnable() {
#Override
public void run() {
sideStage.addTab(tab);
tab.getTabPane().getSelectionModel().select(tab);
}
});

Remove node from TreeView

I want to create this simple example of javaFX TreeView with context menu which can remove nodes from the tree:
public class TreeViewSample extends Application {
private final Node rootIcon = new ImageView(
new Image(getClass().getResourceAsStream("folder_16.png"))
);
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Tree View Sample");
TreeItem<String> rootItem = new TreeItem<String> ("Inbox", rootIcon);
rootItem.setExpanded(true);
for (int i = 1; i < 6; i++) {
TreeItem<String> item = new TreeItem<String> ("Message" + i);
rootItem.getChildren().add(item);
}
TreeView<String> tree = new TreeView<String> (rootItem);
StackPane root = new StackPane();
root.getChildren().add(tree);
primaryStage.setScene(new Scene(root, 300, 250));
primaryStage.show();
}
}
I tested this context menu to remove right click selected node:
final ContextMenu contextMenu = new ContextMenu();
MenuItem item1 = new MenuItem("About");
item1.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent e)
{
System.out.println("About");
}
});
MenuItem item2 = new MenuItem("Preferences");
item2.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent e)
{
System.out.println("Preferences");
}
});
MenuItem item3 = new MenuItem("Remove");
item3.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent e)
{
DynamicTreeNodeModel c = treeView.getSelectionModel().getSelectedItem().getValue();
boolean remove = treeView.getSelectionModel().getSelectedItem().getChildren().remove(c);
System.out.println("Remove");
}
});
contextMenu.getItems().addAll(item1, item2, item3);
treeView.setContextMenu(contextMenu);
For some reason the code is not working. Can you help me to fix this issue?
You're trying to remove the selected node from it's own children. Since it doesn't exist there, nothing happens. You need to remove the selected node from it's parent's children.
MenuItem item3 = new MenuItem("Remove");
item3.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
TreeItem c = (TreeItem)treeView.getSelectionModel().getSelectedItem();
boolean remove = c.getParent().getChildren().remove(c);
System.out.println("Remove");
}
});

Resources