如何在JavaFX中单击的Tab上隐藏TabPane内容

时间:2018-02-10 09:02:16

标签: java javafx

这是一段代码:

package tabpane;

import javafx.application.*;
import javafx.geometry.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.*;

public class HideShowTabContentOnClicked extends Application {

    public static void main(String[] args) {

        launch(args);
    }

    private BorderPane createContent() {

        BorderPane borderPane = new BorderPane();

        TabPane tabPane = new TabPane();
        tabPane.setSide(Side.LEFT);

        StackPane stackPane = new StackPane();
        stackPane.setStyle("-fx-background-color: lightblue");
        stackPane.setMinWidth(200);

        Tab firstTab = new Tab("First");
        firstTab.setClosable(false);
        firstTab.setContent(stackPane);
        firstTab.selectedProperty().addListener((observable, oldValue, newValue) -> {
            if (!newValue) {
                firstTab.setContent(null);
            } else {
                firstTab.setContent(stackPane);
            }
        });

        Tab secondTab = new Tab("Second");
        StackPane stackPane2 = new StackPane();
        stackPane2.setStyle("-fx-background-color: yellow");
        secondTab.setContent(stackPane2);
        secondTab.setClosable(false);

        secondTab.selectedProperty().addListener((observable, oldValue, newValue) -> {
            if (!newValue) {
                secondTab.setContent(null);
            } else {
                secondTab.setContent(stackPane2);
            }
        });

        StackPane center = new StackPane();
        center.setStyle("-fx-background-color: cyan");

        borderPane.setCenter(center);

        tabPane.getTabs().addAll(firstTab, secondTab);
        borderPane.setLeft(tabPane);
        return borderPane;
    }

    @Override
    public void start(Stage stage) throws Exception {

        stage.setScene(new Scene(createContent()));
        stage.setMaximized(true);
        stage.show();
    }
}

这里我尝试通过将内容设置为null来使用selectedProperty()来解决问题,但它不起作用,我想使Tab像切换按钮一样,当我点击它时显示并隐藏TabPanes内容。

点击后

作为一个例子,我想实现TabPane,如Intellij IDEA工具按钮(如" Project"," Structure"工具按钮等)。

2 个答案:

答案 0 :(得分:1)

如果您要将内容保留在#include <iostream> #include <regex> int main() { std::regex r("^.*$"); std::smatch m; std::string str; for(size_t i = 0; i < 2e4; ++i) str += char(rand()%(127-32)+32); std::regex_match(str,m,r); return 0; } ,则可以将StackPanestackPane.visibleProperty()绑定:

toggleButton.selectedProperty()

在此示例中:stackPane.visibleProperty() .bind(Bindings.when(toggleButton.selectedProperty()) .then(false) .otherwise(true) ); toggleButton.isSelected() --> !stackPane.isVisible(), 或者听ToggleButton的!toggleButton.isSelected() --> stackPane.isVisible()

events
  

但问题是我想使用Tab切换按钮而不是切换按钮,因此它的行为类似于切换按钮。即,当我的示例代码中单击“第一个标签”时,如果内容可见,则它应该是不可见的,反之亦然。我的意思是只应显示标签

我找到了解决方案。// toggleButton.setOnAction(e ->{ //new .setOnAction() -> Override previous toggleButton.addEventHandler(ActionEvent.ACTION, e ->{ //can add any quantity for your needs if(toggleButton.isSelected()) stackPane.setVisible(false); else stackPane.setVisible(true); }); 没有Tab ...但是

click-handler

,您可以将Tab tab = new Tab(); tab.setContent(stackPane); Label lable = new Label("Label"); //create Label tab.setGraphic(lable); //set Lable as Graphic to Tab lable.setOnMouseClicked(event ->{ //setOnMouseClicked, for example if(stackPane.isVisible()){ stackPane.setVisible(false); }else{ stackPane.setVisible(true); } }); (例如)用作Label - 文本,并将Tab - 处理程序添加到setOnMouseClicked()。您可以使用任何Label Node - &gt; 这取决于您。

例如,您可以使用Handler/ActionListener来显示/隐藏CheckBoxStackPane文字(您可以合并TabFXML - 代码来制作图形):

enter image description here

Java

Tab tab = new Tab("Tab2");          //Tab with Text
tab.setContent(stackPane);          
CheckBox checkBox = new CheckBox(); //create CheckBox 
tab.setGraphic(checkBox);           //set CheckBox as Graphic to Tab
stackPane.visibleProperty()
            .bind(Bindings.when(checkBox.selectedProperty())
                    .then(false)
                    .otherwise(true)
            );

答案 1 :(得分:0)

我想出了以下解决方案:

AtomicReference<Tab> currentTab = new AtomicReference<>(tabPane.getSelectionModel().getSelectedItem());
AtomicReference<Tab> lastTab = new AtomicReference<>(null);
tabPane.setOnMouseReleased(event -> {
    // Check if current node is actually tab
    Node n = event.getPickResult().getIntersectedNode();
    while (n != null && !(n.getStyleClass().contains("headers-region"))) {
        n = n.getParent();
    }
    if (n == null)
        return;

    lastTab.set(currentTab.get());
    currentTab.set(tabPane.getSelectionModel().getSelectedItem());

    if (currentTab.get() == lastTab.get()) {
        // Hide
        tabPane.setPrefSize(28, 28);
        //tabPane.getSelectionModel().clearSelection(); // notify selection model
        currentTab.set(null);
    } else {
        // Show
        tabPane.setPrefSize(-1,-1);
        currentTab.set(tabPane.getSelectionModel().getSelectedItem());
    }
});

首先,我将鼠标事件添加到tabPane中。在此鼠标事件内,检查光标下的节点是否实际上是Tab节点。如果是这样,请执行一些逻辑操作以识别用户要执行的操作:隐藏或显示。隐藏起来有些棘手,所以我最终将TabPane的首选大小设置为28像素宽。

我还试图用空的newValue通知选择模型:

tabPane.getSelectionModel().clearSelection();

但这不能正常工作。调用select(-1)应该调用clearSelection(),但是行为有所不同。

当我在调用clearSelection()之后选择另一个选项卡时,用oldValue == null调用的选择模型处理程序可能不会更新内部索引,并且选项卡不会切换到选定的选项卡。