记录一个咸鱼大学生三个月的奋进生活017
复习Java(学生信息管理系统05所有菜单功能操作的实现)
今天完成所有菜单功能的实现 (超多内容警告!) ,首先大家需要在之前的帖子中回顾一下动态挂靠菜单的功能:
复习Java第一个项目学生信息管理系统 04(权限管理和动态挂菜单功能) &python简单爬数据实例&Java面试题三次握手和四次挥手&生活【记录一个咸鱼大学生三个月的奋进生活】016
在动态挂靠菜单的时候给每个功能按钮都添加了一个监听器,去实现点击按钮切换操作页面的功能,而这个监听器是这样实现的:
实现MenuListener菜单功能按钮监听器
具体思路就是先获取点击菜单需要进行操作的页面也就是整个mainFrame,然后获取所有组件,再获取组件中的挂靠顺序的第一个也就是中间的空白区域命名为panelWelcome,然后通过获取点击的功能按钮的Id进行数据库查找functionClass也就是相关操作的具体页面实现类,再进行动态加载实现,这样看可能比较乱,按着这个思路看代码就好了。
package com.sm.framework.control.listener;
// 这是control层中的菜单监听器,为了点击菜单中的功能显示可以操作功能的页面
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JPanel;
import com.sm.framework.control.action.org.Action;
import com.sm.framework.model.dao.impl.MyMenuDAOImpl;
import com.sm.framework.model.entity.MyMenu;
import com.sm.framework.view.MainFrame;
public class MenuListener implements ActionListener {
// 继承ActionListener去监听事件,这是设置监听器去实现MainFrame的菜单功能点击事件
private MainFrame mainFrame = null; // 实例化MainFrame主页面在构造方法时会接收参数
private JPanel panelBody = null; // panelBody获得mainframe的ContentPane
private JPanel panelWelcome = null; // panelWelcome获得panelBody(原mainframe)的第二个存的页面,也就是中间的操作页面
private JPanel panelWork = null; // panelWork是中间进行操作的页面
public MenuListener() {
// TODO Auto-generated constructor stub
}
// 编写构造方法在MainFrame中添加监听事件
public MenuListener(MainFrame mainFrame) {
this.mainFrame = mainFrame;
// TODO Auto-generated constructor stub
}
// 事件处理,点击菜单显示左下方详细操作功能按钮区域,所以这属于在别的类实现,在自己类设实现类的监听器,里面调用getPanelTop方法
@Override
public void actionPerformed(ActionEvent e) {
this.panelBody = (JPanel)this.mainFrame.getContentPane(); // 将点击之后传入的mainFrame进行getContentPane然后强转为JPanel格式给当前类的panelBody
Component[] components1 = this.panelBody.getComponents(); // panelBody用getComponents获得添加的组件数组components1
this.panelWelcome = (JPanel)components1[1]; // components1[n]代表之前添加进panelBody(原mainFrame)的第n+1的组件,给当前类的panelWelcome
this.panelWelcome.removeAll(); // 这一步的目的是为了每次点击菜单都能将原来点击而显示的业务关闭,不让显示的业务都重叠在一起
this.panelWelcome.repaint(); // 这一步的目的是为了每次点击菜单都能将原来点击而显示的业务关闭,不让显示的业务都重叠在一起
this.panelWelcome.setLayout(new BorderLayout()); // 设置panelWelcome为BorderLayout
this.panelWork = new JPanel();
this.panelWelcome.add(this.panelWork, BorderLayout.CENTER); // 将panelWork添加设置为panelWelcome的center
String menuId = e.getActionCommand(); // 获得当前点击的按钮的functionId,因为之前每个详细操作按钮的ActionCommand都被设置为了他们各自的FunctionId
MyMenu menuTemp = new MyMenuDAOImpl().findByMenuId(menuId); // 调用MisFunctionDAOImpl中的findByFunctionId方法将刚获得的点击的functionId传入方法
String functionName = menuTemp.getfunctionClass(); // 数据库中FunctionClass里存的是点击详细操作按钮之后的显示右边页面的实现类的地址,赋值给functionName
try {
// 动态加载的语句(重要!背!)
Class functionClass = Class.forName(functionName); // 格式:Class 对象名 = Class.forName(类的地址以及类);
Action action = (Action)functionClass.newInstance(); // newInstance()方法就是实例化刚forname的对象functionClass,functionClass这里存的都是接口的实现类所以要强转成action
action.execute(this.panelWork); // 然后调用action接口中的execute的方法传入panelWork实现类操作后显示,这个方法会根据每次点击的按钮不同,实例化不同的的FunctionClass(也就是不同的接口实现类,例如:如果点击的是“增加机构类别”那么实例化的是OrgTypeCreateAction实现类,显示的就是OrgTypeCreateAction的操作页面)
this.mainFrame.setVisible(true); // 刷新语句
} catch (ClassNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (InstantiationException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IllegalAccessException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
this.mainFrame.setVisible(true); // 当swing添加新的组件之后需要进行刷新操作才会显示,setVisible(true)就是刷新语句
}
}
再在MainFrame主界面动态挂靠菜单功能方法下将每个功能按钮都添加MenuListener监听器
// createMenu动态挂靠菜单方法
private void createMenu() {
MyMenuDAO menuDAO = new MyMenuDAOImpl(); // 实例化MyMenuDAO,里面有一个findBySql方法,通过sql语句进行查询存入对象之后返回
String sql1 = "select * from myMenu where menuId like '__' and menuId in (select menuId from auth where roleId = '"+ misUser.getRoleId() +"')"; // 这句话意思是查找menuId里所有为两位数的信息
List<MyMenu> list1 = menuDAO.findBySql(sql1); // 查找到的数据存到list1集合里
for (MyMenu myMenu1 : list1) {
// 遍历list1
JMenu tempMenu = new JMenu(); // 实例化JMenu,将查到的信息存到tempMenu菜单中,这是有复选的主菜单
tempMenu.setActionCommand(myMenu1.getMenuId()); // setActionCommand方法设置事件名为该功能在数据库中的Id
tempMenu.setText(myMenu1.getMenuName()); // setText方法设置菜单名
String sql2 = "select * from myMenu where menuId like '" + myMenu1.getMenuId() + "__' and menuId in (select menuId from auth where roleId = '"+ misUser.getRoleId() +"')"; // 嵌套循环查找该循环下的id+两位数的信息,例:1011,1012...,挂在该下拉菜单中,成不可再复选的菜单
List<MyMenu> list2 = menuDAO.findBySql(sql2); // 调用findbysql方法查找到的数据存到list2集合里
for (MyMenu myMenu2 : list2) {
// 遍历list2
JMenuItem tempItem = new JMenuItem(); // 实例化tempItem这是一个JMenuItem,没有复选的菜单
tempItem.setActionCommand(myMenu2.getMenuId()); // setActionCommand方法设置事件名为该功能在数据库中的Id,在之后的点击功能显示详细操作MenuListener中会用到
tempItem.setText(myMenu2.getMenuName());
// 也就是下面这一行!!!
// 也就是下面这一行!!!
// 也就是下面这一行!!!
tempItem.addActionListener(new MenuListener(this)); // 给所有的菜单选项添加监听事件,因为是在MenuListener中实现的所以要实例化MenuListener设监听器
tempMenu.add(tempItem); // 将刚设好的无复选的菜单添加进tempMenu,就是有复选的主菜单,注意这还是在循环嵌套中,所以会将10或20等开头的都放在一起
}
this.menuBar.add(tempMenu); // 将刚添加好的主菜单添加进menuBar
}
}
编写MenuListener监听器中实现动态加载的Action接口
实现这个接口的类再实现该接口中的execute方法实现动态加载操作界面效果
package com.sm.framework.control.action.org;
// 这个接口是为了实现在MenuListener中点击操作菜单显示具体操作的页面,是control层下的action代码
import javax.swing.JPanel;
public interface Action {
public void execute(JPanel panelWork); // execute方法是实现点击详细操作显示的页面的功能,然后根据点击的按钮不同在FunctionListener中实例化不同的的FunctionClass
}
接下来就是重头戏,每个功能的Action具体操作功能页面的编写
班级管理功能
新增班级CreateClassAction
package com.sm.framework.control.action.org;
// 这是实现Action中的execute方法的CreateClassAction实现类,该类的名字和地址需要跟数据库myMenu中的FunctionClass中对应功能存的数据一样
// 这个实现类对应的是点击“新增班级”操作按钮的显示页面功能
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import com.sm.framework.model.dao.impl.classNameDAO;
import com.sm.framework.model.dao.impl.classNameDAOImpl;
import com.sm.framework.model.entity.className;
import com.sm.framework.view.LoginFrame;
public class CreateClassAction implements Action,ActionListener {
private JPanel panelBody1 = null;
private JPanel panelButton = null;
private JLabel ClassId = null; // 班级文字
private JTextField ClassIn = null; // 班级输入文字条
private JButton buttonSubmit = null; // 提交按钮
private JButton buttonReset = null; // 清空按钮
// clear方法是点击重置按钮之后进行的步骤,将填写的信息清空
private void clear() {
this.ClassIn.setText("");
}
private void init() {
this.panelBody1.setLayout(new GridBagLayout());
GridBagConstraints constraints = new GridBagConstraints();
constraints.anchor = GridBagConstraints.EAST;
this.ClassId = new JLabel("班级名:");
constraints.gridx = 0;
constraints.gridy = 0;
this.panelBody1.add(this.ClassId, constraints);
this.ClassIn = new JTextField(40);
constraints.gridx = 1;
constraints.gridy = 0;
this.panelBody1.add(this.ClassIn, constraints);
this.panelButton = new JPanel();
this.buttonSubmit = new JButton("新增");
this.buttonSubmit.addActionListener(this);
this.buttonReset = new JButton("重置");
this.buttonReset.addActionListener(this);
this.panelButton.setOpaque(false);
this.panelButton.add(this.buttonSubmit);
this.panelButton.add(this.buttonReset);
constraints.gridx = 1;
constraints.gridy = 1;
this.panelBody1.add(this.panelButton, constraints);
}
// 构造方法的编写,会直接将该页面显示在传入的panelWork页面
@Override
public void execute(JPanel panelWork) {
this.panelBody1 = panelWork;
this.init();
}
// 事件处理
@Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == this.buttonReset) {
this.clear();
}
else if(e.getSource() == this.buttonSubmit) {
String id = this.ClassIn.getText(); // 获取输入的id
if(id == null || (id.trim()).length() <= 0 ) {
//判空
JOptionPane.showMessageDialog(null, "请输入班级名");
return;
}
className classname = new className(); // 实例化className用里面的setStudent_class方法
classname.setStudent_class(this.ClassIn.getText());
classNameDAO dao = new classNameDAOImpl(); // 实例化classNameDAO接口,用里面的addClass新增方法
if(dao.addClass(classname)) {
JOptionPane.showMessageDialog(null, "新增班级成功");
this.clear();
}
}
}
}
界面成果:
package com.sm.framework.control.action.org;
// 这是实现Action中的execute方法的DeleteClassAction实现类,该类的名字和地址需要跟数据库misFunction中的FunctionClass中对应功能存的数据一样
// 这个实现类对应的是点击“删除班级”操作按钮的显示页面功能
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import com.sm.framework.model.dao.impl.classNameDAO;
import com.sm.framework.model.dao.impl.classNameDAOImpl;
import com.sm.framework.model.entity.className;
public class DeleteClassAction implements Action, ActionListener {
private JPanel panelWork = null; // 这是供所有操作进行的panelWork,Action接口实现的execute方法会调用这个panelWork
private JPanel panelButton = null; // 按钮块
private JTable table = null; // 表格块
private DefaultTableModel tablemodel = null; // DefaultTableModel实例化tablemodel,才能放入数据
private JScrollPane scrollPane = null; // 实例化JScrollPane才能显示表头
private String[] title = {
"班级名"}; // 表头数组
private String[][] data = null; // 表格数据数组
private JButton buttonDelete = null; // 删除按钮
private JButton buttonRefresh = null; // 刷新按钮
// 刷新方法
private void refresh() {
this.table.removeAll(); // 清空表格内容
this.table.repaint();
this.tablemodel = new DefaultTableModel(this.getData(new className()), this.title); // 将表头和数据实例化给tablemodel,调用getData方法因为传入的OrgType没有值,根据万能查找的方法就是全部数据都查到
this.table.setModel(this.tablemodel); // 表格用setModel方法设置刚的tablemodel
}
// getData方法,传入orgType返回存放数据的数组
private String[][] getData(className classname) {
String[][] data = null;
classNameDAO dao = new classNameDAOImpl();
List<className> list = dao.findByLike(classname); // 调用的是万能查找的方法
data = new String[list.size()][1]; // 给存放数据的数组定义长度,查找到的数据集合长度和固定的数据种类1
for(int i = 0; i < list.size(); i++) {
data[i][0] = list.get(i).getStudent_class();
}
return data;
}
// 整体界面,要将标签组实例化然后添加刚才的两个界面的
private void init() {
// this.panelWork.removeAll();
// this.panelWork.repaint();
this.panelWork.setLayout(new BorderLayout());
// this.panelWork = new JPanel(new BorderLayout()); // 实例化panelModfy并设置BorderLayout
this.data = this.getData(new className()); // 调用getData方法传入className()实现全查
this.tablemodel = new DefaultTableModel(this.data, this.title); // 然后实例化表格数据DefaultTableModel
this.table = new JTable(this.tablemodel); // 然后实例化表格
this.scrollPane = new JScrollPane(this.table); // 实例化scrollPane将table传入不然会看不到表头
this.panelWork.add(this.scrollPane, BorderLayout.CENTER); // 然后将scrollPane添加进panelModfy的border中间
this.panelButton = new JPanel();
this.buttonDelete = new JButton("删除");
this.buttonDelete.addActionListener(this);
this.buttonRefresh = new JButton("刷新");
this.buttonRefresh.addActionListener(this);
this.panelButton.add(this.buttonDelete);
this.panelButton.add(this.buttonRefresh);
this.panelWork.add(this.panelButton, BorderLayout.SOUTH);
}
// 实现接口Action中的execute方法,传入供操作的panelWork
@Override
public void execute(JPanel panelWork) {
this.panelWork = panelWork;
this.init();
}
// 事件监听代码
@Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == this.buttonRefresh) {
// 点击刷新按钮,执行表格刷新方法
this.refresh();
}
else if(e.getSource() == this.buttonDelete) {
// 点击删除按钮
int n = this.table.getSelectedRowCount(); // 调用表格中的getSelectedRowCount方法,获得选中的行数赋值给n
if(n != 1) {
JOptionPane.showMessageDialog(null, "请选择一条数据!");
return;
}
// 进行删除操作
String classname = this.tablemodel.getValueAt(this.table.getSelectedRow(), 0).toString(); // 这句代码意思是获得点击行的第一个数据也就是id强转为字符串
classNameDAO dao = new classNameDAOImpl(); // 实例化OrgTypeDAO调用里面的remove删除方法将orgTypeId传入
if(dao.removeClass(classname)) {
JOptionPane.showMessageDialog(null, "删除成功");
this.refresh(); // 再调用刷新方法
}
}
}
}
界面成果:
学生信息管理功能
新增学生信息CreateStuAction
package com.sm.framework.control.action.org;
// 这是实现Action中的execute方法的CreateStuAction实现类,该类的名字和地址需要跟数据库myMenu中的FunctionClass中对应功能存的数据一样
// 这个实现类对应的是点击“新增学生信息”操作按钮的显示页面功能
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import com.sm.framework.model.dao.impl.studentsDAO;
import com.sm.framework.model.dao.impl.studentsDAOImpl;
import com.sm.framework.model.entity.students;
import com.sm.framework.view.LoginFrame;
public class CreateStuAction implements Action,ActionListener {
private JPanel panelBody1 = null;
private JScrollPane scrollPaneDisc = null; // 文本框
private JPanel panelButton = null;
private JLabel StuId = null; // 学生学号
private JTextField StuIdIn = null; // 学生学号输入文字条
private JLabel StuName = null; // 学生姓名
private JTextField StuNameIn = null; // 学生姓名输入文字条
private JLabel StuYuan = null; // 学生学院
private JTextField StuYuanIn = null; // 学生学院文字条
private JLabel StuClass = null; // 学生班级
private JTextField StuClassIn = null; // 学生班级输入文字条
private JLabel StuRoom = null; // 学生宿舍
private JTextField StuRoomIn = null; // 学生宿舍输入文字条
private JLabel StuSex = null; // 学生性别
private JTextField StuSexIn = null; // 学生性别输入文字条
private JLabel StuSheng = null; // 学生省份
private JTextField StuShengIn = null; // 学生省份输入文字条
private JLabel StuShi = null; // 学生城市
private JTextField StuShiIn = null; // 学生城市输入文字条
private JLabel StuPhone = null; // 学生电话
private JTextField StuPhoneIn = null; // 学生电话输入文字条
private JLabel StuHome = null; // 学生住址
private JTextArea StuHomeIn = null; // 学生住址输入文字条
private JButton buttonSubmit = null; // 提交按钮
private JButton buttonReset = null; // 清空按钮
// clear方法是点击重置按钮之后进行的步骤,将填写的信息清空
private void clear() {
this.StuIdIn.setText("");
this.StuNameIn.setText("");
this.StuYuanIn.setText("");
this.StuClassIn.setText("");
this.StuRoomIn.setText("");
this.StuSexIn.setText("");
this.StuShengIn.setText("");
this.StuShiIn.setText("");
this.StuPhoneIn.setText("");
this.StuHomeIn.