Reputation: 1668
I want to display label is empty at the center:
private TabPane tabPane = new TabPane();
private Text placeHolder = new Text("Empty");
placeHolder.setFont(Font.font(null, FontWeight.BOLD, 20));
placeHolder.visibleProperty().bind(Bindings.isEmpty(tabPane.getChildren()));
What is the proper way to implement this?
Upvotes: 1
Views: 1095
Reputation: 49185
TabPane
does not have a ready-to-use placeholder like a TableView
does. You may try 3 different approaches:
1) Using custom skin, and set it via -fx-skin
.
package my.skin;
import com.sun.javafx.scene.control.skin.TabPaneSkin;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.control.TabPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
public class CustomTabPaneSkin extends TabPaneSkin
{
private final VBox placeHolder;
private final Label placeHolderText;
public CustomTabPaneSkin( TabPane tabPane )
{
super( tabPane );
placeHolderText = new Label( "Empty" );
placeHolderText.setFont( Font.font( null, FontWeight.BOLD, 20 ) );
placeHolderText.setAlignment( Pos.CENTER );
placeHolderText.minWidthProperty().bind( getSkinnable().widthProperty() );
placeHolderText.minHeightProperty().bind( getSkinnable().heightProperty() );
placeHolder = new VBox( placeHolderText );
for ( Node node : getChildren() )
{
if ( node.getStyleClass().contains( "tab-header-area" ) )
{
Pane headerArea = ( Pane ) node;
// Header area is hidden if there is no tabs, thus when the tabpane is "empty"
headerArea.visibleProperty().addListener( ( observable, oldValue, newValue )
->
{
if ( newValue )
{
getChildren().remove( placeHolder );
}
else
{
getChildren().add( placeHolder );
}
}
);
break;
}
}
}
}
and in custom css file
.tab-pane {
-fx-skin: "my.skin.CustomTabPaneSkin";
}
That's all. Use tabpanes as in usual way.
2) Using custom wrapper that holds tabpane and placeholder
@Override
public void start( Stage primaryStage )
{
TabPaneHolder tabPaneHolder = new TabPaneHolder( new Tab( "tab 1" ) );
tabPaneHolder.getTabs().add( new Tab( "tab 2" ) );
Scene scene = new Scene( tabPaneHolder, 350, 200 );
primaryStage.setScene( scene );
primaryStage.show();
}
public class TabPaneHolder extends VBox
{
private final TabPane tabPane;
private final Text placeHolder;
public TabPaneHolder( Tab... tabs )
{
this( "Empty", tabs );
}
public TabPaneHolder( String emptyMessage, Tab... tabs )
{
this.tabPane = new TabPane( tabs );
placeHolder = new Text( emptyMessage );
placeHolder.setFont( Font.font( null, FontWeight.BOLD, 20 ) );
BooleanBinding bb = Bindings.isEmpty( tabPane.getTabs() );
placeHolder.visibleProperty().bind( bb );
placeHolder.managedProperty().bind( bb );
getChildren().addAll( placeHolder, tabPane );
alignmentProperty().bind( Bindings.when( bb ).then( Pos.CENTER ).otherwise( Pos.TOP_LEFT ) );
}
public ObservableList<Tab> getTabs()
{
return tabPane.getTabs();
}
}
3) Simple, direct approach
@Override
public void start( Stage primaryStage )
{
TabPane tabPane = new TabPane();
tabPane.getTabs().add( new Tab( "tab" ) );
Text placeHolder = new Text( "Empty" );
placeHolder.setFont( Font.font( null, FontWeight.BOLD, 20 ) );
BooleanBinding bb = Bindings.isEmpty( tabPane.getTabs() );
placeHolder.visibleProperty().bind( bb );
placeHolder.managedProperty().bind( bb );
Scene scene = new Scene( new VBox( placeHolder, tabPane ), 350, 200 );
primaryStage.setScene( scene );
primaryStage.show();
}
Upvotes: 5