最近想倒腾一下JavaFx技术,利用掌握的相关知识,进行一些学习开发一些工作中需要用到的小工具岂不是美滋滋。于是花了几天的学习和研究,空闲时开发了一款adb工具,将adb命令进行窗口化。效果如下
工具下载地址点击这里
源码预览及下载点击这里
开发过程中有一些代码需要进行总结
1.Main.java入口函数调用Controller
我们有这样的需求,view中有一些东西需要初始化,想把这些方法写在Controller中,但是是无法在Controller构造函数中进行实现的。所以我们需要在Main中进行Controller的调用
Main.java
FXMLLoader loader = new FXMLLoader(getClass().getResource("sample.fxml"));
Parent root = loader.load();
primaryStage.setTitle("adb窗口工具");
primaryStage.setScene(new Scene(root, 900, 550));
primaryStage.setResizable(false);
primaryStage.show();
mController = loader.getController();
mController.initView();//调用initView方法
mController.setOwnerWindow(primaryStage);
2.从界面中匹配view
基于安卓应用的开发经验,我们需要从sample.fxml
上findViewById,获得view。但是JavaFx没有提供类似方法但是提供了以下形式。
sample.fxml
<TextField fx:id="textInput" maxWidth="250" GridPane.columnIndex="1" GridPane.rowIndex="10"/>
Controller.java
import javafx.fxml.FXML;
public class Controller {
@FXML
private TextField textInput;
}
Java文件中变量名需要与fxml文件中fx:id对应
3.fxml中绑定Controller
<!--xxx为最外层布局-->
<xxx xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="top.foxhome.top.adbutil.Controller">
</xxx>
依据fx:controller
属性进行绑定。
5.线程切换
开发过程中使用了new Thread(()->..).start();
然后调用Platform.runLater(()->...);
进行线程切换结果还是引起了阻塞。后续的研究中使用了以下方法方可进行正常的线程切换。
new Thread(new Task<E>() {
@Override
protected E call() throws Exception {//耗时任务,在自线程中运行
for (int index=0;index<100;index++){
updateMessage("msg:"+index);//发送Message
updateProgress(index,100);//发送进度
}
return new E();
}
@Override
protected void succeeded() {//UI线程,运行未除错
super.succeeded();
E obj=getValue();//获取call的return值
}
@Override
protected void failed() {//UI线程,运行出错
super.failed();
}
@Override
protected void updateMessage(String message) {//UI线程,接收Message
super.updateMessage(message);
}
@Override
protected void updateProgress(long workDone, long max) {//UI线程,接收进度
super.updateProgress(workDone, max);
}
}).start();
6.绑定点击事件
我们需要一个按钮或者view能够接收到用户的交互,需要进行事件的绑定,列如一个按钮的点击事件
sample.fxml
<Button fx:id="installApk" mnemonicParsing="false" onAction="#installApk" text="安装APK"/>
当我们输入onAction="#installApk"
IDE即可进行代码提示,我们依据提示在与之绑定的controller
创建对应的方法即可。
Controller.java
public void installApk(ActionEvent actionEvent) {
}
另外推荐使用IDE提示点击进行自动创建,手动创建比较麻烦。
7.按钮的禁用和启用
与安卓开发不同的是,安卓的设计思路是设置是否可用
JavaFX的设计思路是设置是否禁用
installApk.setDisable(true);//禁用
installApk.setDisable(false);//启用
8.应用的退出
如果直接点击窗口上的退出键,JVM并没有进行回收,导致jar文件依旧处于运行之中。所以我们需要监听界面的退出进行jvm回收。
//Stage primaryStage
primaryStage.setOnCloseRequest(event -> {
event.consume();
System.exit(0);
});
primaryStage.show();
9.支持文件拖动到输入框
我们使用应用是通常有拖动文件到输入框的需求,拖动文件后将文件绝对路径输入到输入框。
sample.fxml
<TextArea onDragExited="#getFilePath" fx:id="cmdIput" maxWidth="430" GridPane.columnIndex="1" GridPane.rowIndex="2"/>
通过onDragExited
进行事件绑定。
Controller.java
public void getFilePath(DragEvent event) {
List<File> files = event.getDragboard().getFiles();
}
10.Controller初始化回调
除使用1中提到的方式进行初始化以外你还可以在Controller进行初始化
@FXML
private void initialize() {
System.out.println("initialize");
}