【问题标题】:JavaFX - Create Button from IconJavaFX - 从图标创建按钮
【发布时间】:2018-11-12 06:35:15
【问题描述】:

我最近开始使用 JavaFX 进行自定义控件,并且想知道创建一个简单的图像按钮的最佳方法是什么。例如,在 Stack Overflow 上,我们有这些按钮(我想实际上它们是链接,但我希望在 JavaFX 中具有相同的效果)看起来根本不像按钮。

在 JavaFX 中创建类似内容的最佳方法是什么?我知道您可以将图像添加到按钮,但是否还有一种方法可以完全移除背景(我怀疑有)?

【问题讨论】:

  • 在我看来,使用 Button 也不是最好的方法。您可以使用超链接,但我建议使用带有侦听器的 ImageView,因为我发现它更节省内存。

标签: button javafx icons custom-controls


【解决方案1】:

我在我的项目中使用自定义 ImageButton 类。这类似于fabian 的方法,但使用ImageView。在我看来,实现起来也更简单一些。

public class ImageButton extends Button {

    private final String STYLE_NORMAL = "-fx-background-color: transparent; -fx-padding: 2, 2, 2, 2;";
    private final String STYLE_PRESSED = "-fx-background-color: transparent; -fx-padding: 3 1 1 3;";

    public ImageButton(Image originalImage, double h, double w) {

        ImageView image = new ImageView(originalImage);
        image.setFitHeight(h);
        image.setFitHeight(w);
        image.setPreserveRatio(true);
        setGraphic(image);
        setStyle(STYLE_NORMAL);

        setOnMousePressed(event -> setStyle(STYLE_PRESSED));
        setOnMouseReleased(event -> setStyle(STYLE_NORMAL));
    }

}

那么您只需将Image 和尺寸传递给它:

ImageButton newButton = new ImageButton(new Image("icon.png"), 16, 16);

【讨论】:

    【解决方案2】:

    只需相应地设置按钮的graphic 属性即可。

    由于 stackoverflow 使用 svg 路径,以下示例使用 SVGPath,但它可以轻松更改为 ImageView,并且缩放可以替换为设置 fitWidth/fitHeight。如果你确实想使用ImageView,你应该知道ImageView不提供fill属性,你需要使用不透明度或不同的图像。

    public static Button createIconButton(String svg) {
        SVGPath path = new SVGPath();
        path.setContent(svg);
        Bounds bounds = path.getBoundsInLocal();
    
        // scale to size 20x20 (max)
        double scaleFactor = 20 / Math.max(bounds.getWidth(), bounds.getHeight());
        path.setScaleX(scaleFactor);
        path.setScaleY(scaleFactor);
        path.getStyleClass().add("button-icon");
    
        Button button = new Button();
        button.setPickOnBounds(true); // make sure transparent parts of the button register clicks too
        button.setGraphic(path);
        button.setAlignment(Pos.CENTER);
        button.getStyleClass().add("icon-button");
    
        return button;
    }
    
    @Override
    public void start(Stage primaryStage) {
        // the following svg paths were copied from the stackoverflow website
        HBox root = new HBox(
                createIconButton("M15.19 1H4.63c-.85 0-1.6.54-1.85 1.35L0 10.79V15c0 1.1.9 2 2 2h16a2 2 0 0 0 2-2v-4.21l-2.87-8.44A2 2 0 0 0 15.19 1zm-.28 10l-2 2h-6l-2-2H1.96L4.4 3.68A1 1 0 0 1 5.35 3h9.12a1 1 0 0 1 .95.68L17.86 11h-2.95z"),
                createIconButton("M15 2V1H3v1H0v4c0 1.6 1.4 3 3 3v1c.4 1.5 3 2.6 5 3v2H5s-1 1.5-1 2h10c0-.4-1-2-1-2h-3v-2c2-.4 4.6-1.5 5-3V9c1.6-.2 3-1.4 3-3V2h-3zM3 7c-.5 0-1-.5-1-1V4h1v3zm8.4 2.5L9 8 6.6 9.4l1-2.7L5 5h3l1-2.7L10 5h2.8l-2.3 1.8 1 2.7h-.1zM16 6c0 .5-.5 1-1 1V4h1v2z"));
    
        Scene scene = new Scene(root);
        scene.getStylesheets().add("style.css");
        primaryStage.setScene(scene);
        primaryStage.show();
    }
    

    style.css

    /* set default fill of svg path */
    .icon-button .button-icon {
        -fx-fill: #888888;
    }
    
    /* set default fill of svg path */
    .icon-button:focused {
        -fx-background-color: lightblue;
        -fx-background-radius: 0;
    }
    
    /* remove default button style & set size */
    .icon-button {
        -fx-background-color: transparent, transparent, transparent, transparent, transparent;
        -fx-pref-height: 30;
        -fx-pref-width: 30;
        -fx-min-height: 30;
        -fx-min-width: 30;
        -fx-max-height: 30;
        -fx-max-width: 30;
    }
    
    /* modify svg path fill for hovered/pressed button */
    .icon-button:pressed .button-icon,
    .icon-button:hover .button-icon {
        -fx-fill: #444444;
    }
    

    【讨论】:

    • 此实现仍然包含按钮边框,因此它显示为标准按钮,而不仅仅是可点击的图像。
    • @Zephyr 仅当按钮获得焦点时才显示按钮的背景。如果这不是所需的效果,您可以轻松地从 CSS 样式表中删除此规则。由于标准按钮是通过结合背景来实现的,所以边框被移除了。
    • 啊,对不起;我在测试中加载 style.css 时遇到问题。
    【解决方案3】:

    尽管这是一篇旧文章,但对于那些使用 SceneBuilder 的人来说,知道您可以使用 Button 和 ImageView 来做到这一点仍然可能是件好事:

    (我正在使用 Gluon SceneBuilder)

    按钮设置:

    Under 'Graphic' set the Display to 'GRAPHIC_ONLY'

    Then for the in-line CSS use: -fx-background-colour: transparent;

    ImageView:

    Set the image to whatever you want
    In the 'Hierarchy' pick up and drop the ImageView onto the button

    完成后的样子:

    Transparent Button ~ with only Image shown

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-13
      • 1970-01-01
      • 2016-10-17
      • 2014-06-27
      • 2015-07-04
      • 2015-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多