Java作业-6
JavaFx相关
一个 Observable 类的实例被认为是一个可观察对象,如何添加一个监听器?监听器必须实现什么接口?
实现InvalidationListener接口以重写invalidated(Observable o)
- 解耦监听器与Observable:尽量让监听器与被观察的对象解耦,以便于维护和扩展。
- 避免在ChangeListener内部修改Observable值:这可能导致不可预见的行为。
- 小心内存泄漏:如果你添加了一个监听器但之后没有从Observable对象中移除它,可能会导致内存泄漏。
什么是功能接口?为什么对于一个 lambda 表达式而言,必须是一个功能接口?
一个功能接口(Functional Interface)是具有单一抽象方法(SAM, Single Abstract Method)的接口。这意味着接口中只能有一个没有实现的方法。这种接口可以有多个带有默认或静态实现的方法,但只能有一个抽象方法。
@FunctionalInterface // 注解是可选的,但是有助于编译器检查
public interface MyFunctionalInterface {
void execute();
}
Lambda 表达式的主要目的是提供一种简洁、可读的方式来表示实例化一个单一方法的接口。因为 Lambda 表达式旨在提供一种简单的方式来实现一个方法,所以它自然地适用于具有单一抽象方法的接口。如果接口有多于一个的抽象方法,编译器将无法确定该实现哪一个,这会导致歧义。
对于一个鼠标按下、释放、单击、进入、退出、移动和拖动事件,使用什么方法来注册一个相应的处理器?
rectangle.setOnMousePressed(event -> {
System.out.println("Mouse pressed");
});
rectangle.setOnMouseReleased(event -> {
System.out.println("Mouse released");
});
rectangle.setOnMouseClicked(event -> {
System.out.println("Mouse clicked");
});
rectangle.setOnMouseEntered(event -> {
System.out.println("Mouse entered");
});
rectangle.setOnMouseExited(event -> {
System.out.println("Mouse exited");
});
rectangle.setOnMouseMoved(event -> {
System.out.println("Mouse moved");
});
rectangle.setOnMouseDragged(event -> {
System.out.println("Mouse dragged");
});
使用什么方法来针对键的按下、释放以及敲击事件注册处理器?这些方法定义在哪些类中?
node.setOnKetpressed(event -> {
System.out.println("Pressed");
});
node.setOnKeyReleased(event -> {
System.out.println("Release");
});
node.setOnKeyTyped(event -> {
System.out.println("Typed");
});
定义在javafx.scene.Node类中,因此所有继承自Node的类(如Control,Shape,Text等)都可以使用这些方法。
(创建一个簡单的计算器) 编写一个程序完成加法、减法、乘法和除法操作
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class Caculator extends Application {
@Override
public void start(Stage primaryStage) {
HBox hBox1 = new HBox();
HBox hBox2 = new HBox();
Text text = new Text("Divisor cannot be 0!");
text.setFill(Color.RED);
BorderPane borderPane = new BorderPane();
Button addBtn = new Button("Add");
Button subtractBtn = new Button("Subtract");
Button multiplyBtn = new Button("Multiply");
Button divideBtn = new Button("Divide");
Text num1 = new Text("Number 1");
TextField num1Field = new TextField();
Text num2 = new Text("Number 2");
TextField num2Field = new TextField();
Text result = new Text("Result");
TextField resultField = new TextField();
resultField.setEditable(false);
hBox1.getChildren().addAll(num1, num1Field, num2, num2Field, result, resultField);
hBox1.setSpacing(10);
hBox1.setAlignment(Pos.CENTER);
hBox2.getChildren().addAll(addBtn, subtractBtn, multiplyBtn, divideBtn);
hBox2.setSpacing(20);
hBox2.setAlignment(Pos.CENTER);
addBtn.setOnAction(e -> {
borderPane.getChildren().remove(text);
double num1Value = Double.parseDouble(num1Field.getText());
double num2Value = Double.parseDouble(num2Field.getText());
double resultValue = num1Value + num2Value;
resultField.setText("" + resultValue);
});
subtractBtn.setOnAction(e -> {
borderPane.getChildren().remove(text);
double num1Value = Double.parseDouble(num1Field.getText());
double num2Value = Double.parseDouble(num2Field.getText());
double resultValue = num1Value - num2Value;
resultField.setText("" + resultValue);
});
multiplyBtn.setOnAction(e -> {
borderPane.getChildren().remove(text);
double num1Value = Double.parseDouble(num1Field.getText());
double num2Value = Double.parseDouble(num2Field.getText());
double resultValue = num1Value * num2Value;
resultField.setText("" + resultValue);
});
divideBtn.setOnAction(e -> {
borderPane.getChildren().remove(text);
double num1Value = Double.parseDouble(num1Field.getText());
double num2Value = Double.parseDouble(num2Field.getText());
if (num2Value == 0) {
borderPane.setTop(text);
resultField.clear();
BorderPane.setAlignment(text, Pos.CENTER);
return;
}
double resultValue = num1Value / num2Value;
resultField.setText("" + resultValue);
});
borderPane.setCenter(hBox1);
borderPane.setBottom(hBox2);
Scene scene = new Scene(borderPane, 400, 200);
primaryStage.setScene(scene);
primaryStage.setTitle("Caculator");
primaryStage.show();
}
}
(输入并显示字符串)请编写一个程序,从键盘接收一个字符串并把它显示在面板上。回车键表明字符串结束。任何时候输人一个新字符串时都会将它显示在面板上
package com.example;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class StringDisplay extends Application {
StringBuilder stringBuilder = new StringBuilder(); // 用于存储输入的字符串
Text displayText = new Text(); // 用于显示字符串的Text节点
@Override
public void start(Stage primaryStage) throws Exception {
GridPane root = new GridPane();
TextField textField = new TextField();
// 添加键盘事件处理器
textField.setOnKeyTyped(event -> {
if (event.getCharacter().charAt(0) == '\r') { // 检查是否按下回车键
displayText.setText(stringBuilder.toString()); // 更新Text节点的内容
stringBuilder.setLength(0); // 清空StringBuilder
} else {
stringBuilder.append(event.getCharacter()); // 添加字符到StringBuilder
}
});
HBox hbox1 = new HBox();
HBox hbox2 = new HBox();
hbox1.setAlignment(Pos.CENTER);
hbox1.getChildren().add(textField);
hbox2.setAlignment(Pos.CENTER);
hbox2.getChildren().add(displayText);
root.add(hbox1,0,0); // 添加Text节点到面板
root.add(hbox2,0,1); // 添加TextField到面板
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Display String");
primaryStage.setScene(scene);
primaryStage.show();
}
}
(游戏:手眼协调)请编写一个程序,显示一个半径为10 像素的实心圆,该圆放置在面板上的随机位置,并填充随机的顔色,如图15-29b所示。单击这个圆时,它会消失,然后在另一个随机的位置显示新的随机颜色的圆。在单击了20 个圆之后,在面板上显示所用的时间
import java.util.Random;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
public class RandomCircle extends Application{
private int clickCount = 0; // 单击计数器
private long startTime; // 记录开始时间
@Override
public void start(Stage primaryStage) {
Pane pane = new Pane();
startTime = System.currentTimeMillis(); // 记录开始时间
// 初始化圆
Circle circle = new Circle(10);
setPositionAndColor(circle);
pane.getChildren().add(circle);
// 注册单击事件
circle.setOnMouseClicked(event -> {
clickCount++; // 单击计数器加一
if (clickCount < 20) {
// 设置新的位置和颜色
setPositionAndColor(circle);
} else {
long endTime = System.currentTimeMillis(); // 记录结束时间
long elapsedTime = (endTime - startTime); // 计算所用时间(毫秒)
// 显示所用时间
pane.getChildren().clear();
// 注意:这里简单地使用了JavaFX的Text组件,更多功能可根据需求添加
javafx.scene.text.Text text = new javafx.scene.text.Text(20, 20, "Time: " + elapsedTime + "ms");
pane.getChildren().add(text);
}
});
Scene scene = new Scene(pane, 400, 400);
primaryStage.setTitle("Random Circle");
primaryStage.setScene(scene);
primaryStage.show();
}
private void setPositionAndColor(Circle circle) {
Random rand = new Random();
// 设置随机位置
double x = 20 + rand.nextInt(360);
double y = 20 + rand.nextInt(360);
circle.setCenterX(x);
circle.setCenterY(y);
// 设置随机颜色
double r = rand.nextDouble();
double g = rand.nextDouble();
double b = rand.nextDouble();
circle.setFill(new Color(r, g, b, 1.0));
}
}
(自动改变大小的圆柱)重写编程练习题 14.10, 当窗体改变大小的时候,圆柱的宽度和高度自动改变大小
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.shape.Arc;
import javafx.scene.shape.ArcType;
import javafx.scene.shape.Ellipse;
import javafx.scene.shape.Line;
import javafx.stage.Stage;
public class AutoCylinder extends Application{
@Override
public void start(Stage primaryStage) {
BorderPane pane = getPane();
Scene scene = new Scene(pane, 300, 300);
// 初始化圆柱
resizeCylinder(pane, 300, 300);
// 注册窗体大小改变事件
scene.widthProperty().addListener((observable, oldValue, newValue) -> resizeCylinder(pane, newValue.doubleValue(), scene.getHeight()));
scene.heightProperty().addListener((observable, oldValue, newValue) -> resizeCylinder(pane, scene.getWidth(), newValue.doubleValue()));
primaryStage.setScene(scene);
primaryStage.setTitle("显示圆柱");
primaryStage.show();
}
/** 返回圆柱面板 */
private BorderPane getPane() {
return new BorderPane(new Group());
}
/** 改变圆柱大小 */
private void resizeCylinder(BorderPane pane, double width, double height) {
Group group = new Group();
double X0 = width / 2;
double Y0 = height / 4;
double cylinderHeight = height / 2;
double radiusX = width / 4;
double radiusY = height / 8;
Ellipse topEllipse = new Ellipse(X0, Y0, radiusX, radiusY);
topEllipse.setStyle("-fx-stroke: black; -fx-fill: white;");
Arc dashArc = new Arc(X0, Y0 + cylinderHeight, radiusX, radiusY, 0, 180);
dashArc.setStyle("-fx-fill: white; -fx-stroke: black;");
dashArc.getStrokeDashArray().addAll(6.0, 21.0);
dashArc.setType(ArcType.OPEN);
Arc solidArc = new Arc(X0, Y0 + cylinderHeight, radiusX, radiusY, 180, 180);
solidArc.setStyle("-fx-fill: white; -fx-stroke: black;");
solidArc.setType(ArcType.OPEN);
Line left = new Line(X0 - radiusX, Y0, X0 - radiusX, Y0 + cylinderHeight);
Line right = new Line(X0 + radiusX, Y0, X0 + radiusX, Y0 + cylinderHeight);
group.getChildren().addAll(topEllipse, dashArc, solidArc, left, right);
pane.setCenter(group);
}
}