프로그래머를
프로그래머를 위한 위한 Java 2, 4 Java 2, 4 판 판
제 제 8 8 장 장 자바 자바 GUI GUI 프로그래밍 프로그래밍 II II
Chap.8
MVC Model 2
8.1 MVC
8.1 MVC 스윙스윙 모델모델
z
MVC (Model, View, Controller) 모델
스윙은 MVC 모델에 기초를 두고 있다.
MVC란 Xerox의 연구소에서 Smalltalk 언어를 바탕으로 사용자 인터페이스를 개발하기 위한 방법
MVC는 3개의 구성 요소로 구성
Model : 응용 프로그램의 자료를 표현하기 위한 모델
View : 자료를 시각적으로 (GUI 방식으로) 표현하는 것
Controller: 사용자가 View를 통해 입력을 하면 Model을 변경해주는 것
Chap.8
MVC Model 3
8.1 MVC
8.1 MVC 스윙스윙 모델모델
z
스윙의 MVC 모델
모델 , 뷰, 컨트롤러를 분리한 MVC 모델은 상당히 유용하고 강력한 프로그래밍 모델이기 때문에 사용자 인터페이스 개발에 많이 적용
스윙을 개발하면서 MVC 모델을 그대로 적용하기에는 실제적인 어려움이 많아서 MVC를 변형한 모델을 개발.
스윙에서는 MVC의 뷰와 컨트롤러를 합쳐서 "UI delegate"라는 객체를 정의 .
z
스윙의 MVC
모델 – 내부 상태, 자료 관리
UI delegate – 모양 결정, 이벤트
Chap.8
MVC Model 4
MVC MVC 스윙스윙 모델모델
스윙의 모든 GUI 컴포넌트들은 UI delegate 부분과 Model 부분으로 구성
UI delegate 부분은 GUI 컴포넌트의 모양과 사용자의 입력에 따른 이벤트를 처리
모델의 역할
내부 상태를 알아본다.
내부 상태를 관리한다.
이벤트 리스너를 추가/삭제 한다.
이벤트를 발생시킨다.
UI delegate의 역할
GUI 컴포넌트를 그려준다.
GUI 컴포넌트의 위치 정보를 리턴한다.
AWT 이벤트를 처리한다.
Chap.8
MVC Model 5
8.1 MVC
8.1 MVC 스윙스윙 모델모델
z
각 컴포넌트의 모델 인터페이스와 모델 타입 (I)
Chap.8
MVC Model 6
8.1 MVC
8.1 MVC 스윙스윙 모델모델
z
각 컴포넌트의 모델 인터페이스와 모델 타입 (II)
Chap.8
MVC Model 7
8.1 MVC
8.1 MVC 스윙스윙 모델모델
z
버튼 모델 예
Chap.8
MVC Model 8
8.1 MVC
8.1 MVC 스윙스윙 모델모델
z
예제 : CountButtonModel.java
4 public class CountButtonModel extends DefaultButtonModel { 5 private int count;
6 private JButton btn;
7
8 public CountButtonModel(JButton btn) { 9 this.btn = btn;
10 btn.setModel(this);
11 }
13 public void setPressed(boolean b) { 14 if(b) {
15 count = ++count % 4;
16 switch(count) { 17 case 0:
18 btn.setBackground(Color.lightGray);
Chap.8
MVC Model 9
8.1 MVC
8.1 MVC 스윙스윙 모델모델
z
예제 : ButtonModelTest.java
8 ImageIcon rai = new ImageIcon("rai.gif");
9 ok = new JButton("OK", rai);
10 ok.setRolloverIcon(rai);
11 ok.setPressedIcon(rai);
12 CountButtonModel model = new CountButtonModel(ok);
13
14 getContentPane().add("South", ok);
15 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
16 setSize(400, 300);
17 setVisible(true);
Chap.8
MVC Model 10
8.1 MVC
8.1 MVC 스윙스윙 모델모델
z
새로운 컴포넌트 (ShipComponent) 만들기
Chap.8
MVC Model 11
8.1 MVC
8.1 MVC 스윙스윙 모델모델
z
예제 : ShipComponent.java
5 public class ShipComponent extends JComponent { 6 private ShipModel model;
7 private ShipComponentUI ui;
8 private ActionListener actionListener;
9 private boolean pressed;
10
11 public ShipComponent(String s, String d) {
12 enableEvents(AWTEvent.MOUSE_EVENT_MASK);
13 model = new DefaultShipModel(s, d);
14 setUI(new ShipComponentUI());
15 }
Chap.8
MVC Model 12
8.1 MVC
8.1 MVC 스윙스윙 모델모델
z
예제 : ShipComponent.java(계속)
22 public void paint(Graphics g) { 23 ui.paint(this, g);
24 }
…
35 public void setUI(ShipComponentUI ui) { 36 if(ui != null && this.ui != null) {
37 this.ui.uninstallUI(this);
38 }
40 if(ui != null) { 41 this.ui = ui;
42 this.ui.installUI(this);
43 }
44 updateShipComponent();
Chap.8
MVC Model 13
8.1 MVC
8.1 MVC 스윙스윙 모델모델
z
예제 : ShipComponent.java(계속)
51 public Dimension getPreferredSize() { 52 return ui.getPreferredSize(this);
53 }
…
67 public boolean isPressed() { 68 return pressed;
69 } 70
71 public void addActionListener(ActionListener listener) { 72 actionListener =
73 AWTEventMulticaster.add(actionListener, listener);
74 }
Chap.8
MVC Model 14
8.1 MVC
8.1 MVC 스윙스윙 모델모델
z
예제 : ShipComponent.java(계속)
81 public void processMouseEvent(MouseEvent e) { 82 Graphics g;
83 switch(e.getID()) {
…
88 case MouseEvent.MOUSE_RELEASED:
89 if(actionListener != null) {
90 actionListener.actionPerformed(new ActionEvent(this, 91 ActionEvent.ACTION_PERFORMED, model.getData()));
92 }
93 if(pressed == true) { 94 pressed = false;
95 repaint();
Chap.8
MVC Model 15
8.1 MVC
8.1 MVC 스윙스윙 모델모델
z
예제 : ShipComponentUI.java
5 public class ShipComponentUI extends ComponentUI { 6 private Dimension dim;
…
32 public void paint(ShipComponent ship, Graphics g) {
…
37 int xs[] = {2, d.width-2, 2*d.width/3, d.width/3, 2};
38 int ys[] = { 2, 2, d.height -2, d.height - 2, 2};
39 Color fg = g.getColor();
40 g.setColor(new Color(200, 200, 200));
41 g.fillPolygon(xs, ys, xs.length);
42 g.setColor(fg);
43 if(ship.isPressed()) {
44 g.drawPolygon(xs, ys, xs.length);
Chap.8
MVC Model 16
8.1 MVC
8.1 MVC 스윙스윙 모델모델
z
예제 : ImgShipComponentUI.java
3 public class ImgShipComponentUI extends ShipComponentUI { 4 private Image img;
…
37 public void paint(ShipComponent ship, Graphics g) { 38 Dimension d = ship.getSize();
39 ShipModel model = ship.getModel();
40 ship.setToolTipText(model.getData());
41 if(img != null) {
42 int x = (d.width - img.getWidth(ship))/2;
43 int y = (d.height - img.getHeight(ship))/2;
44 g.drawImage(img, x, y, ship);
45 }
46 if(ship.isPressed()) {
47 g.drawRect(1,1,d.width-2, d.height-2);
Chap.8
MVC Model 17
8.1 MVC
8.1 MVC 스윙스윙 모델모델
z
예제 : ShipModel.java
1 public interface ShipModel { 2 public String getData();
3 }
Chap.8
MVC Model 18
8.1 MVC
8.1 MVC 스윙스윙 모델모델
z
예제 : DefaultShipModel.java
1 public class DefaultShipModel implements ShipModel { 2 private String dest;
3 private String start;
4
5 public DefaultShipModel(String s, String d) { 6 start = s;
7 dest = d;
8 } 9
10 public String getData() {
11 return start + " -> " + dest;
Chap.8
MVC Model 19
8.1 MVC
8.1 MVC 스윙스윙 모델모델
z
예제 : MVCTest.java
4 public class MVCTest extends JFrame implements ActionListener { 6 private ShipComponent toLA, toTokyo;
…
12 toLA = new ShipComponent("Seoul", "LA");
13 toLA.addActionListener(this);
14 map.add(toLA);
…
19 toTokyo = new ShipComponent("Seoul", "Tokyo");
20 toTokyo.addActionListener(this);
21 toTokyo.setUI(new ImgShipComponentUI(this, "ship.jpg"));
22 map.add(toTokyo);
23 toTokyo.setLocation(250, 130);
24 toTokyo.setSize(toTokyo.getPreferredSize());
Chap.8
MVC Model 20
8.1 MVC
8.1 MVC 스윙스윙 모델모델
z
결과
Chap.8
MVC Model 21
8.2.1
8.2.1 리스트리스트((JListJList))
z
리스트 (JList)
여러 개의 값들 중에서 하나 혹은 여러 개를 선택할 수 있는 GUI 컴포넌트
형태
z
리스트 사용 예
String [] data = { "ABC", "DEF", "GHI" };
JList list = new JList(data);
JScrollPane pane = new JScrollPane(list);
Chap.8
MVC Model 22
8.2.1
8.2.1 리스트리스트((JListJList))
z
리스트 모델의 상속 관계
Chap.8
MVC Model 23
8.2.2
8.2.2 콤보콤보 박스박스((JComboBoxJComboBox))
z
콤보 박스
여러 개의 값들 중에서 하나만 선택할 수 있는 GUI 컴포넌트
드랍 다운 메뉴라고도 함
형태
z
콤보 박스 사용 예
String[] data = { "ab", "cde" };
JComboBox c = new JComboBox(data);
JComboBox c = new JComboBox();
c.addItem("ab");
c.addItem("cde");
Chap.8
MVC Model 24
8.2.2
8.2.2 콤보콤보 박스박스((JComboBoxJComboBox))
z
예제 : JListComboBox.java
8 protected String items[] = {"apple", "orange", "banana", "pear"};
…
13 fruits = new JList(items);
14 fruits.addMouseListener(new MouseAdapter() { 15 public void mouseClicked(MouseEvent e) {
16 int index = fruits.locationToIndex(e.getPoint());
17 if (e.getClickCount() == 1) {
18 System.out.println(items[index]);
19 } else if(e.getClickCount() == 2) {
20 System.out.println("[" + items[index] + "]");
…
24 fruits.setVisibleRowCount(3);
25 JScrollPane sp = new JScrollPane(fruits);
Chap.8
MVC Model 25
8.2.2
8.2.2 콤보콤보 박스박스((JComboBoxJComboBox))
z
예제 : JListComboBox.java(계속)
27 colors = new JComboBox();
28 colors.addItem("white");
29 colors.addItem("blue");
30 colors.addItem("green");
31 colors.addItemListener(this);
…
40 public void itemStateChanged(ItemEvent e) { 41 Object o = e.getSource();
42 if(o == colors) {
43 if(e.getStateChange() == ItemEvent.SELECTED) { 44 Object data = colors.getSelectedItem();
45 System.out.println(data.toString());
Chap.8
MVC Model 26
8.2.3
8.2.3 셀셀 편집기와편집기와 렌더러렌더러
z
셀 렌더러
데이터 값을 화면에 보여주기 위해서 사용되는 클래스
리스트 , 콤보 박스, 테이블, 트리에서 사용
보통 JLabel로부터 상속받은 클래스 사용
z
셀 편집기
셀 데이터 값을 수정할 수 있도록 지원하는 클래스
리스트 , 콤보 박스, 테이블, 트리에서 사용
보통 JTextField로부터 상속받은 클래스 사용
Chap.8
MVC Model 27
8.2.3
8.2.3 셀셀 편집기와편집기와 렌더러렌더러
z
셀 렌더러 상속 관계
Chap.8
MVC Model 28
8.2.3
8.2.3 셀셀 편집기와편집기와 렌더러렌더러
z
예제 : IconCellRenderer.java
5 public class IconCellRenderer extends DefaultListCellRenderer {
…
12 public Component getListCellRendererComponent(JList list, 13 Object value, int index, boolean isSelected,
14 boolean cellHasFocus) { 15
16 String text = value.toString();
17 setText(text);
18 if(!icons.containsKey(text)) {
19 ImageIcon img = new ImageIcon(text + ".gif");
20 icons.put(text, img);
21 setIcon(img);
22 } else {
23 setIcon((ImageIcon)icons.get(text));
Chap.8
MVC Model 29
8.2.3
8.2.3 셀셀 편집기와편집기와 렌더러렌더러
z
예제 : DeviceListCombo.java
5 protected JList list;
6 protected JComboBox combo;
7
8 public DeviceListCombo() {
9 super("아이콘을 갖는 리스트와 콤보");
10 String[] data = {"keyboard", "mouse", "joystick" };
11 list = new JList(data);
12 list.setBackground(Color.lightGray);
13 list.setCellRenderer(new IconCellRenderer());
14 getContentPane().add(new JScrollPane(list), "Center");
15
16 combo = new JComboBox(data);
17 combo.setRenderer(new IconCellRenderer());
Chap.8
MVC Model 30
8.2.4
8.2.4 스피너스피너((JSpinnerJSpinner))
z
스피너
마우스 클릭으로 여러 개의 값들 중에서 하나를 선택할 수 있는 GUI 컴포넌트
형태
z
스피너 사용 예
SpinnerNumberModel scoreModel = new
SpinnerNumberModel(0,0,100,5);
JSpinner(scoreModel);
Chap.8
MVC Model 31
8.2.4
8.2.4 스피너스피너((JSpinnerJSpinner))
z
예제 : SpinnerTest.java
10 SpinnerNumberModel scoreModel =
11 new SpinnerNumberModel(0, 0, 100, 5);
12 score = new JSpinner(scoreModel);
…
16 String colors[] = { "빨강", "노랑", "파랑" };
17 SpinnerListModel colorModel = new SpinnerListModel(colors);
18 color = new JSpinner(colorModel);
…
22 SpinnerDateModel dateModel = new SpinnerDateModel();
23 date = new JSpinner(dateModel);
Chap.8
MVC Model 32
8.3 8.3 텍스트텍스트 컴포넌트컴포넌트
z
텍스트 컴포넌트
JTextField
한 줄 입력
JPasswordField
암호 한 줄 입력
JFormattedTextField
포맷이 텍스트의 한 줄 입력
JTextArea
여러 줄의 텍스트
Chap.8
MVC Model 33
8.3 8.3 텍스트텍스트 컴포넌트컴포넌트
z
예제 : SwingText.java
13 public SwingText() throws ParseException {
…
17 area = new JTextArea();
18 field = new JTextField(10);
19 field.addActionListener(this);
20 passwd = new JPasswordField(10);
21 passwd.addActionListener(this);
22
23 MaskFormatter mf = new MaskFormatter("(0##) ####-####");
24 mf.setPlaceholderCharacter('_');
25 phone = new JFormattedTextField(mf);
26 phone.addActionListener(this);
Chap.8
MVC Model 34
8.3 8.3 텍스트텍스트 컴포넌트컴포넌트
z
예제 : SwingText.java(계속)
43 public void actionPerformed(ActionEvent e) { 44 Object o = e.getSource();
45 if(o == field || o == passwd || o == phone) { 46 System.out.println("ID - " + field.getText());
47 char [] data = passwd.getPassword();
48 System.out.println("PASSWD - " + new String(data));
49 System.out.println("Phone - " + phone.getValue());
50 } 51 }
Chap.8
MVC Model 35
8.4.1
8.4.1 탭팬탭팬((JTabbedPaneJTabbedPane))
z
탭팬
탭을 이용해서 공간을 효율적으로 사용하기 위한 GUI 컴포넌트
형태
z
탭팬 사용 예
JTabbedPane pane = JTabbedPane();
pane.addTab(“One”, icon, panel);
Chap.8
MVC Model 36
8.4.2
8.4.2 트리트리((JTreeJTree))
z
트리
계층적은 데이터를 표현하기 위한 GUI 컴포넌트
형태
z
트리 사용 예
JMutableTreeNode root = new JMutableTreeNode("노드");
JMutableTreeNode n1 = new JMutableTreeNode("노드1");
root.add(n1);
JTree tree = new JTree(root);
Chap.8
MVC Model 37
8.4.2
8.4.2 트리트리((JTreeJTree))
z
예제 : TreeDemo.java
11 DefaultMutableTreeNode jcomponent =
12 new DefaultMutableTreeNode("JComponent");
14 DefaultMutableTreeNode jpanel =
15 new DefaultMutableTreeNode("JPanel");
…
21 jcomponent.add(jpanel);
…
33 tree = new JTree(jcomponent);
34 tree.addMouseListener(this);
35 JScrollPane sp = new JScrollPane(tree);
Chap.8
MVC Model 38
8.4.2
8.4.2 트리트리((JTreeJTree))
z
예제 : TreeDemo.java(계속)
46 public void mousePressed(MouseEvent e) {
47 TreePath path = tree.getPathForLocation(e.getX(), e.getY());
48 if(path == null) 49 return;
50
51 Object o = path.getLastPathComponent();
52 if(o instanceof DefaultMutableTreeNode) {
53 DefaultMutableTreeNode node = (DefaultMutableTreeNode) o;
54 Object uobj = node.getUserObject();
55 System.out.println(uobj);
56 }
Chap.8
MVC Model 39
8.4.3
8.4.3 테이블테이블((JTableJTable))
z
테이블
많은 레코드 데이터를 표현하기 위한 GUI 컴포넌트
형태
z
테이블 사용 예
String head[] = { "A", "B" };
String data[][] = { {"a", "b"} };
JTable table = new JTable(data, head);
Chap.8
MVC Model 40
8.4.3
8.4.3 테이블테이블((JTableJTable))
z
예제 : TableDemo.java
11 String fieldName[] = { 12 "이름",
13 "전화번호",
…
17 data = new String[3][3];
18 String r0[] = {"최종명", "000-0000", "jmchoi@email"};
19 data[0] = r0;
20 String r1[] = {"박준서", "111-1111", "jspark@email"};
21 data[1] = r1;
25 table = new JTable(data, fieldName);
26 table.addMouseListener(this);
27 JScrollPane sp = new JScrollPane(table);
Chap.8
MVC Model 41
8.4.3
8.4.3 테이블테이블((JTableJTable))
z
예제 : TableDemo.java(계속)
38 public void mousePressed(MouseEvent e) { 39 int row = table.getSelectedRow();
40 int col = table.getSelectedColumn();
41 if(row == -1 || col == -1) 42 return;
43
44 System.out.print("<" + row + "," + col + "> - ");
45 System.out.println(data[row][col]);
46 }
Chap.8
MVC Model 42
8.4.5
8.4.5 내부내부 프레임프레임((JInternalFrameJInternalFrame))
z
내부 프레임
MDI(Multiple Document Interface) 형태를 지원하기 위한 GUI 컴포넌트
형태
z
내부 프레임 사용 예
JInternalFrame f = new JInternalFrame("타이틀", true);
f.setSize(400, 300);
f.setVisible(true);
Chap.8
MVC Model 43
8.4.5
8.4.5 내부내부 프레임프레임((JInternalFrameJInternalFrame))
z
예제 : InnerFrame.java
11 JDesktopPane desk = new JDesktopPane();
12 iframe = new JInternalFrame("프레임", true, true, true, true);
13 text = new JTextArea();
14 iframe.getContentPane().add(new JScrollPane(text), 15 BorderLayout.CENTER);
16 desk.add(iframe);
17 iframe.setSize(400, 300);
18 iframe.setVisible(true);
19 getContentPane().add(desk, BorderLayout.CENTER);
Chap.8
MVC Model 44
8.5 8.5 자바자바 룩룩--앤앤--필필
z
룩 -앤-필
스윙 GUI 형태를 동적으로 변경할 수 있는 방법을 제공
기본으로 제공되는 룩 -앤-필
자바
모티프
윈도우
기타 – JDK 버전에 따라 약간씩 다름
필요한 경우에 개발자가 새로운 룩 -앤-필을 개발할 수 있음
Chap.8
MVC Model 45
8.5 8.5 자바자바 룩룩--앤앤--필필
z
예제 : LookNFeelTest.java
65 if(o == metal) { 66 try {
67 UIManager.setLookAndFeel(
68 "javax.swing.plaf.metal.MetalLookAndFeel" );
69 SwingUtilities.updateComponentTreeUI(this);
70 } catch(Exception ex1) { 71 ex1.printStackTrace();
72 }
73 } else if(o == motif) { 74 try {
75 UIManager.setLookAndFeel(
76 "com.sun.java.swing.plaf.motif.MotifLookAndFeel" );
77 SwingUtilities.updateComponentTreeUI(this);
Chap.8
MVC Model 46
8.6 8.6 드래그드래그--앤앤--드랍드랍
z
드래그 -앤-드랍(Drag & Drop)
자바 프로그램간 혹은 일반 프로그램과 자바 프로그램간의 드래그 -앤- 드랍을 지원
용어 및 지원되는 클래스들
드래그 소스(DragSource) : 드래그-앤-드랍이 시작되는 GUI 컴포넌트
드래그 타겟(DropTarget) : 드래그-앤-드랍이 끝나는 GUI 컴포넌트
Transferable : 드래그-앤-드랍을 통해서 전달되는 데이터
DataFlavor : 드래그-앤-드랍을 통해서 전달되는 데이터 포맷
DnDConstants : 드래그-앤-드랍의 동작 방식
Chap.8
MVC Model 47
8.6 8.6 드래그드래그--앤앤--드랍드랍
z
예제 : DnDText.java
2 import java.awt.dnd.*;
3 import java.awt.datatransfer.*;
…
6 public class DnDText extends JFrame implements DropTargetListener {
…
12 editor = new JTextArea();
13 target = new DropTarget(editor,
14 DnDConstants.ACTION_COPY_OR_MOVE, this, true, null);
…
21 public void dragEnter(DropTargetDragEvent dtde) { 22 System.out.println("dragEnter");
23 }
Chap.8
MVC Model 48
8.6 8.6 드래그드래그--앤앤--드랍드랍
z
예제 : DnDText.java(예제)
33 public void drop(DropTargetDropEvent dtde) { 35 if((dtde.getDropAction() &
36 DnDConstants.ACTION_COPY_OR_MOVE) != 0) { 37 dtde.acceptDrop(dtde.getDropAction());
38 Transferable tr = dtde.getTransferable();
39 try {
40 java.util.List list = (java.util.List)
41 tr.getTransferData(DataFlavor.javaFileListFlavor);
42 File file = (File)list.get(0);
43 char buf[] = new char[1024];
44 BufferedReader in =
45 new BufferedReader(new FileReader(file));
…
48 while((n = in.read(buf, 0, 1024)) != -1) { 49 editor.append(new String(buf, 0, n));
Chap.8
MVC Model 49
8.6 8.6 드래그드래그--앤앤--드랍드랍
z