JavaFX中MVC例子理解

       JavaFX可以让你使用GUI组件创建桌面应用程序。一个GUI应用程序执行三个任务:接受用户的输入,处理输入,并显示输出。而一个GUI应用程序包含两个
类型的代码:

  • 领域代码。处理特定领域的数据和遵循业务规范。
  • 交互代码。处理用户输入信息。

       MVC模型最大的优点就是同一组数据可以根据需求在不同的界面或表格中显示。例如你可以在web端,桌面端、工控机等不同UI界面上同时查看同一组数据。。MVC模型对应的有三个模型组件:model,view和controller。如下图所示:

        MVC模型介绍。

  • model:由记录数据的领域对象组成。
  • view:显示给用户的界面。
  • controller:处理用户输入,及对用户输入的响应。

       这里有个简单的例子。模型模块PersonTableUtil保存领域数据Person,因为只是显示数据,所有此示例中没有controller模块,显示模块SimplestableView

领域数据Person:

package cn.learnjavafx.ch11;import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyIntegerProperty;
import javafx.beans.property.ReadOnlyIntegerWrapper;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;/*** @copyright 2023-2022* @package   learnjavafx8.ch11* @file      Person.java* @date      2023-07-01 21:31* @author    qiao wei* @version   1.0* @brief     模型类。保存数据,字段使用属性,可以通过注册监听器监听数据更新情况,自动更新属性。* @history*/
public class Person {/*** @class   Person* @date    2023-07-01 21:31* @author  qiao wei* @version 1.0* @brief   Default constructor.* @param* @return* @throws*/public Person() {this("None", "None", null);}/*** @class   Person* @date    2023-07-01 21:32* @author  qiao wei* @version 1.0* @brief   Constructor.* @param   firstName 名。* @param   lastName  姓。* @param   birthDate 出生日期。* @return* @throws*/public Person(String firstName, String lastName, LocalDate birthDate) {this.firstName.set(firstName);this.lastName.set(lastName);this.birthDate.set(birthDate);}public final int getPersonId() {return personId.get();}public final ReadOnlyIntegerProperty getPersonIdProperty() {return personId.getReadOnlyProperty();}/*** @class   Person* @date    2023-07-01 21:37* @author  qiao wei* @version 1.0* @brief   Get first name property.* @param* @return  Person first name.* @throws*/public final String firstName() {return firstName.get();}public final void setFirstName(String firstName) {firstNameProperty().set(firstName);}public final StringProperty firstNameProperty() {return firstName;}public final String lastName() {return lastName.get();}public final void setLastName(String lastName) {lastNameProperty().set(lastName);}public final StringProperty lastNameProperty() {return lastName;}/** birthDate Property */public final LocalDate birthDate() {return birthDate.get();}public final void setBirthDate(LocalDate birthDate) {birthDateProperty().set(birthDate);}public final ObjectProperty<LocalDate> birthDateProperty() {return birthDate;}/*** @class   Person* @date    2023-07-02 10:30* @author  qiao wei* @version 1.0* @brief   Domain specific business rules.* @param   localDate 当地时区日期* @return* @throws*/public boolean isValidBirthDate(LocalDate localDate) {return isValidBirthDate(localDate, new ArrayList<>());}/*** @class   Person* @date    2023-07-08 19:21* @author  qiao wei* @version 1.0* @brief   验证输入的出生日期是否有效。出生日期无效时,将错误日志记录到errorList中。* @param   date 出生日期。* @param   errorList 错误日志。   * @return  出生日期有效返回true,反之返回false。* @throws*/public boolean isValidBirthDate(LocalDate date, List<String> errorList) {if (null == date) {return true;}// Birthdate cannot be in the futureif (date.isAfter(LocalDate.now())) {errorList.add(LocalDate.now().toString() + " : Birth date must not be in future.");return false;}return true;}/*** @class   Person* @date    2023-07-02 11:51* @author  qiao wei* @version 1.0* @brief   重写方法,验证个人信息是否正确。Domain specific business rules。* @param   errorList 错误信息列表。* @return* @throws*/public boolean isValidPerson(List<String> errorList) {return isValidPerson(this, errorList);}/*** @class   Person* @date    2023-07-02 11:53* @author  qiao wei* @version 1.0* @brief   重写方法,验证个人信息是否正确,对个人的姓、名、生日进行有效性验证。Domain specific business*           rules。* @param   person 需要验证的个人信息。* @param   errorList 错误信息列表。记录错误信息。 * @return  true 个人信息有效;false 个人信息无效。* @throws*/public boolean isValidPerson(Person person, List<String> errorList) {boolean isValidPerson = true;String firstName = person.firstName();// 将以下3个判断条件都走一遍,将所有异常信息统计到errorList中if (firstName == null || firstName.trim().length() == 0) {errorList.add("First name must contain minimum one character.");isValidPerson = false;}String lastName = person.lastName();if (null == lastName || 0 == lastName.trim().length()) {errorList.add("Last name must contain minimum one character.");isValidPerson = false;}if ( !isValidBirthDate(this.birthDate.get(), errorList)) {isValidPerson = false;}return isValidPerson;}/*** @class   Person* @date    2023-07-02 12:15* @author  qiao wei* @version 1.0* @brief   根据年龄,返回不同的年龄层。* @param* @return  年龄层,枚举类型。根据不同年龄返回不同年龄层。* @throws*/public AgeCategory getAgeCategory() {if (null == birthDate.get()) {return AgeCategory.UNKNOWN;}// 计算年龄。long years = ChronoUnit.YEARS.between(birthDate.get(), LocalDate.now());if (0 <= years && 2 > years) {return AgeCategory.BABY;} else if (2 <= years && 13 > years) {return AgeCategory.CHILD;} else if (13 <= years && 19 >= years) {return AgeCategory.TEEN;} else if (19 < years && 50 >= years) {return AgeCategory.ADULT;} else if (50 < years) {return AgeCategory.SENIOR;} else {return AgeCategory.UNKNOWN;}}public boolean save(List<String> errorList) {boolean isSaved = false;if (isValidPerson(errorList)) {System.out.println("Saved " + this.toString());isSaved = true;}return isSaved;}@Overridepublic String toString() {StringBuilder stringBuilder = new StringBuilder("[personId=");stringBuilder.append(personId.get()).append(", firstName = ").append(firstName.get()).append(", lastName = ").append(lastName.get()).append(", birthDate = ").append(birthDate.get()).append("]");return stringBuilder.toString();}/*** @date   2023-07-01 21:33* @author qiao wei* @brief  Person id*/private final ReadOnlyIntegerWrapper personId =new ReadOnlyIntegerWrapper(this, "personId", personSequence.incrementAndGet());private final StringProperty firstName =new SimpleStringProperty(this, "firstName", null);private final StringProperty lastName =new SimpleStringProperty(this, "lastName", null);/*** @date   2023-07-01 21:33* @author qiao wei* @brief  出生日期。*/private final ObjectProperty<LocalDate> birthDate =new SimpleObjectProperty<>(this, "birthDate", null);/*** @date   2023-07-01 21:34* @author qiao wei* @brief  Class field. Keeps track of last generated person id.*/private static AtomicInteger personSequence = new AtomicInteger(0);
}

模型模块PersonTableUtil,将Person数据添加到ObservabList中,作为数据模型返回给View。同时,PersonTableUtil有多个static方法返回TableColumn,进行处理,并根据显示模块的要求进行处理。

package cn.learnjavafx.ch13.tableview01;import java.time.LocalDate;import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.TableColumn;
import javafx.scene.control.cell.PropertyValueFactory;import cn.learnjavafx.ch11.Person;/*** @copyright 2023-2022* @package   cn.learnjavafx.ch13.tableview01* @file      PersonTableUtil.java* @date      2023-07-05 20:30* @author    qiao wei* @version   1.0* @brief     模型类。方法getPersonList返回与视图绑定的列表。方法getIdColumn,getFirstNameColumn,*             getLastNameColumn以列的数据格式返回列表中各项的对应值。* @history*/
public class PersonTableUtil {/*** @class   PersonTableUtil* @date    2023-07-06 16:41* @author  qiao wei* @version 1.0* @brief   Default constructor.* @param   * @return  * @throws*/public PersonTableUtil() {}/*** @class   PersonTableUtil* @date    2023-07-05 20:32* @author  qiao wei* @version 1.0* @brief   Retrieve an observable list of person.* @param   * @return  Person列表。要显示的模型。* @throws*/public static ObservableList<Person> getPersonList() {Person p1 = new Person("Ashwin", "Sharan", LocalDate.of(2012, 10, 11));Person p2 = new Person("Advik", "Tim", LocalDate.of(2012, 10, 11));Person p3 = new Person("Layne", "Estes", LocalDate.of(2011, 12, 16));Person p4 = new Person("Mason", "Boyd", LocalDate.of(2003, 4, 20));Person p5 = new Person("Babalu", "Sha", LocalDate.of(1980, 1, 10));return FXCollections.<Person>observableArrayList(p1, p2, p3, p4, p5);}/*** @class   PersonTableUtil* @date    2023-07-05 20:40* @author  qiao wei* @version 1.0* @brief   Retrieve person Id TableColumn.* @param   * @return  Id column.* @throws*/public static TableColumn<Person, Integer> getIdColumn() {/*** 创建显示的列实例。参数Person:列绑定的数据模型。参数Integer:数据模型中数据的类型,类型必须是引用类型。*  “Id”是列表头显示的内容。*/TableColumn<Person, Integer> personIdCol = new TableColumn<>("Id");// 列实例绑定模型的对应属性。personIdCol.setCellValueFactory(new PropertyValueFactory<>("personId"));return personIdCol;}/*** @class   PersonTableUtil* @date    2023-07-05 20:51* @author  qiao wei* @version 1.0* @brief   Retrieve first name TableColumn.* @param   * @return  First name column.* @throws*/public static TableColumn<Person, String> getFirstNameColumn() {TableColumn<Person, String> firstNameColumn = new TableColumn<>("First Name");firstNameColumn.setCellValueFactory(new PropertyValueFactory<>("firstName"));return firstNameColumn;}/*** @class   PersonTableUtil* @date    2023-07-05 20:59* @author  qiao wei* @version 1.0* @brief   Retrieve last name TableColumn.* @param   * @return  Last name column.* @throws*/public static TableColumn<Person, String> getLastNameColumn() {TableColumn<Person, String> lastNameColumn = new TableColumn<>("Last Name");lastNameColumn.setCellValueFactory(new PropertyValueFactory<>("lastName"));return lastNameColumn;}/*** @class   PersonTableUtil* @date    2023-07-05 21:00* @author  qiao wei* @version 1.0* @brief   Retrieve birthdate TableColumn.* @param   * @return  Birthdate column.* @throws*/public static TableColumn<Person, LocalDate> getBirthDateColumn() {TableColumn<Person, LocalDate> birthDateColumn = new TableColumn<>("Birth Date");birthDateColumn.setCellValueFactory(new PropertyValueFactory<>("birthDate"));return birthDateColumn;}
}

SimplestTableView是显示模块,将模型模块中的数据显示出来。

package cn.learnjavafx.ch13.tableview01;import java.time.LocalDate;import javafx.application.Application;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.TableView;
import javafx.scene.layout.VBox;import cn.learnjavafx.ch11.Person;/*** @copyright 2023-2022* @package   cn.learnjavafx.ch13.tableview01* @file      SimplestTableView.java* @date      2023-07-05 22:52* @author    qiao wei* @version   1.0* @brief     * @history*/
public class SimplestTableView extends Application {@Overridepublic void start(Stage primaryStage) {try {start03(primaryStage);} catch (Exception exception) {exception.printStackTrace();}}/*** @class   SimplestTableView* @date    2023-07-05 22:52* @author  qiao wei* @version 1.0* @brief   * @param   primaryStage Main window.* @return  * @throws*/private void start01(Stage primaryStage) throws Exception {// Create a TableView and bind model.TableView<Person> table = new TableView<>(PersonTableUtil.getPersonList());/*** Add columns to the TableView in order.*/table.getColumns().addAll(PersonTableUtil.getIdColumn(), PersonTableUtil.getFirstNameColumn(), PersonTableUtil.getLastNameColumn());// Add a table column in index position.table.getColumns().add(2, PersonTableUtil.getBirthDateColumn());VBox root = new VBox(table);root.setStyle("-fx-padding: 10;"+ "-fx-border-style: solid inside;"+ "-fx-border-width: 2;"+ "-fx-border-insets: 5;"+ "-fx-border-radius: 5;"+ "-fx-border-color: pink;");        Scene scene = new Scene(root);primaryStage.setScene(scene);primaryStage.setTitle("Simplest TableView");primaryStage.show();}/*** @class   SimplestTableView* @date    2023-07-05 22:53* @author  qiao wei* @version 1.0* @brief   设置复合表头,占位符测试。设置表头Name中包含FirstName和LastName。当表格没有内容时,显示占位符内容。* @param   primaryStage 主窗体。* @return  * @throws*/private void start02(Stage primaryStage) throws Exception {// Create a TableView with a list of persons.TableView<Person> table = new TableView<>(PersonTableUtil.getPersonList());// Placeholder。当table没有内容显示时,显示Label内容。table.setPlaceholder(new Label("No visible columns and/or data exist."));// Setup nest table header.TableColumn<Person, String> nameColumn = new TableColumn<>("Name");nameColumn.getColumns().addAll(PersonTableUtil.getFirstNameColumn(), PersonTableUtil.getLastNameColumn());// Inserts columns to the TableView.table.getColumns().addAll(PersonTableUtil.getIdColumn(), nameColumn);/*** 在指定列添加列表信息,列从0开始计数。FirstName和LastName设置在复合表头,只算一列。所以插入“出生日期”列只*  能在0~2列。*/table.getColumns().add(2, PersonTableUtil.getBirthDateColumn());VBox root = new VBox(table);root.setStyle("-fx-padding: 10;"+ "-fx-border-style: solid inside;"+ "-fx-border-width: 2;"+ "-fx-border-insets: 5;"+ "-fx-border-radius: 5;"+ "-fx-border-color: gray;");Scene scene = new Scene(root);primaryStage.setScene(scene);primaryStage.setTitle("Simplest TableView02");primaryStage.show();}private void start03(Stage primaryStage) {// Create a TableView instance and set Placeholder.TableView<Person> tableView = new TableView<>(PersonTableUtil.getPersonList());tableView.setPlaceholder(new Label("No rows to display"));// 调用PersonTableUtil.getIdColumn方法,返回TableColumn。TableColumn<Person, Integer> idColumn = PersonTableUtil.getIdColumn();/*** 创建TableColumn实例,参数Person表示列中显示数据来自于那里,参数String表示显示数据的类型,参数*  First Name是该列显示的列表头内容。*/TableColumn<Person, String> firstNameColumn = new TableColumn<>("First Name");/*** PropertyValueFactory的参数是Person对象的字段,绑定Person的字段显示。* In the example shown earlier, a second PropertyValueFactory is set on the second*  TableColumn instance. The property name passed to the second PropertyValueFactory is*  lastName, which will match the getter method getLastName() of the Person class.*/firstNameColumn.setCellValueFactory(new PropertyValueFactory<>("firstName"));TableColumn<Person, String> lastNameColumn = new TableColumn<>("Last Name");lastNameColumn.setCellValueFactory(new PropertyValueFactory<>("lastName"));tableView.getColumns().addAll(lastNameColumn, firstNameColumn);tableView.getColumns().add(0, idColumn);tableView.getItems().add(new Person("John", "Doe", LocalDate.of(2000, 8, 12)));VBox root = new VBox(tableView);Scene scene = new Scene(root);primaryStage.setScene(scene);primaryStage.show();}
}

启用方法start01的运行结果如下图,02/03方法主要对数据插入不同列,在模型外添加模型数据测试。

start02方法和start03方法自测。

      

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/2643.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Linux】多线程(上)

本文详细介绍了多线程的常见概念 生产者消费者模型将在多线程&#xff08;下&#xff09;继续讲解 欢迎大家指正 提起讨论进步啊 目录 多线程的理解 线程的优点 线程的缺点&#xff1a; 线程的用途 线程VS进程 用户级线程库 POSIX线程库 线程创建&#xff1a; 线程…

springboot整合jwt

JWT介绍 JWT是JSON Web Token的缩写&#xff0c;即JSON Web令牌&#xff0c;是一种自包含令牌。 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准。 JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息&#xff0c;以便于从资源服务器获…

DICOM开源库兼容性问题

常见的DICOM开源库有dcmtk、fo-dicom、dcm4che3等&#xff0c;DICOM开源库遇到的兼容性问题类似&#xff0c;——dcmtk兼容性最强&#xff0c;fo-dicom次之&#xff0c;dcm4che3最差。 本人在dicom医学影像方面从事软件开发已有10几年&#xff0c;用过dcmtk&#xff0c;fo-dico…

Android国际化各国语言简写

<?xml version"1.0" encoding"utf-8"?> <locale-config xmlns:android"http://schemas.android.com/apk/res/android"><locale android:name"af"/> <!-- 南非荷兰语 --><locale android:name"am&qu…

Spark(32):Spark性能调优之Shuffle调优

目录 0. 相关文章链接 1. 调节 map 端缓冲区大小 2. 调节 reduce 端拉取数据缓冲区大小 3. 调节 reduce 端拉取数据重试次数 4. 调节 reduce 端拉取数据等待间隔 5. 调节 SortShuffle 排序操作阈值 0. 相关文章链接 Spark文章汇总 1. 调节 map 端缓冲区大小 在 Spark 任…

基于.net6的WPF程序使用SignalR进行通信

之前写的SignalR通信&#xff0c;是基于.net6api&#xff0c;BS和CS进行通信的。 .net6API使用SignalRvue3聊天WPF聊天_signalr wpf_故里2130的博客-CSDN博客 今天写一篇关于CS客户端的SignalR通信&#xff0c;后台服务使用.net6api 。其实和之前写的差不多&#xff0c;主要在…

Ubuntu22.04密码忘记怎么办 Ubuntu重置root密码方法

在Ubuntu 22.04 或其他更高版本上不小心忘记root或其他账户的密码怎么办&#xff1f; 首先uname -r查看当前系统正在使用的内核版本&#xff0c;记下来 前提&#xff1a;是你的本地电脑&#xff0c;有物理访问权限。其他如远程登录的不适用这套改密方法。 通过以下步骤&#…

写字楼/办公楼能源管理系统的具体应用 安科瑞 许敏

0 引言 随着社会的进步&#xff0c;我国经济的快速发展&#xff0c;企业的办公环境和方式发生了巨大的变化&#xff0c;专业的写字楼在各大城市遍布林立。写字楼的出现使得各地企业办公集中化、高效化&#xff0c;然而写字楼物业管理的同步发展对于企业服务来说更是一个很大的…

SciencePub学术 | 区块链类重点SCIEEI征稿中

SciencePub学术 刊源推荐: 区块链类重点SCIE&EI征稿中&#xff01;信息如下&#xff0c;录满为止&#xff1a; 一、期刊概况&#xff1a; SCI-01 【期刊简介】IF&#xff1a;4.0-4.5&#xff0c;JCR2区&#xff0c;中科院3区&#xff1b; 【检索情况】SCIE&EI双检&…

Mysql+ETLCloud CDC+StarRocks实时数仓同步实战

一、业务需求及其痛点 大型企业需要对各种业务系统中的销售及营销数据进行实时同步分析&#xff0c;例如库存信息、对帐信号、会员信息、广告投放信息&#xff0c;生产进度信息等等&#xff0c;这些统计分析信息可以实时同步到StarRocks中进行分析和统计&#xff0c;StarRocks…

vue注意点:$attrs、$slots!插槽

$attrs 当父组件给子组件传值&#xff0c;子组件并没有接收数据时&#xff0c;此时数据在$attrs中可以拿到&#xff0c;并且如果子组件不需要使用数据&#xff0c;而孙组件需要&#xff0c;则可以直接v-bind"$attrs"传给孙。 <-- 父组件 --> <div><…

[java安全]URLDNS

文章目录 [java安全]URLDNS前言HashMapURLURLStreamHandler调用过程调用链流程图POC [java安全]URLDNS 前言 URLDNS利用链是一条很简单的链子&#xff0c;可以用来查看java反序列化是否存在反序列化漏洞&#xff0c;如果存在&#xff0c;就会触发dns查询请求 它有如下优点&a…

Centos 8 / TencentOS Server 3.1 安装 docker-ce

目录 前言安装 docker-ce设置Docker Hub 镜像缓存参考 前言 TencentOS Server 3.1(与 CentOS 8用户态完全兼容&#xff0c;配套基于社区5.4 LTS 内核深度优化的 tkernel4版本) 安装 docker-ce 先卸载老版本&#xff0c;没有老版本的跳过 yum remove docker \docker-client \d…

vue3学习

响应式数据 const searchFormState reactive({})const searchFormRef ref()两者差不多&#xff0c;reactive(&#xff09;多用于复杂数据结构 ref()多用与简单数据结构 组件传值父传子 属性传值 父组件给子组件传值属性aa值为data :aa"data" 子组件接收数据方法 引…

常见面试题之HashMap

1. 二叉树 1.1 二叉树概述 二叉树&#xff0c;顾名思义&#xff0c;每个节点最多有两个“叉”&#xff0c;也就是两个子节点&#xff0c;分别是左子节点和右子节点。不过&#xff0c;二叉树并不要求每个节点都有两个子节点&#xff0c;有的节点只有左子节点&#xff0c;有的节…

前端基本功 用 React Hooks + Antd 实现一个 Todo-List

背景 使用 React Hooks 以及组件库 Antd 来实现一个可以 增删 标记是否完成 的 todo-list 思路 要实现一个 todo-list 首先想到用 useState 维护一个状态数组来保存当前 list &#xff0c;还要用一个状态维护添加框中的内容 const [todos, setTodos] useState(initialValu…

Excel之VLOOKUP()函数介绍

Excel之VLOOKUP()函数介绍 Excel的VLOOKUP函数语法&#xff1a; VLOOKUP(lookup_value, table_array, col_index_num, [range_lookup]) 参数说明&#xff1a; lookup_value&#xff1a;要查找的值或要比较的值。 table_array&#xff1a;包含要在其中进行查找的数据表的区…

解决打开excel时报错 “不能使用对象链接和嵌入”

问题截图 打开excel文件或者插入对象时&#xff0c;直接弹出不能使用对象链接和嵌入报错信息。 解决方法 按 winr 组合快捷键&#xff0c;打开运行&#xff0c;输入 dcomcnfg.exe 按回车确定 此时进入到组件服务管理界面&#xff0c;依次选择 组件服务-计算机-我的电脑-DOCM…

S3C2440点亮LED(裸机开发)

文章目录 前言一、环境介绍一、GPIO介绍二、点亮开发板的LED1.预备动作2.led代码 总结 前言 本期和大家主要分享的是使用S3C2440开发板点亮一个LED灯&#xff0c;可能大家拿到开发板之后做的第一件事情都是点灯&#xff0c;这是为什么呢&#xff1f;因为点灯这件事情不仅能够检…

Linux搭建node环境-MobaXterm+node+pm2安装

1.登录session 2.安装X11-forwarding 我也不知道这个有什么用&#xff0c;但是有个叉叉在那里有点难受&#xff0c;就把它解决了什么是X11-forwarding&#xff1f;怎么使用&#xff1f; yum install xorg-x11-xauth xorg-x11-fonts-* xorg-x11-font-utils xorg-x11-fonts-Ty…