表示组件的鼠标事件在边界范围处理方式,如果 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时,此时鼠标的事件相应范围是该组件本身的形状,也就是这个圆形。下边会举一个比较清晰直观的例子。
表示如果 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)
先看下效果:
解释:完全可点击、部分可点击、不可点击、指的是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() {
@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;
}
}
方法有两种
-fx-background-insets: 0.0;
-fx-background-color: transparent;
-fx-background-repeat: no-repeat;
-fx-background-position: center;
-fx-background-image: url(yourpath/*.png);
第二种方法,用Polygon制做出多边形polygon后,用 button.setShape(polygon) 设置按钮的形状,还可以根据需要用button.setRotate(degree) 将按钮旋转。绘制多边形算法可以参考下面这篇文章:如何画一个正多边形,下面以制作六边形按钮为例。
先上个效果图:
Demo.fxml
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);
}
}
可以对按钮不同的状态设置不同的背景图片(可以参考这个思路:我一般都是这样做的,比较有点击感。原来的按钮:图片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背景图片,可按以下方式更改
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包下,以免资源文件加载不出来。