JavaFX 选项卡窗格下拉列表中不考虑图像视图大小

Image view size not respected in JavaFX tab pane dropdown

我正在使用 JavaFX TabPane,其中一个选项卡设置了图像。实际图像比需要的大,所以我使用 ImageView.setFitHeight(int)ImageView.setFitWidth(int) 来更改图像大小。

标签标签本身看起来不错,但是当我添加太多标签并添加标签下拉列表时,下拉列表中的尺寸显示为原始图像尺寸。关于如何更改下拉菜单中的图像大小的任何想法?

最小可重现示例:

public class TabGraphicsIssueDemo extends Application {

    private static final int TAB_IMAGE_SIZE = 15;
    
    @Override
    public void start(Stage primaryStage) throws Exception {
        
        TabPane pane = new TabPane();
        
        ImageView image = new ImageView(new Image(new FileInputStream("smile.jpg")));
        image.setFitHeight(TAB_IMAGE_SIZE);
        image.setFitWidth(TAB_IMAGE_SIZE);
        
        Tab imageTab = new Tab();
        imageTab.setGraphic(image);
        pane.getTabs().add(imageTab);
        
        for(int i = 0; i < 10; i++) {
            pane.getTabs().add(new Tab("Tab " + i));
        }
        
        
        primaryStage.setScene(new Scene(pane, 300, 300));
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
    
}

结果:

当前版本(JavaFX 版本 17)中的实现以相当原始的方式复制了 Labels 和 ImageViews(因此它们可以同时出现在选项卡和选项卡菜单中)。如果 Tab 的图形是 ImageView,则会创建一个新的 ImageView,其 ImageProperty 绑定到原始 ImageViewimageProperty .但是,不会复制其他属性,例如 fitWidthfitHeight

因此,解决方法是调整 Image 而不是 ImageView 的大小。这意味着选项卡菜单使用的 ImageView 也将引用调整大小的 Image,并且不需要 fitHeightfitWidth set:

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

        TabPane pane = new TabPane();

        ImageView image = new ImageView(new Image(new FileInputStream("smile.jpg"),
                                      TAB_IMAGE_SIZE, TAB_IMAGE_SIZE, true, true));

//        image.setFitHeight(TAB_IMAGE_SIZE);
//        image.setFitWidth(TAB_IMAGE_SIZE);


        Tab imageTab = new Tab();
        imageTab.setGraphic(image);
        pane.getTabs().add(imageTab);

        for(int i = 0; i < 10; i++) {
            pane.getTabs().add(new Tab("Tab " + i));
        }


        primaryStage.setScene(new Scene(pane, 300, 300));
        primaryStage.show();
    }