package sample;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Pos;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
public class Main extends Application {
private static Parent build() {
GridPane gridPane = new GridPane();
gridPane.setAlignment(Pos.CENTER);
gridPane.setHgap(10);
gridPane.setVgap(10);
TextField textField = new TextField();
gridPane.add(textField, 0, 0);
Button button = new Button();
button.setText("click me");
gridPane.add(button, 0, 1);
Label label = new Label();
label.setPrefWidth(200);
label.setStyle("-fx-border-color: black; -fx-border-width: 1; -fx-border-radius: 5");
gridPane.add(label, 0, 2);
Controller controller = new Controller();
controller.inputField = textField;
controller.outputLabel = label;
//button.setOnMouseClicked(controller::点击事件);
//button.setOnMouseClicked(event -> controller.点击事件(event));
button.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent mouseEvent) {
controller.点击事件(mouseEvent);
}
});
return gridPane;
}
@Override
public void start(Stage primaryStage) throws Exception{
//Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
Parent root = build();
primaryStage.setTitle("陈沛鑫");
Scene scene = new Scene(root, 300, 275);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
package sample;
import java.net.URL;
public class ResourceDemo {
public static void main(String[] args) {
URL r1 = ResourceDemo.class.getResource(“sample.fxml”);
URL r2 = ResourceDemo.class.getClassLoader().getResource(“root.fxml”);
System.out.println(r1);
System.out.println(r2);
}
}
package sample;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.input.MouseEvent;
import java.util.Date;
public class Controller {
@FXML
public TextField inputField;
@FXML
public Label outputLabel;
// thread 的所有读写操作其实都在主线程中,所以不需要考虑线程安全的问题
private Thread thread = null;
@FXML
public void 点击事件(MouseEvent mouseEvent) {
System.out.println(new Date() + ": 按钮被点击");
// 从输入框中读取文字内容
String inputText = inputField.getText();
System.out.println("用户输入了: " + inputText);
try {
int n = Integer.parseInt(inputText.trim());
// 主线程
if (thread != null) {
thread.interrupt();
}
thread = new Thread(() -> {
long r = fib(n); // <--- 目前在子线程中进行
// <--- 在 UI 中,主线程的核心工作是响应事件
// <--- 解决办法:不要把可能耗时比较久的操作,放到主线程中进行
// 涉及 UI 修改的,最好回到主线程中进行
// 如果多个线程同时操作 UI 界面,可能有线程安全问题
System.out.printf("fib(%d) = %d\n", n, r);
if (Thread.interrupted()) {
// 前提是 thread == this。thread 是我这个线程
// 如果 thread 指向别的线程了,我没有权力把 thread 修改
// 由于当前线程被中断了,所以很大可能 thread 已经指向了其他线程了
// 没有权力修改 thread 了
// thread = null; // <-- 这里加这句代码对不对? 所以不对
return;
}
Platform.runLater(() -> {
// 以事件方式通知主线程执行该操作
// 主线程中
outputLabel.setText(String.valueOf(r));
// 能保证 thread 就是 当前线程么?
//thread = null; // 不行,所以有 BUG
});
});
thread.start();
} catch (NumberFormatException exc) {
outputLabel.setText("请输入合法的数字");
}
}
// 故意使用特别慢的及算法方式,时间复杂度是 O(2^n)
private long fib(int n) {
if (n < 2) {
return 1;
}
return fib(n - 1) + fib(n - 2);
}
}
<?import javafx.geometry.Insets?> <?import javafx.scene.layout.GridPane?> <?import javafx.scene.control.Button?> <?import javafx.scene.control.Label?> <?import javafx.scene.control.TextField?>