JavaFX Button常用相关属性和制作多边形按钮Button

Button常用相关属性

     pickOnBoundsProperty (pick On Bounds)

       表示组件的鼠标事件在边界范围处理方式,如果 pickOnBounds为true,则通过与该节点的边界相交来计算拾取,否则通过与该节点的几何形状相交来计算拾取。官网原文解释

   Defines how the picking computation is done for this node when triggered by a MouseEvent or a contains function call. If pickOnBounds is true, then picking is computed by intersecting with the bounds of this node, else picking is computed by intersecting with the geometric shape of this node.

       ​​​​说简单点就是,该属性为true时,假如该组件(按钮)是圆形的,此时鼠标的事件相应范围是能框住这个组件的矩形;当该属性为false时,此时鼠标的事件相应范围是该组件本身的形状,也就是这个圆形。下边会举一个比较清晰直观的例子。

     mouseTransparentProperty (Mouse Transparent)

       表示如果 mouseTransparent 为true,此节点(及其所有子节点)对鼠标事件完全透明。选择鼠标事件的目标时,不会考虑mouseTransparent设置为true及其子树的节点。官网原文解释

     If true, this node (together with all its children) is completely transparent to mouse events. When choosing target for mouse event, nodes with mouseTransparent set to true and their subtrees won't be taken into account.

        下边的这个例子将清晰直观地演示这个两个属性(注:该例代码修改自LayerClick.java
        先看下效果:

演示pickOnBounds和mouseTransparent属性

        解释:完全可点击、部分可点击、不可点击、指的是ToggleButton的点击状态。当两个属性都没选时,button只有一部分能按动,因为使用的stackpane存放的button和circle,circle在上面(circle的透明度为0.7),盖住了button的一部分。当pickOnBounds为true时,此时circle鼠标事件响应的边界,变成一个矩形(刚好框住圆形), 而button在矩形范围内,所以此时button完全被circle盖住了,不能点击。当mouseTransparentProperty为true时,此时circle对鼠标透明,所以此时button完全都能点击。

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.event.EventHandler;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ToggleButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

// 演示JavaFX节点mouseTransparent和pickOnBounds属性
public class CustomControl extends Application {
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage stage) throws Exception {
        ToggleButton testButton = new ToggleButton("");

        VBox layer1 = new VBox();
        layer1.getChildren().add(testButton);

        Node layer2 = new Circle(100, 100, 100, Color.FIREBRICK);
        layer2.setOnMouseClicked(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                System.out.println("circle click");

            }
        });
        layer2.setOpacity(0.7);

        StackPane stack = new StackPane();
        stack.getChildren().setAll(layer1, layer2);
        stack.setStyle("-fx-background-color: azure;");

        VBox layout = new VBox();
        layout.getChildren().setAll(stack, createControls(testButton, layer2));

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

    private VBox createControls(ToggleButton controlledButton, Node controlledNode) {
        controlledButton.textProperty().bind(Bindings.when(controlledNode.mouseTransparentProperty()).then("完全可点击")
                .otherwise(Bindings.when(controlledNode.pickOnBoundsProperty()).then("不可点击").otherwise("部分可点击"))); // button的text值绑定圆的mouseTransparentProperty和pickOnBoundsProperty

        CheckBox enableMouseTransparency = new CheckBox("激活MouseTransparency");
        enableMouseTransparency.setSelected(controlledNode.isMouseTransparent());
        controlledNode.mouseTransparentProperty().bind(enableMouseTransparency.selectedProperty());
        // 圆的mouseTransparentProperty绑定checkbox的选中属性。
        // mouseTransparentProperty若为true则该节点及其子节点的鼠标事件无效

        CheckBox enablePickOnBounds = new CheckBox("激活Pick On Bounds");
        enablePickOnBounds.setSelected(controlledNode.isPickOnBounds());
        controlledNode.pickOnBoundsProperty().bind(enablePickOnBounds.selectedProperty());
        // 圆的pickOnBoundsProperty绑定checkbox的选中属性
        VBox controls = new VBox(10);
        controls.setStyle("-fx-background-color: cornsilk; -fx-padding: 10;");
        controls.getChildren().addAll(enableMouseTransparency, enablePickOnBounds);

        return controls;
    }
}

制作多边形按钮Button

方法有两种

  1. 将 Button 的背景颜色设置为透明,同时用一张多边形 PNG 格式的图片当作 Button 的背景。这种方法相对简单,但比较粗糙,因为它的边角还是存在的,只不过变成透明的了。
    这里稍微点几个关键的属性就好,实现不难。
    <!--去掉按钮(Button)的边框-->
    -fx-background-insets: 0.0;
    
    <!--按钮背景设置为透明-->
    -fx-background-color: transparent;
    
    <!--图片的相关属性-->
    -fx-background-repeat: no-repeat;
    -fx-background-position: center;
    -fx-background-image: url(yourpath/*.png);
  2. 第二种方法,用Polygon制做出多边形polygon后,用 button.setShape(polygon) 设置按钮的形状,还可以根据需要用button.setRotate(degree) 将按钮旋转。绘制多边形算法可以参考下面这篇文章:如何画一个正多边形,下面以制作六边形按钮为例。

制作六边形按钮

先上个效果图:


Demo.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>

<AnchorPane prefHeight="200.0" prefWidth="300.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="customcontrolexample.DemoControl">
   <children>
      <Button fx:id="button1" layoutX="50.0" layoutY="55.0" mnemonicParsing="false" prefHeight="100.0" prefWidth="100.0" text="Button1" />
      <Button fx:id="button2" layoutX="150.0" layoutY="55.0" mnemonicParsing="false" prefHeight="100.0" prefWidth="100.0" text="Button2" />
   </children>
</AnchorPane>

DemoControl.java

import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.shape.Polygon;

public class DemoControl {
    @FXML
    private Button button1;
    @FXML
    private Button button2;
    
    @FXML
    private void initialize() {
        //正六边形
        double[] path = new double[12];
        for (int q = 0; q < 6; q++) {
            double x = Math.cos(Math.PI / 3.0 * q);
            double y = Math.sin(Math.PI / 3.0 * q);
            //也可以在此处设置组件旋转的角度,如旋转90°,
            //double x = Math.cos(Math.PI / 3.0 * q + Math.PI / 2.0);
            //double y = Math.sin(Math.PI / 3.0 * q + Math.PI / 2.0);
            path[q * 2] = x;
            path[q * 2 + 1] = y;
        }
        Polygon hexagon = new Polygon(path);
        button1.setShape(hexagon);
        button2.setShape(hexagon);
        button1.setRotate(90);//button1旋转90°
    }
}

Demo.java

import java.io.IOException;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;

public class Demo extends Application {

    private AnchorPane rootLayout;

    @Override
    public void start(Stage primaryStage) {
        FXMLLoader loader = new FXMLLoader();
        loader.setLocation(Demo.class.getResource("Demo.fxml"));
        try {
            rootLayout = (AnchorPane) loader.load();
            DemoControl control = loader.getController();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        Scene scene = new Scene(rootLayout);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

 对Button进一步美化

       可以对按钮不同的状态设置不同的背景图片(可以参考这个思路:我一般都是这样做的,比较有点击感。原来的按钮:图片1,悬停状态: 图片2,按住状态: 图片1。先上一个效果图(这部分比较容易实现,我就不放代码了,点出要用到的属性就好,下图是我课设的一部分,后面整理好后,在放完整的图片)。
       效果图:

<!--原来状态-->
#yourButton {
	-fx-background-image: url(path/*.png);
}
<!--悬停状态-->
#yourButton:hover{
	-fx-background-image: url(path/*.png);
} 
<!--按压状态-->
#yourButton:pressed {
	-fx-background-image: url(path/*.png);
}

 在Java代码中更改Button背景图片

       如果需要在Java代码中更改Button背景图片,可按以下方式更改

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) {

        try {
            Pane root = new Pane();
            Button button = new Button();
            //资源文件的类加载器的绝对路径
            String path = getClass().getClassLoader().getResource("application/resources/image/timg.jpg").toExternalForm();
            Image image = new Image(path);
            ImageView imageView = new ImageView(image);
            //更改按钮图像
	        button.setGraphic(imageView);

            root.getChildren().add(button);
            Scene scene = new Scene(root);
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

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

       项目结构:

        效果图:

        上面这个方式可能会出现图像在组件中无法居中的问题,所以建议用CSS进行修改。

String path = getClass().getClassLoader().getResource("类加载资源的绝对路径").toExternalForm();
button.setStyle("-fx-background-image: url('"+path+"')");

        这里顺便提一下,因为Jar文件系统不支持相对路径,如果要将项目打包成 Jar文件或 exe文件,加载引用资源最好使用

/*
 *类加载器的绝对路径,toExternalForm()方法将URL用字符串表示出来
 */
getClass().getClassloader().getResource(path).toExternalForm()

同时注意将资源文件放在src包下,以免资源文件加载不出来。

  • 7
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值