swing实现MVC模式实现增删改查+排序系统3.0

简介: swing实现MVC模式实现增删改查+排序系统3.0

swing实现MVC模式实现增删改查+排序系统3.0

 

MVC模式应用

 

顾客类(面向对象)、

 

顾客窗体类(样式、视图层)、

 

数据库类(提供测试数据)、

 

表格模式类(数据层、核心逻辑类,修改表格模式、处理业务)

 

ps:这次整个项目代码的注解的分析更加详细易懂噢!!!

 

1.顾客类:属性:姓名、年龄、卡号、电话等,get、set方法

2.顾客窗体类

样式:卡号标签、电话标签、两个文本框、一个搜索按钮、 一张表格:

18.png

 

 

3.自己暂时定义一个数据库类:存放List的数据,static静态块初始化,List集合的元素。用来作为提供数据测试使用的。

4.由于DefaultTableModel默认表格模式,存放的数据是Vector或者二维数组的数据,而我们的数据是List类型,所以,我们自定了一个DefaultTableModel 的兄弟类(继承父类呀、实现接口呀与DefaultTableModel一样)--表格模式类:

5表格模式类:兼容我们的数据类型List,所以定义了List<顾客类>的集合。//顾客类的List集合,通过构造方法,我们要求传入的是一个List的集合。

 

华丽的分割线~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~(至此四个类已经全部出现)

 

1.看一下:表格模式类:兼容我们的数据类型List,所以定义了List<顾客类>的集合。//顾客类的List集合,通过构造方法,我们要求传入的是一个List的集合。( 顾客数据层,自己实现表格模式,因为DefauleTableModel 处理的数据类型时Vector,而我们想要实现处理List型数据

19.png

2.  表格模式类实现的三个方法+后边我们想要的一些方法:先重点看一下getValueAt(int rowIndex, int columIndex)方法获取值的实现:

2-1.先获取到行数据(某个对象的数据):Customer cust = custList.get(rowIndex);      (custLIst就是替换DefauleTableMode,我们自己的表格模式类,我们用来存放数据的List集合)

2-2.在获取到列数据时出现问题:

发现:想要取出的对象属性没有先后之分,可能会导致我们的属性位置放错了,没给我们设置一种模式让我们取

②发现:(某个对象的某个属性--与当前的参数列下标columnIndex要没有联系)

解决

考虑如果传入当前的列下标的话,我们可以获取到对应表头名称;

通过列名挂钩到对象的属性--借助桥梁(Map集合<列名,属性名>)(通过反射实现);    

通过map的列名key获取map的属性名(value);

获取到顾客对象的属性;(反射应用啦):    field = Customer.class.getDeclaredField(fileName);  (fields是“反射变量”, fileName 是map的属性名,通过map挂钩到对象属性啦)

通过属性反射,获取到该属性是哪一个对象的属性:Object fieldValue = field.get(cust);    (cust 是2-1,获取的某个对象的数据)

 

20.png(2-1)

 

21.png(2-2的问题)

 

22.png(2-2解决:Map集合<列名,属性名>)

 

 

getValueAt(int rowIndex, int columIndex)方法代码:

 

//设置表格的单元格的值
    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        if(custList == null)    return null;
        //先获取到行数据(某个对象的数据)
        Customer cust = custList.get(rowIndex);
        //获取到列数据(某个对象的某个属性--与当前的列下标要有联系)
//        Object custProperty = cust.get
        //当前的列下标传入的话,可以获取到对应表头名称
//        String columnName = tableHeaderName.get(columnIndex);
        String columnName = tableHeaderName[columnIndex];
        //通过列名挂钩到对象的属性--借助桥梁(Map集合<列名,属性名>)(通过反射实现)
        //通过列名key获取属性名(value)
        String fileName = map.get(columnName);
        Field field = null;
        try {
            //获取到顾客对象的属性
            field = Customer.class.getDeclaredField(fileName);
            //设置访问权限为true
            field.setAccessible(true);
            //通过属性反射,获取到该属性是哪一个对象的属性
            Object fieldValue = field.get(cust);
            //设置访问权限为false
            field.setAccessible(false);
            return fieldValue;
        } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }

 

3.    其实在第2点实现前,我们做完了大概表格模式后,先测试一下,使用我们自定的表格模式,拿我们自定义的数据库类数据做测试。不过样式:

23.png

(样子没那么完美,列名是A,B,C,D)

 

解决:列名是A,B,C,D不完美:重写getColumnName(int column)方法。改为返回表头的名称:

24.png

 

 

 

 

 

华丽的分割线~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~(至此,表格的模式实现了我们想要的啦,接下来我们有业务需求啦)

业务分析请看:放到最后啦

 

 

整个项目的全部代码:

顾客类(面向对象)

package com.xuetang9.kenny.MVCDemo;
/**
 * 顾客类
 * @author Huangyujun
 *
 */
public class Customer implements Comparable<Customer>{
    private String cardId;        //卡号
    private String telPhone;    //电话
    private String name;        //姓名
    private int age;            //年龄
    public Customer() { };
    public Customer(String cardId, String name, String telPhone, int age) {
        super();
        this.cardId = cardId;
        this.telPhone = telPhone;
        this.name = name;
        this.age = age;
    }
    @Override
    public int compareTo(Customer o) {
        return this.cardId.compareTo(o.cardId);
    }    
    public String getCardId() {
        return cardId;
    }
    public void setCardId(String cardId) {
        this.cardId = cardId;
    }
    public String getTelPhone() {
        return telPhone;
    }
    public void setTelPhone(String telPhone) {
        this.telPhone = telPhone;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

 

顾客窗体类(样式、视图层)

package com.xuetang9.kenny.MVCDemo;
/**
 * 顾客视图层
 * @author Huangyujun
 *
 */
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
public class CustomerView extends JFrame{
    //内容面板
    JPanel searchPane = new JPanel();
    //标签
    JLabel lblCard = new JLabel("卡号:");
    JLabel lblTel = new JLabel("电话:");
    //文本框
    JTextField txtCard = new JTextField();
    JTextField txtTel = new JTextField();
    //搜索按钮
    JButton searchButton = new JButton("搜索");
    //排序按钮
    JButton sortButton = new JButton("排序");
    //表格
    JTable table = new JTable();
    //增加按钮
    JButton addButton = new JButton("添加");
    //右键弹出菜单
    JPopupMenu popMenu = new JPopupMenu();
    //删除菜单项
    JMenuItem delMenuItem = new JMenuItem("删除顾客");
    //修改菜单项
    JMenuItem modifyMenuItem = new JMenuItem("修改顾客");
    //实例化CustomerModel,List集合是来自数据库的
    CustomerModel customerModel = new CustomerModel(MyDataBase.custList);
    public CustomerView() {
        //设置标题
        setTitle("顾客管理系统");
        //设置退出模式
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        //设置大小
        setSize(800, 600);
        //居中
        setLocationRelativeTo(null);
        //封装其余部分的初始话工作  
        initComponents();
        //事件
        initEvent();
    }
    private void initComponents() {
        //设置文本框大小
        txtCard.setPreferredSize(new Dimension(160, 30));
        txtTel.setPreferredSize(new Dimension(160, 30));
        //面板添加标签、文本框、搜索按钮、表格
        searchPane.add(lblCard);
        searchPane.add(txtCard);
        searchPane.add(lblTel);
        searchPane.add(txtTel);
        searchPane.add(searchButton);
        searchPane.add(sortButton);
//        searchPane.add(table);
        //菜单添加删除菜单项
        popMenu.add(delMenuItem);
        //菜单添加修改菜单项
        popMenu.add(modifyMenuItem);
        //表格添加右键菜单
        table.add(popMenu);
        //设置表格模型
        table.setModel(customerModel);
        //内容面板添加搜索面板(布局面板)
        getContentPane().add(searchPane, BorderLayout.NORTH);
        getContentPane().add(addButton, BorderLayout.SOUTH);
        //添加表格到内容面板
        getContentPane().add(new JScrollPane(table), BorderLayout.CENTER);
    }
    private void initEvent() {
        //为添加按钮添加事件
        addButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //业务的实现都是在数据层(逻辑层)--调用逻辑层的方法即可
                Customer cust = new Customer("007", "汉堡可乐", "11122233344", 20);
                CustomerView.this.customerModel.addCustomer(cust);
            }
        });
        //为表格添加右键菜单的事件
        table.addMouseListener(new MouseAdapter() {
             public void mouseClicked(MouseEvent e) {
                 if(e.getButton() == MouseEvent.BUTTON3) {    //右键鼠标
                     popMenu.show(table, e.getX(), e.getY());
                 }
             }
        });
        //(删除菜单项)添加事件
        delMenuItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //先获取单元格所处在表格的行
                int delRow = table.getSelectedRow();
                //通过行获取到对象的卡号,调用数据层的 getValueAt(int rowIndex, int columnIndex)方法
                String cardId = (String) CustomerView.this.customerModel.getValueAt(delRow, 0);
                //调用数据层的删除对象方法
                CustomerView.this.customerModel.delCustomer(cardId);
            }
        });
        //(修改菜单项)添加事件
        modifyMenuItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                Customer cust = new Customer("000", "炸鸡炸鸡", "11122266677", 00);
                //先获取单元格所处在表格的行
                int modifyRow = table.getSelectedRow();
                //调用数据层的修改对象方法
                CustomerView.this.customerModel.modifyCustomer(cust, modifyRow);
            }
        });
        //搜索按钮添加上事件
        searchButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //恢复数据
                CustomerView.this.customerModel. recover();
                //获取文本框的文本内容
                String strContent = txtCard.getText();
                if("".equals(strContent))    return;
                //把文本内容传递给数据层处理
                //调用数据层的查找对象方法
                CustomerView.this.customerModel.searchByTxtCard(strContent);
            }
        });
        sortButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //默认升序
                CustomerView.this.customerModel.sortByCardId();    
            }
        });
    }
    public static void main(String[] args) {
        new CustomerView().setVisible(true);
    }
}

数据库类(提供测试数据)

package com.xuetang9.kenny.MVCDemo;
import java.util.ArrayList;
import java.util.List;
/**
 * 数据库类
 * @author Huangyujun
 *
 */
public class MyDataBase {
    public static List<Customer> custList = null;
    static {
        custList = new ArrayList<Customer>();
        Customer cust1 = new Customer("001", "小盼", "13421127777", 18);
        Customer cust2 = new Customer("002", "小金", "13531121111", 18);
        Customer cust3 = new Customer("003", "小花", "13421126666", 18);
        custList.add(cust1);
        custList.add(cust2);
        custList.add(cust3);
    }
}


表格模式类(数据层、核心逻辑类,修改表格模式、处理业务)

package com.xuetang9.kenny.MVCDemo;
/**
 * 顾客数据层,自己实现表格模式,因为DefauleTableModel 处理的数据类型时Vector,而我们想要实现处理List型数据
 * @author Huangyujun
 *
 */
import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.table.AbstractTableModel;
public class CustomerModel extends AbstractTableModel implements Serializable{
    List<Customer> custList = null;
//    List<String> tableHeaderName = null;
    String[] tableHeaderName = null;
    Map<String, String> map = null;
    //构造方法,要传入List集合作为参数
    public CustomerModel(List<Customer> custList) {
        this.custList = custList;
        //表头名称
//        tableHeaderName = new ArrayList<String>();
//        tableHeaderName.addAll(Arrays.asList("卡号", "姓名", "电话", "年龄"));
        tableHeaderName = new String[] {"卡号", "姓名", "电话", "年龄"};
        map = new HashMap();
        map.put("卡号", "cardId");
        map.put("姓名", "name");
        map.put("电话", "telPhone");
        map.put("年龄", "age");
    }
    //实现业务:增删改查
    /**
     * 1.增加对象
     * @param cust
     */
    public void addCustomer(Customer cust) {
        //内部List添加顾客对象
        custList.add(cust);
        //更新一下数据
        fireTableDataChanged();
    }
    /**
     * 2.删除对象--通过卡号删除对象
     * @param cardId
     */
    public void delCustomer(String cardId) {
        Customer delCust = searchByCardId(cardId);
        custList.remove(delCust);
        //更新一下数据
        fireTableDataChanged();
    }
    /**
     * 查找--根据视图层传递的文本内容查找
     * @param strContent
     */
    public void searchByTxtCard(String strContent) {
        //定义一个存放查找到的结果的List,用来替换掉原来的List
        List<Customer> resultList = new ArrayList<Customer>();
        for(Customer customer : custList) {
            if(strContent.equals(customer.getCardId())) {
                resultList.add(customer);
            }
        }
        custList = resultList;
        //更新一下数据
        fireTableDataChanged();
    }
    /**
     * 根据传入的行号和传入的顾客对象,修改对应的行号的对象为新对象
     * @param cust
     * @param modifyRow
     */
    public void modifyCustomer(Customer cust, int modifyRow) {
        //更改List中的对象
        custList.set(modifyRow, cust);
        //更新一下数据
        fireTableDataChanged();
    }
    /**
     * 根据卡号排序,默认升序
     */
    public void sortByCardId() {
        //使用Collections工具类排序
//        Collections.sort(custList, new Comparator<Customer>() {
//            @Override
//            public int compare(Customer o1, Customer o2) {
//                return o1.getCardId().compareTo(o2.getCardId());
//            }        
//        });
        Collections.sort(custList);
        //更新一下数据
        fireTableDataChanged();
    }
    //复位数据--恢复数据
    public void recover() {
        custList = MyDataBase.custList;
        //更新一下数据
        fireTableDataChanged();
    }
    /**
     * 根据卡号查找对象,找到并返回对象
     * @param cardId
     * @return
     */
    public Customer searchByCardId(String cardId) {
        Customer cust = null;
        for(Customer customer : custList) {
            if(cardId.equals(customer.getCardId())) {
                cust = customer;
                break;
            }
        }
        return cust;
    }
    @Override
    //返回表格的行数,即List的对象的数量
    public int getRowCount() {
        if(custList == null)    return 0;
        return custList.size();
    }
    //重写表头名称
    @Override
    public String getColumnName(int column) {
        return tableHeaderName[column];
    }
    @Override
    public int getColumnCount() {
//        return tableHeaderName.size();
        return tableHeaderName.length;
    }
    //设置表格的单元格的值
    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        if(custList == null)    return null;
        //先获取到行数据(某个对象的数据)
        Customer cust = custList.get(rowIndex);
        //获取到列数据(某个对象的某个属性--与当前的列下标要有联系)
//        Object custProperty = cust.get
        //当前的列下标传入的话,可以获取到对应表头名称
//        String columnName = tableHeaderName.get(columnIndex);
        String columnName = tableHeaderName[columnIndex];
        //通过列名挂钩到对象的属性--借助桥梁(Map集合<列名,属性名>)(通过反射实现)
        //通过列名key获取属性名(value)
        String fileName = map.get(columnName);
        Field field = null;
        try {
            //获取到顾客对象的属性
            field = Customer.class.getDeclaredField(fileName);
            //设置访问权限为true
            field.setAccessible(true);
            //通过属性反射,获取到该属性是哪一个对象的属性
            Object fieldValue = field.get(cust);
            //设置访问权限为false
            field.setAccessible(false);
            return fieldValue;
        } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }
}


 

业务分析请看


1.   添加对象:

1-1.    逻辑层:List集合添加完对象,表视图还不知道数据更新了,需要通过fireTableDateChanged();通知一下。

25.png

 

 

1-2.视图层搞一个按钮:

26.png

 

 

按钮添加上事件: 按钮.addActionListener(),事件里在表格模式添加上对象即可,不用操作表格,操作的是表格模式。

27.png

 

 

总结一下:增删改查操作,都不用在界面层操作,都是操作数据层(逻辑层),然后添加上对应操作的控件后,加事件,事件里只需要操作表格模型(逻辑层)

2.   删除对象:

2-1.视图层:通过右键菜单删除选中对象

实例化右键菜单,和菜单项,然后右键菜单里添加菜单项。

2-2.表格控件添加右键鼠标事件:表格.addMouseListener(鼠标监听适配器)方法,实现鼠标点击方法,效果:在表格上右键鼠标,弹出删除对象提醒。

28.png

 

 

2-3.要删除的菜单项添加事件:在视图层获取到要删除的对象的卡号(卡号是主键噢),再把视图层要删除的卡号传递给数据层(逻辑层,表格模式),在数据层找到对应要删除的对象,然后remove( );最后fireTableDataChanged();通知一下数据更新啦!

29.png

 

30.png

 

bug:新添加的对象,不能删除,why?(ps:项目代码我改了这个bug啦)

 

3.  查找:

3-1.视图层:查找按钮添加事件监听:通过卡号文本框的文本,判断要查找的内容。

31.png

 

 

3-2逻辑层:

32.png

 

 

bug:就是查找一次后,第二次查找不灵光了,数据变成了第一次查找后的结果。

解决:(复位,恢复数据层数据)

33.png

 

 

4.  改功能

5.排序功能:

 

目录
相关文章
|
4月前
|
设计模式 前端开发 JavaScript
浅谈MVC、MVP、MVVM框架模式
浅谈MVC、MVP、MVVM框架模式
33 0
|
4月前
|
XML 前端开发 测试技术
Android基础知识:解释Android的MVC和MVP模式。
Android基础知识:解释Android的MVC和MVP模式。
35 0
|
5月前
|
设计模式 前端开发 Java
Java设计模式【二十六】:MVC模式
Java设计模式【二十六】:MVC模式
36 0
|
4月前
|
设计模式 前端开发 Java
javaweb实训第四天上午——员工管理系统-JavaBean&EL&JSTL&MVC思想(3)
5.2.怎么使用JSTL标签库 第一步:导入相关的jar包
78 0
|
4月前
|
前端开发 Java
javaweb实训第四天上午——员工管理系统-JavaBean&EL&JSTL&MVC思想(1)
1.课程介绍 项目需求分析; (了解) JavaBean; (掌握) El表达式; (掌握) JSTL标签; (掌握) MVC思想; (掌握)
50 0
|
2月前
|
前端开发 数据安全/隐私保护
什么是mvvm,mvp、mvc和mvvm模式有什么区别?
什么是mvvm,mvp、mvc和mvvm模式有什么区别?
41 0
|
16天前
|
安全 数据管理 中间件
云LIS系统源码JavaScript+B/S架构MVC+SQLSugar医院版检验科云LIS系统源码 可提供演示
检验科云LIS系统源码是医疗机构信息化发展的重要趋势。通过云计算技术实现数据的集中管理和共享可以提高数据利用效率和安全性;通过高效灵活的系统设计和可扩展性可以满足不同医疗机构的需求;通过移动性和智能化可以提高医疗服务的精准度和效率;通过集成性可以实现医疗服务的协同性和效率。因此,多医院版检验科云LIS系统源码将成为未来医疗机构信息化发展的重要方向之一。
26 2
|
4月前
|
前端开发 Java
javaweb实训第四天上午——员工管理系统-JavaBean&EL&JSTL&MVC思想(2)
4.3.EL表达式访问四大作用域的绑定值 搭建环境:分别从各大作用域里面取值
56 0
|
1天前
|
设计模式 存储 前端开发
MVC(模型-视图-控制器)是一种在Web应用程序开发中广泛使用的软件设计模式
【5月更文挑战第12天】MVC模式是Web应用开发中的常见设计模式,将逻辑、数据和界面分离,提升代码可维护性和重用性。模型处理数据逻辑,视图展示数据,控制器协调用户输入与模型视图交互。优点包括代码分离、易维护、可扩展和组件重用,促进高效灵活的开发。
7 2
|
11天前
|
设计模式 前端开发 Java
19:Web开发模式与MVC设计模式-Java Web
19:Web开发模式与MVC设计模式-Java Web
22 4