java 图形界面 mvc模式控制
使用模型-视图-控件结构来开发GUI程序。
下面的程序演示了MVC模式开发的java程序。
其中CircleModel为模型,包含了圆的半径,是否填充,等属性。
CircleView为视图,显示这个圆。
CircleController为控制器,控制圆的大小,以及是否被填充。
模型:
1 package circleMVC; 2 3 import java.awt.Color; 4 import java.awt.event.*; 5 import java.util.*; 6 7 public class CircleModel { 8 //圆半径 9 private double radius = 20; 10 11 //是否填充 12 private boolean filled; 13 14 //颜色 15 private java.awt.Color color; 16 17 private ArrayList<ActionListener> actionListenerList; 18 19 public double getRadius() { 20 return radius; 21 } 22 23 public void setRadius(double radius) { 24 this.radius = radius; 25 processEvent(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "radius"));//当属性值改变是通知监听器 26 } 27 28 public boolean isFilled() { 29 return filled; 30 } 31 32 public void setFilled(boolean filled) { 33 this.filled = filled; 34 processEvent(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "filled"));//当属性值改变是通知监听器 35 } 36 37 38 39 public java.awt.Color getColor() { 40 return color; 41 } 42 43 public void setColor(java.awt.Color color) { 44 this.color = color; 45 processEvent(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "color"));//当属性值改变是通知监听器 46 } 47 48 public synchronized void addActionListener(ActionListener l){ 49 if(actionListenerList == null){ 50 actionListenerList = new ArrayList<ActionListener>(); 51 } 52 actionListenerList.add(l); 53 } 54 55 public synchronized void removeActionListener(ActionListener l){ 56 if(actionListenerList != null && actionListenerList.contains(l)){ 57 actionListenerList.remove(l); 58 } 59 } 60 61 private void processEvent(ActionEvent e){ 62 ArrayList list; 63 64 synchronized(this){ 65 if(actionListenerList == null) return; 66 list = (ArrayList)actionListenerList.clone(); 67 } 68 for(int i = 0; i < list.size(); i++){ 69 ActionListener listener = (ActionListener)list.get(i); 70 listener.actionPerformed(e); 71 } 72 } 73 }
视图:
1 package circleMVC; 2 3 import java.awt.*; 4 import java.awt.event.*; 5 import javax.swing.*; 6 public class CircleView extends JPanel implements ActionListener{ 7 private CircleModel model; 8 9 public void actionPerformed(ActionEvent actionEvent){ 10 repaint(); 11 } 12 13 //设置一个model 14 public void setModel(CircleModel newModel) { 15 model = newModel; 16 17 if(model != null){ 18 //给model增加啊监听器 19 model.addActionListener(this); 20 } 21 22 repaint(); 23 } 24 25 public CircleModel getModel(){ 26 return model; 27 } 28 29 public void paintComponent(Graphics g){ 30 super.paintComponent(g); 31 32 if(model == null) return; 33 34 g.setColor(model.getColor()); 35 36 int xCenter = getWidth() / 2; 37 int yCenter = getHeight() / 2; 38 int radius = (int)model.getRadius(); 39 40 if(model.isFilled()) { 41 g.fillOval(xCenter - radius, yCenter - radius, 2 * radius, 2 * radius); 42 }else{ 43 g.drawOval(xCenter - radius, yCenter - radius, 2 * radius, 2 * radius); 44 } 45 } 46 }
控制器
1 package circleMVC; 2 3 import java.awt.*; 4 import java.awt.event.*; 5 import javax.swing.*; 6 public class CircleController extends JPanel{ 7 private CircleModel model; 8 private JTextField jtfRadius = new JTextField(); 9 @SuppressWarnings("unchecked") 10 private JComboBox jcboFilled = new JComboBox(new Boolean[]{ 11 new Boolean(false), new Boolean(true) 12 }); 13 private JRadioButton jrbRed, jrbGreen, jrbBlue; 14 15 //创建一个新的CircleController 16 public CircleController(){ 17 JPanel panel1 = new JPanel(); 18 panel1.setLayout(new GridLayout(2,1)); 19 panel1.add(new JLabel("Radius")); 20 panel1.add(new JLabel("Filled")); 21 22 // 23 JPanel panel2 = new JPanel(); 24 panel2.setLayout(new GridLayout(2,1)); 25 panel2.add(jtfRadius); 26 panel2.add(jcboFilled); 27 28 JPanel panel3 = new JPanel(); 29 panel3.setLayout(new GridLayout(1, 3)); 30 panel3.add(jrbRed = new JRadioButton("Red")); 31 panel3.add(jrbGreen = new JRadioButton("Green")); 32 panel3.add(jrbBlue = new JRadioButton("Blue")); 33 34 35 36 setLayout(new BorderLayout()); 37 add(panel1, BorderLayout.WEST); 38 add(panel2, BorderLayout.CENTER); 39 add(panel3, BorderLayout.SOUTH); 40 41 //将三个单选框组成单选按钮 42 ButtonGroup group = new ButtonGroup(); 43 group.add(jrbRed); 44 group.add(jrbGreen); 45 group.add(jrbBlue); 46 47 jtfRadius.addActionListener(new ActionListener(){ 48 public void actionPerformed(ActionEvent e) { 49 if(model == null) return ;//还没有model 50 model.setRadius(new Double(jtfRadius.getText()).doubleValue()); 51 } 52 }); 53 54 jcboFilled.addActionListener(new ActionListener(){ 55 public void actionPerformed(ActionEvent e){ 56 if(model == null) return; 57 model.setFilled( ((Boolean)jcboFilled.getSelectedItem()).booleanValue()); 58 } 59 }); 60 61 //单选按钮监听 62 jrbRed.addActionListener(new ActionListener(){ 63 public void actionPerformed(ActionEvent e){ 64 if(model == null) return; 65 model.setColor(Color.RED); 66 } 67 }); 68 69 jrbGreen.addActionListener(new ActionListener(){ 70 public void actionPerformed(ActionEvent e){ 71 if(model == null) return; 72 model.setColor(Color.GREEN); 73 } 74 }); 75 76 jrbBlue.addActionListener(new ActionListener(){ 77 public void actionPerformed(ActionEvent e){ 78 if(model == null) return; 79 model.setColor(Color.BLUE); 80 } 81 }); 82 } 83 84 public void setModel(CircleModel newModel){ 85 model = newModel; 86 } 87 88 public CircleModel getModel() { 89 return model; 90 } 91 }
MVCDemo:
1 package circleMVC; 2 3 import java.awt.*; 4 import java.awt.event.*; 5 import javax.swing.*; 6 public class MVCDemo extends JApplet { 7 private JButton jbtController = new JButton("Show Contuoller"); 8 private JButton jbtView = new JButton("Show View"); 9 private CircleModel model = new CircleModel(); 10 11 public MVCDemo() { 12 setLayout(new FlowLayout()); 13 add(jbtController); 14 add(jbtView); 15 16 jbtController.addActionListener(new ActionListener() { 17 @Override 18 public void actionPerformed(ActionEvent e) { 19 20 JFrame frame = new JFrame("Controller"); 21 CircleController controller = new CircleController(); 22 controller.setModel(model); 23 frame.add(controller); 24 frame.setSize(240, 100); 25 frame.setLocation(200, 200); 26 frame.setVisible(true); 27 } 28 }); 29 30 jbtView.addActionListener(new ActionListener() { 31 32 @Override 33 public void actionPerformed(ActionEvent e) { 34 JFrame frame = new JFrame("view"); 35 CircleView view = new CircleView(); 36 view.setModel(model); 37 frame.add(view); 38 frame.setSize(200, 200); 39 frame.setLocation(200, 200); 40 frame.setVisible(true); 41 } 42 }); 43 } 44 45 }
运行效果:
二、
在同一个窗口中使用MVC模式,控制器和视图都在同一个窗口中,可以使用鼠标拖动来控制半径,也可以使用输入来控制半径,同时面积和体积要同步更新。
难点:在同一个窗口中,控制器的数据怎么和视图的数据进行交互,而且要同步显示,控制器和视图相互交错,控制器也是视图,视图也是控制器。
代码如下:
模型:
1 /** 2 * java MVC模式 模型部分 3 * 2016/5/22 4 */ 5 package circleMVC_x; 6 7 import java.awt.Color; 8 import java.awt.event.*; 9 import java.util.*; 10 11 public class CircleModel { 12 //圆半径 13 private double radius = 20; 14 15 //是否填充 16 private boolean filled; 17 18 //颜色 19 private java.awt.Color color; 20 21 private ArrayList<ActionListener> actionListenerList; 22 23 public double getRadius() { 24 return radius; 25 } 26 27 public void setRadius(double radius) { 28 this.radius = radius; 29 processEvent(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "radius"));//当属性值改变是通知监听器 30 } 31 32 public boolean isFilled() { 33 return filled; 34 } 35 36 public void setFilled(boolean filled) { 37 this.filled = filled; 38 processEvent(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "filled"));//当属性值改变是通知监听器 39 } 40 41 42 43 public java.awt.Color getColor() { 44 return color; 45 } 46 47 public void setColor(java.awt.Color color) { 48 this.color = color; 49 processEvent(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "color"));//当属性值改变是通知监听器 50 } 51 52 public synchronized void addActionListener(ActionListener l){ 53 if(actionListenerList == null){ 54 actionListenerList = new ArrayList<ActionListener>(); 55 } 56 actionListenerList.add(l); 57 } 58 59 public synchronized void removeActionListener(ActionListener l){ 60 if(actionListenerList != null && actionListenerList.contains(l)){ 61 actionListenerList.remove(l); 62 } 63 } 64 65 private void processEvent(ActionEvent e){ 66 ArrayList list; 67 68 synchronized(this){ 69 if(actionListenerList == null) return; 70 list = (ArrayList)actionListenerList.clone(); 71 } 72 for(int i = 0; i < list.size(); i++){ 73 ActionListener listener = (ActionListener)list.get(i); 74 listener.actionPerformed(e); 75 } 76 } 77 }
控制器:
1 /** 2 * java MVC模式 控制器部分(其中面积,体积部分不能设置,算作视图) 3 * 2016/5/22 4 */ 5 package circleMVC_x; 6 7 import java.awt.*; 8 import java.awt.event.*; 9 import javax.swing.*; 10 public class CircleController extends JPanel implements ActionListener{ 11 private CircleModel model; 12 private JTextField jtfRadius = new JTextField(); 13 private JTextField jtfArea = new JTextField(); 14 private JTextField jtfVolume= new JTextField(); 15 private JRadioButton jrbRed, jrbGreen, jrbBlue; 16 17 //创建一个新的CircleController 18 public CircleController(){ 19 JPanel panel1 = new JPanel(); 20 panel1.setLayout(new GridLayout(3,1)); 21 panel1.add(new JLabel("半径:")); 22 panel1.add(new JLabel("面积:")); 23 panel1.add(new JLabel("体积:")); 24 25 // 26 JPanel panel2 = new JPanel(); 27 panel2.setLayout(new GridLayout(3,1)); 28 panel2.add(jtfRadius); 29 panel2.add(jtfArea); 30 panel2.add(jtfVolume); 31 32 JPanel panel3 = new JPanel(); 33 panel3.setLayout(new GridLayout(1, 3)); 34 panel3.add(jrbRed = new JRadioButton("Red")); 35 panel3.add(jrbGreen = new JRadioButton("Green")); 36 panel3.add(jrbBlue = new JRadioButton("Blue")); 37 38 39 40 setLayout(new BorderLayout()); 41 add(panel1, BorderLayout.WEST); 42 add(panel2, BorderLayout.CENTER); 43 add(panel3, BorderLayout.SOUTH); 44 45 //将三个单选框组成单选按钮 46 ButtonGroup group = new ButtonGroup(); 47 group.add(jrbRed); 48 group.add(jrbGreen); 49 group.add(jrbBlue); 50 51 jtfRadius.addActionListener(new ActionListener(){ 52 public void actionPerformed(ActionEvent e) { 53 if(model == null) return ;//还没有model 54 model.setRadius(new Double(jtfRadius.getText()).doubleValue()); 55 } 56 }); 57 58 59 //单选按钮监听 60 jrbRed.addActionListener(new ActionListener(){ 61 public void actionPerformed(ActionEvent e){ 62 if(model == null) return; 63 model.setColor(Color.RED); 64 } 65 }); 66 67 jrbGreen.addActionListener(new ActionListener(){ 68 public void actionPerformed(ActionEvent e){ 69 if(model == null) return; 70 model.setColor(Color.GREEN); 71 } 72 }); 73 74 jrbBlue.addActionListener(new ActionListener(){ 75 public void actionPerformed(ActionEvent e){ 76 if(model == null) return; 77 model.setColor(Color.BLUE); 78 } 79 }); 80 } 81 82 public void setModel(CircleModel newModel){ 83 model = newModel; 84 if(model != null){ 85 //给model增加啊监听器 86 model.addActionListener(this); 87 } 88 } 89 90 public CircleModel getModel() { 91 return model; 92 } 93 94 @Override 95 public void actionPerformed(ActionEvent e) { 96 double radius = model.getRadius(); 97 jtfRadius.setText(model.getRadius()+""); 98 double num_1 = 4 * Math.PI * radius * radius; 99 double num_1_1 = (Math.round(num_1 * 100) / 100.0);// 保留两位小数 100 jtfArea.setText(num_1_1+""); 101 double num_2 = 4 / 3 * Math.PI * radius * radius; 102 double num_2_2 = (Math.round(num_2 * 100) / 100.0);// 保留两位小数 103 jtfVolume.setText(num_2_2+""); 104 105 } 106 }
视图:
1 /** 2 * java MVC模式 视图部分 3 * 2016/5/22 4 */ 5 package circleMVC_x; 6 7 import java.awt.*; 8 import java.awt.event.*; 9 import javax.swing.*; 10 public class CircleView extends JPanel implements ActionListener{ 11 private CircleModel model; 12 13 public CircleView(){ 14 super.setBounds(12, 144, 426, 300); 15 repaint(); 16 //增加鼠标监听事件 17 addMouseMotionListener(new MouseMotionAdapter() { 18 public void mouseDragged(MouseEvent e){ 19 model = getModel(); 20 21 int x = e.getX(); 22 int y = e.getY(); 23 int radius; 24 25 double radius_d = Math.sqrt((x - (getWidth() / 2)) 26 * (x - (getWidth() / 2)) + (y - (getHeight() / 2)) 27 * (y - (getHeight() / 2))); 28 29 radius = (int) radius_d; 30 31 System.out.println("坐标:" + x + " " + y ); 32 model.setRadius(radius); 33 repaint(); 34 35 } 36 }); 37 } 38 public void actionPerformed(ActionEvent actionEvent){ 39 repaint(); 40 } 41 42 //设置一个model 43 public void setModel(CircleModel newModel) { 44 model = newModel; 45 46 if(model != null){ 47 //给model增加啊监听器 48 model.addActionListener(this); 49 } 50 51 repaint(); 52 } 53 54 public CircleModel getModel(){ 55 return model; 56 } 57 58 public void paintComponent(Graphics g){ 59 super.paintComponent(g); 60 61 if(model == null) return; 62 63 g.setColor(model.getColor()); 64 65 int radius = (int)model.getRadius(); 66 67 g.drawOval(getWidth() / 2 - radius, getHeight() / 2 - radius, 68 2 * radius, 2 * radius); 69 g.drawOval(getWidth() / 2 - radius / 2, getHeight() / 2 - radius, 70 radius, 2 * radius); 71 g.drawOval(getWidth() / 2 - radius, getHeight() / 2 - radius / 2, 72 2 * radius, radius); 73 } 74 }
程序入口:
1 /** 2 * javaMVC模式 入口 3 * 2016/6/20 4 */ 5 package circleMVC_x; 6 7 import java.awt.BorderLayout; 8 import java.awt.EventQueue; 9 10 import javax.swing.JFrame; 11 import javax.swing.JPanel; 12 import javax.swing.border.EmptyBorder; 13 import java.awt.FlowLayout; 14 15 public class MVCdemo_x extends JFrame { 16 17 private JPanel contentPane; 18 private CircleController controller = new CircleController(); 19 private CircleView view = new CircleView(); 20 private CircleModel model = new CircleModel(); 21 22 /** 23 * Launch the application. 24 */ 25 public static void main(String[] args) { 26 EventQueue.invokeLater(new Runnable() { 27 public void run() { 28 try { 29 MVCdemo_x frame = new MVCdemo_x(); 30 frame.setSize(500, 500); 31 frame.setVisible(true); 32 } catch (Exception e) { 33 e.printStackTrace(); 34 } 35 } 36 }); 37 } 38 39 /** 40 * Create the frame. 41 */ 42 public MVCdemo_x() { 43 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 44 setBounds(100, 100, 450, 300); 45 contentPane = new JPanel(); 46 contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); 47 setContentPane(contentPane); 48 contentPane.setLayout(null); 49 50 JPanel panel = new JPanel(); 51 controller.setModel(model); 52 panel.add(controller); 53 panel.setBounds(57, 34, 310, 98); 54 contentPane.add(panel); 55 56 view.setModel(model); 57 contentPane.add(view); 58 } 59 }
运行结果: