JavaFX - closing a Tab in TabPane dynamically

15,999

Solution 1

The approach using only tabPane.getTabs().remove(tab) is not totally correct because it does'nt call the "onClosed" handler if setted. I'm using the following method:

private void closeTab(Tab tab) {
        EventHandler<Event> handler = tab.getOnClosed();
        if (null != handler) {
            handler.handle(null);
        } else {
            tab.getTabPane().getTabs().remove(tab);
        }
    }

which remove the tab if no handler is set or call the "onClosed" handler.

Solution 2

I opened a feature request for this.

In the meantime, if you are using Java 8 and don't use a custom TabPane skin, you can use this workaround to mimic the exact closing behavior that's taking place when the close button is clicked:

import javafx.scene.control.Tab;

import com.sun.javafx.scene.control.behavior.TabPaneBehavior;
import com.sun.javafx.scene.control.skin.TabPaneSkin;

public class MyTab extends Tab {

    public void requestClose() {
        TabPaneBehavior behavior = getBehavior();
        if(behavior.canCloseTab(this)) {
            behavior.closeTab(this);
        }
    }

    private TabPaneBehavior getBehavior() {
        return ((TabPaneSkin) getTabPane().getSkin()).getBehavior();
    }
}
Share:
15,999
Ramazan
Author by

Ramazan

Updated on June 11, 2022

Comments

  • Ramazan
    Ramazan about 2 years

    I have a TabPane with closable tabs. I want to fire a "close tab event" when the user clicks a button in the content of the tab. Here is the method called when the user clicks the button:

    public class CustomTab extends Tab {
    
        ...
    
        protected void close() {
            Event.fireEvent(this, new Event(Tab.CLOSED_EVENT));
        }
    
        ....
    }
    

    I add this custom tab to tabpane as:

    TabPane tabPane = new TabPane();
    ...
    CustomTab tab = new CustomTab();
    tab.setOnClosed(new EventHandler<Event>() {
        @Override
        public void handle(Event t) {
            System.out.println("Closed!");
        }
    });
    tabPane.getTabs().add(tab);
    tabPane.getSelectionModel().select(tab);
    

    Normally, the tabs can be closed by clicking the (default) close icons in the header of the tab, and "Closed!" is printed to the screen. However, when the user clicks the button (that is in the content of the tab) and calls close() method of CustomTab, again, "Closed!" is printed to the screen, but the tab is not closed this time. Isn't it weird?

    How can I close a tab upon clicking on an arbitrary button?

    P.S.: tabPane.getTabs().remove(tab) works, but firing the corresponding event is much elegant. It should also close the tab.

    • zhujik
      zhujik about 11 years
      which javafx version are you using? since 8.0, there is a "TAB_CLOSE_REQUEST_EVENT"
    • Ramazan
      Ramazan about 11 years
      Since 8.0 is not official, and not contained in default jre, I am using 2.2.
    • pmoule
      pmoule about 11 years
      1: As the event's name Tab.CLOSED_EVENT indicates, the event should be fired after the tab is closed. IMHO the documentation is a bit fuzzy. 2: Simply invoking the event does not close the tab. Your approach calling tabPane.getTabs().remove(tab) is correct.