0

I want to cancel the tab change when a tab is clicked in my TabPane. I want to change tabs manually, not by user clicks on tabs.

How can I do that? Thanks in advance.

AwesomeGuy
  • 537
  • 1
  • 6
  • 17
  • 1
    Can you share your code? – Greedo Nov 13 '19 at 09:55
  • 1
    @Greedo I have nothing so far because I don't even know how to start treating that. – AwesomeGuy Nov 13 '19 at 10:07
  • 1
    why do you want to confuse your users? Anyway, that's not supported, you would probably need a custom skin to change how it handles mouse events – kleopatra Nov 13 '19 at 10:30
  • @kleopatra it might not be confusing if he is trying to build a work flow and validate information before moving to the next pane it would probably be easier then building out this functionality on its own and its also extremely easy to manage – Matt Nov 13 '19 at 15:08
  • 1
    Maybe a wizard would be better than tabs? See https://stackoverflow.com/questions/19198951/create-wizard-in-javafx – Robert Nov 13 '19 at 17:50

2 Answers2

2

You could use event filter(s) to block the events you don't want tab header area to receive. The following code blocks the MOUSE_PRESSED event responsible for changing the tabs on a click. Any click inside the content area is not blocked.

@Override
public void start(Stage stage) throws IOException {
    Button btn = new Button("Click");
    TabPane tp = new TabPane(new Tab("tab1", new StackPane(btn)), new Tab("tab2"));
    btn.setOnAction(event-> {
        tp.getSelectionModel().select(1); // change tab programmatically
    });

    tp.addEventFilter(MouseEvent.MOUSE_PRESSED, event -> {
        Node n = event.getPickResult().getIntersectedNode();

        boolean outsideContentArea = true;

        // iterate from node actually clicked to the TabPane
        // and look for the content area
        while (outsideContentArea && (n != tp)) {
            if (n.getStyleClass().contains("tab-content-area")) {
                outsideContentArea = false;
            }
            n = n.getParent();
        }
        if (outsideContentArea) {
            // stop event propagation to any part
            // of the TabPane outside the content area
            event.consume();
        }
    });

    Scene scene = new Scene(tp, 300, 300);

    stage.setScene(scene);
    stage.show();
}
fabian
  • 80,457
  • 12
  • 86
  • 114
0

If you want this type of flow you can do this by hiding the tabs so that they cannot be clicked on and then adding buttons to iterate through each tab

You will need the line below to hide the tabs

tabPane.setStyle("-fx-tab-max-height: -2;");//You can still see tabs at -1 not sure why

Note if you want to hide the header space(as seen in my application below) you need to do it though css and you can ignore the above line

.tab-pane {
    -fx-tab-max-height: 0 ;
}
.tab-pane .tab-header-area {
    visibility: hidden ;
}

and you will also need to look at how the buttons are setup to get to the next tab and previous tab as I am not sure what your application will look like I just did it with buttons but you can use the same action to move thought he tabs

    Button buttonPlus = new Button("+");
    buttonPlus.setOnAction(event -> {
        int selectedIndex = tabPane.getSelectionModel().getSelectedIndex();
        if(selectedIndex<tabPane.getTabs().size()-1)
            tabPane.getSelectionModel().select(++selectedIndex);
    });

    Button buttonMinus = new Button("-");
    buttonMinus.setOnAction(event -> {
        int selectedIndex = tabPane.getSelectionModel().getSelectedIndex();
        if(selectedIndex>0)
            tabPane.getSelectionModel().select(--selectedIndex);
    });

Also just as a heads up you can change tabs by passing an index like so tabPane.getSelectionModel().select(index); or by passing a specific tab like so tabPane.getSelectionModel().select(tab);

Once these have been created and added to the scene you will easily be able to click through each tab

Check out my application below let me know if you have any questions

public class Main extends Application {

    @Override
    public void start(Stage stage) {
        TabPane tabPane = new TabPane();
        tabPane.setStyle("-fx-tab-max-height: -2;");//You can still see tabs at -1

        createNewTab(tabPane);
        createNewTab(tabPane);
        createNewTab(tabPane);

        stage.setScene(new Scene(tabPane));
        stage.show();
    }

    private void createNewTab(TabPane tabPane){
        Tab tab = new Tab();
        tab.setClosable(false);
        addNodesToTab(tabPane, tab);

        tabPane.getTabs().add(tab);
    }

    private void addNodesToTab(TabPane tabPane, Tab tab){

        Button buttonPlus = new Button("+");
        buttonPlus.setOnAction(event -> {
            int selectedIndex = tabPane.getSelectionModel().getSelectedIndex();
            if(selectedIndex<tabPane.getTabs().size()-1)
                tabPane.getSelectionModel().select(++selectedIndex);
        });

        Button buttonMinus = new Button("-");
        buttonMinus.setOnAction(event -> {
            int selectedIndex = tabPane.getSelectionModel().getSelectedIndex();
            if(selectedIndex>0)
                tabPane.getSelectionModel().select(--selectedIndex);
        });

        tab.setContent(new VBox(new Label("Tab:"+tabPane.getTabs().size()),buttonPlus, buttonMinus));
    }
}
Matt
  • 3,052
  • 1
  • 17
  • 30
  • playing guessing games on what the OP is really after :) – kleopatra Nov 13 '19 at 16:30
  • @kleopatra if you read his post this is the exact functionality he asked for there are no games here he says "I want to change tabs manually, not by user clicks on tabs" – Matt Nov 13 '19 at 17:16