JavaFX入门笔记

背景

Java选修课第四次实验

所需工具

  • IDEA
  • JavaFX插件(需要Maven)
  • JavaFX Scene Builder

参考资料

开始操作

安装JavaFX插件

File -> Settings -> Plugins中搜索javafx然后下载第一个



之后便可以在IDEA中创建JavaFX项目

配置JavaFX Scene Builder

https://www.oracle.com/java/technologies/javafxscenebuilder-1x-archive-downloads.html 从网址下载适合自己电脑的版本

点击运行进行安装

点击下一步自行安装即可

安装完毕后电脑桌面会出现如图图标

创建项目



此处放上最终项目目录

设计界面

  1. 先对自动生成的.fxml文件和启动类改名,此处分别改为mainWindow和MainWindow
  2. 右键mainWindow.fxml并选择在SceneBuilder打开

  3. 设计界面

  4. 进行相关绑定
  • 在IDEA中打开mainWindow.fxml
  • 注意:给控件设置id时要写fx:id="",不能只写id="",否则将无法绑定!!!

编写DAO包中的类(实现文件读写操作)

CustomerDAO.java源码:

package banking.DAO;

import javafx.util.Pair;

import java.io.IOException;
import java.io.RandomAccessFile; public class CustomerDAO { //Specify the size of two string fields in the record
final static int FIRST_NAME_SIZE = 16;//FirstName最大长度(也是存储长度,不足则用空格不足)
final static int LAST_NAME_SIZE = 16;//LastName最大长度
public final static int CUSTOMER_SIZE = (FIRST_NAME_SIZE + LAST_NAME_SIZE);//每份数据的最大长度 //写入用户数据
public static void writeCustomr(String first, String last, RandomAccessFile raf) {
try {
raf.seek(raf.length());//在文件尾部进行写操作
FixedLengthStringIO.writeFixedLengthString(
first, FIRST_NAME_SIZE, raf
);//写入firstname
FixedLengthStringIO.writeFixedLengthString(
last, LAST_NAME_SIZE, raf
);//写入lastname
} catch (IOException e) {
e.printStackTrace();
}
} //在指定位置写入用户数据
public static void writeCustomer(String first, String last, RandomAccessFile raf, long position) {
try {
raf.seek(position);//前往特定位置进行写操作
FixedLengthStringIO.writeFixedLengthString(
first, FIRST_NAME_SIZE, raf
);//写入firstname
FixedLengthStringIO.writeFixedLengthString(
last, LAST_NAME_SIZE, raf
);//写入lastname
} catch (IOException e) {
e.printStackTrace();
}
} //读出用户数据
public static Pair readCustomer(long position, RandomAccessFile raf) throws IOException{
raf.seek(position);//前往特定位置进行读操作 String first = FixedLengthStringIO.readFixedLengthString(
FIRST_NAME_SIZE, raf
); //读出firstname
String last = FixedLengthStringIO.readFixedLengthString(
LAST_NAME_SIZE, raf
); //读出lastname //返回一个记录姓名的键值对
return new Pair<String, String>(first, last);
}
}

编写控制类(实现各自操作)

  • Add:将用户输入的客户名添加进文件中并在List显示
  • Del:将用户输入的客户名在文件中删除并更新List;若输入的客户名不存在则提示删除失败
  • Search:查找用户输入的客户名,若存在则会在List中置顶;若不存在则提示查找失败
  • Sort:将现有数据按照姓名进行排序并在List更新
package banking.controller;

import java.io.IOException;
import java.io.RandomAccessFile; import java.net.URL;
import java.util.*; import banking.DAO.CustomerDAO;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.util.Pair; public class CustomersController implements Initializable{
//对以下几个成员变量进行@FXML注入,注意变量名与fxml文件中的fx:id对应相同
//添加@FXML注解表明与fxml文件进行绑定
@FXML
private ListView customersList;
@FXML
private TextField firstName;
@FXML
private TextField lastName; // Access customers.dat using RandomAccessFile
private RandomAccessFile raf; // A list which stores customers' name
List<String>names = new ArrayList<>(); //重写初始化函数,类似于构造函数
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
// Open or create a random access file
try {
raf = new RandomAccessFile("customers.dat", "rw");
}
catch(IOException ex) {
System.out.print("Error: " + ex);
System.exit(0);
} //设置ListView不可编辑
customersList.setEditable(false); //将文件中原先存有的数据读出并展示
try {
getCustomersFromRAF();
} catch (IOException e) {
e.printStackTrace();
} } //add事件
//添加@FXML注解表明与fxml文件进行绑定
@FXML
protected void onAddButtonClick() throws IOException {
//调用接口写入客户名
CustomerDAO.writeCustomer(firstName.getText(), lastName.getText(), raf);
getCustomersFromRAF();//读出数据并展示
} //del事件
//添加@FXML注解表明与fxml文件进行绑定
@FXML
protected void onDelButtonClick() throws IOException {
//获取用户输入的客户名
String target = clearSpaces(firstName.getText() + ',' + lastName.getText());
if (names.contains(target)) {//若该客户名存在
//重新读取文件内容
long currentPosition = 0;//定位指针
names.clear();//清空列表,准备重新读入
while (currentPosition < raf.length()) {
//读出客户名,存在Pair对象中
Pair<String, String>customer = CustomerDAO.readCustomer(currentPosition, raf);
//对读出的客户名进行拼接操作
String name = clearSpaces(customer.getKey()) + ',' + clearSpaces(customer.getValue());
// System.out.println(name);
names.add(name);//在客户名列表中新增 //自增(偏移量)
//注意要2*CustomerDAO.CUSTOMER_SIZE
//具体原因不清楚,但.dat文件中每条数据的长度为2 * CustomerDAO.CUSTOMER_SIZE
//因此偏移量为2 * CustomerDAO.CUSTOMER_SIZE而不是CustomerDAO.CUSTOMER_SIZE
currentPosition += 2 * CustomerDAO.CUSTOMER_SIZE;
} //用最后一条数据覆盖要删除的数据
String[]name = names.get(names.size()-1).split(",");//获取最后一条数据并存在字符串数组中
//写入位置names.indexOf(target) * 2 * CustomerDAO.CUSTOMER_SIZE
//解读:
//names.indexOf(target)为要删除的数据在客户名列表中对应的索引,也为在文件中的索引
//将此索引乘以偏移量,即为此条数据在文件中的具体位置,然后进行写入操作即可覆盖
CustomerDAO.writeCustomer(name[0], name[1], raf,names.indexOf(target) * 2 * CustomerDAO.CUSTOMER_SIZE);
raf.setLength(raf.length() - 2 * CustomerDAO.CUSTOMER_SIZE);//重置raf数据长度(删除最后一条数据) //重新展示
getCustomersFromRAF();
} else {
//新建一个对话框提示删除失败
Dialog<ButtonType> warning = new Dialog<>();
warning.getDialogPane().getButtonTypes().add(new ButtonType("确认", ButtonBar.ButtonData.OK_DONE));
warning.setTitle("删除失败");
warning.setContentText("该客户不存在");
warning.show();
} } //search事件
//添加@FXML注解表明与fxml文件进行绑定
@FXML
protected void onSearchButtonClick() {
//查找该元素并交换位置
String target = clearSpaces(firstName.getText() + ',' + lastName.getText());
if (names.contains(target)) {//若要查找的客户名存在
Collections.swap(names, 0, names.indexOf(target));//则将其置顶,即放在names中第一个元素的位置
//将names的数据放入ListView中
ObservableList<String>items = FXCollections.observableArrayList(names);
customersList.setItems(items);
} else {
//新建一个对话框提示查找失败
Dialog<ButtonType> warning = new Dialog<>();
warning.getDialogPane().getButtonTypes().add(new ButtonType("确认", ButtonBar.ButtonData.OK_DONE));
warning.setTitle("查找失败");
warning.setContentText("该客户不存在");
warning.show();
}
} //sort事件
//添加@FXML注解表明与fxml文件进行绑定
@FXML
protected void onSortButtonClick() {
//对names进行排序
names.sort(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
String[] name1 = o1.split(",");
String[] name2 = o2.split(",");
if (name1[1].equals(name2[1])) {
return name1[0].compareTo(name2[0]);
} else {
return name1[1].compareTo(name2[1]);
}
}
});
//将排序后的names的数据放入ListView中
ObservableList<String>items = FXCollections.observableArrayList(names);
customersList.setItems(items);
} //从文件中读取数据并存入names然后展示
protected void getCustomersFromRAF() throws IOException {
long currentPosition = 0;
names.clear();
while (currentPosition < raf.length()) {
//读出客户名,存在Pair对象中
Pair<String, String>customer = CustomerDAO.readCustomer(currentPosition, raf);
//对读出的客户名进行拼接操作
String name = clearSpaces(customer.getKey()) + ',' + clearSpaces(customer.getValue());
// System.out.println(name);
names.add(name);//在客户名列表中新增 //自增(偏移量)
//注意要2*CustomerDAO.CUSTOMER_SIZE
//具体原因不清楚,但.dat文件中每条数据的长度为2 * CustomerDAO.CUSTOMER_SIZE
//因此偏移量为2 * CustomerDAO.CUSTOMER_SIZE而不是CustomerDAO.CUSTOMER_SIZE
currentPosition += 2 * CustomerDAO.CUSTOMER_SIZE;
}
//获取姓名
ObservableList<String>items = FXCollections.observableArrayList(names);
customersList.setItems(items);
} //清空后缀空格
public String clearSpaces(String s) {
char[] chars = s.toCharArray();
for (int i = s.length() - 1; i >= 0; i--) {
if (chars[i] != ' ') {
//从后往前找到第一个非空格的字符并截取
return s.substring(0, i + 1);
}
}
return "";//若原字符串全是空格/为空则返回空串
} }

配置启动类

在MainWindow.java中简单修改一下窗口尺寸和title即可运行

package banking.UI;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage; import java.io.IOException; public class MainWindow extends Application {
@Override
public void start(Stage stage) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(MainWindow.class.getResource("mainWindow.fxml"));
Scene scene = new Scene(fxmlLoader.load(), 577, 286);
stage.setTitle("banking");
stage.setScene(scene);
stage.show();
} public static void main(String[] args) {
launch();
}
}

运行启动类

运行后效果如图:

JavaFX入门笔记的更多相关文章

  1. 每天成长一点---WEB前端学习入门笔记

    WEB前端学习入门笔记 从今天开始,本人就要学习WEB前端了. 经过老师的建议,说到他每天都会记录下来新的知识点,每天都是在围绕着这些问题来度过,很有必要每天抽出半个小时来写一个知识总结,及时对一天工 ...

  2. ES6入门笔记

    ES6入门笔记 02 Let&Const.md 增加了块级作用域. 常量 避免了变量提升 03 变量的解构赋值.md var [a, b, c] = [1, 2, 3]; var [[a,d] ...

  3. [Java入门笔记] 面向对象编程基础(二):方法详解

    什么是方法? 简介 在上一篇的blog中,我们知道了方法是类中的一个组成部分,是类或对象的行为特征的抽象. 无论是从语法和功能上来看,方法都有点类似与函数.但是,方法与传统的函数还是有着不同之处: 在 ...

  4. React.js入门笔记

    # React.js入门笔记 核心提示 这是本人学习react.js的第一篇入门笔记,估计也会是该系列涵盖内容最多的笔记,主要内容来自英文官方文档的快速上手部分和阮一峰博客教程.当然,还有我自己尝试的 ...

  5. redis入门笔记(2)

    redis入门笔记(2) 上篇文章介绍了redis的基本情况和支持的数据类型,本篇文章将介绍redis持久化.主从复制.简单的事务支持及发布订阅功能. 持久化 •redis是一个支持持久化的内存数据库 ...

  6. redis入门笔记(1)

    redis入门笔记(1) 1. Redis 简介 •Redis是一款开源的.高性能的键-值存储(key-value store).它常被称作是一款数据结构服务器(data structure serv ...

  7. OpenGLES入门笔记四

    原文参考地址:http://www.cnblogs.com/zilongshanren/archive/2011/08/08/2131019.html 一.编译Vertex Shaders和Fragm ...

  8. OpenGLES入门笔记三

    在入门笔记一中比较详细的介绍了顶点着色器和片面着色器. 在入门笔记二中讲解了简单的创建OpenGL场景流程的实现,但是如果在场景中渲染任何一种几何图形,还是需要入门笔记一中的知识:Vertex Sha ...

  9. unity入门笔记

    我于2010年4月1日硕士毕业加入完美时空, 至今5年整.刚刚从一家公司的微端(就是端游技术+页游思想, 具体点就是c++开发, directX渲染, 资源采取所需才会下载)项目的前端主程职位离职, ...

  10. System Generator入门笔记

    System Generator入门笔记  [CPLD/FPGA] 发布时间:2010-04-08 23:02:09  System Generator是Xilinx公司进行数字信号处理开发的一种设计 ...

随机推荐

  1. Linkerd、Consul、Istio、Kuma、Traefik、AWS App服务网格全方位对比

  2. 从应用访问Pod元数据-DownwardApi的应用

    对于某些需要调度之后才能知道的数据,比如 pod 的 ip,主机名,或者 pod 自身的名称等等,k8s 依旧很贴心的提供了 Downward API 的方式来获取此类数据,并且可以通过环境变量或者文 ...

  3. Docker | 数据持久化与数据共享

    数据持久化(安装MySQL) 参考另一篇Docker安装mysql: https://www.cnblogs.com/all-smile/p/16778376.html MySQL的数据持久化问题 # ...

  4. Azure DevOps Pipelines部署.Net Core 应用到Kubernetes

    一.    先决条件 1.Azure Repos Git/Git和项目上传 把本地的Net Core项目上传至Azure Repos Git/Git 2.Docker Registry Service ...

  5. Python模拟服务端

    本机服务端 import socket # 获取到socket sk = socket.socket() # 获取到地址 ip 和 端口号 address = ('127.0.0.1', 8001) ...

  6. 腾讯云短信SDK-精简版

    /** * 腾讯云短信SDK-精简版 * 本模块使用-向腾讯云短信服务器发送请求 * @return json 腾讯服务器返回值-json字符串 */ private function send_sm ...

  7. JS复制粘贴效果

    话不多说.直接上代码 HTML: 1 <div> 2 老师入会密码:<input type="text" id="tPass"> < ...

  8. Ajax的使用(jquery的下载)

    Ajax学习笔记(jquery的下载) JQuery的官网下载 地址:http://jquery.com 右上角的"Download JQuery" 三个可供下载的文件: Prod ...

  9. springboot如何处理矩阵参数类型的url

    矩阵参数类型的url如何处理 首先要开启这个功能 在webconfig类中创建Webconfigurer类 并且设置 urlPathHelper类中的removeSemicolonContent 为f ...

  10. 浅谈MYSQL的索引以及它的数据结构

    什么是索引 mysql的数据是持久化到磁盘的,写SQL查询数据也就是在磁盘的某个位置查找符合条件的数据,但是磁盘IO比起内存效率是极慢的,特别是数据量大的时候,这时候就需要引入索引来提高查询效率: 在 ...