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. CentOS7.9 yum方式安装redis最新版

    yum install -y http://rpms.famillecollet.com/enterprise/remi-release-7.rpm yum --enablerepo=remi ins ...

  2. 普通用户使用CI/CD权限使用

    根据文章:授权用户访问名称空间 (https://www.cnblogs.com/sanduzxcvbnm/p/15015576.html) 进行有关操作后,普通用户点击 会报错如下信息: 解决办法: ...

  3. PostgreSQL 创建表格

    PostgreSQL 使用 CREATE TABLE 语句来创建数据库表格. 语法 CREATE TABLE 语法格式如下: CREATE TABLE table_name( column1 data ...

  4. Codeforces Round #823 (Div. 2) A-D

    比赛链接 A 题解 知识点:贪心. 对于一个轨道,要么一次性清理,要么一个一个清理.显然,如果行星个数大于直接清理的花费,那么选择直接清理,否则一个一个清理.即 \(\sum \min (c,cnt[ ...

  5. Git、TortoiseGit中文安装教程,如何注册Gitee账号进行代码提交,上传代码后主页贡献度没显示绿点(详解)

    今天给大家分享的是 Git 软件和 TortoiseGit 图形化软件的详细安装教程以及如何在 gitee 上进行代码提交. 首先我也是个刚接触 gitee 的一个小白用户,这些都是自己一边学一边记录 ...

  6. 后端框架学习-----mybatis(4)

    文章目录 4.解决属性名和字段名不一致的问题 4.解决属性名和字段名不一致的问题 1.问题.数据库字段名和属性名不一致,导致查出的数据部分为空 2.resultMap(用于解决数据库表中的字段和属性) ...

  7. dubbo的一系列配置与搭建

    dubbo新的版本采用前后端分离技术,在github上下载的时候,不仅仅只是一个dubbo-admin 而是将admin包分离为dubbo-admin-ui前端包和dubbo-admin-server ...

  8. Java 8 Stream API 引入和使用

    引入流 流是什么 流是Java API的新成员,它允许你以声明性的方式处理数据集合.可以看成遍历数据集的高级迭代.流可以透明地并行处理,无需编写多线程代码.我们先简单看一下使用流的好处.下面两段代码都 ...

  9. Windows7下驱动开发与调试体系构建——0.概述

    本文集内容为windows7x64下驱动开发与调试体系构建,内容目录如下: 1.驱动开发的环境准备 2.R3与R0的通信示例 3.自建调试体系概述 4.在x64下使用汇编代码 5.实战反调试标记位(N ...

  10. 三十五、kubernetes NameSpace介绍

    Kubernetes NameSpace 介绍 Kubernetes使用命名空间的概念帮助解决集群中在管理对象时的复杂性问题.命名空间允许将对象分组到一起,便于将它们作为一个单元进行筛选和控制.无论是 ...