프로그래머를위한 Java 2, 4 판 제8장자바 GUI 프로그래밍 II
8.1 MVC 스윙모델 MVC (Model, View, Controller) 모델 스윙은 MVC 모델에기초를두고있다. MVC란 Xerox의연구소에서 Smalltalk 언어를바탕으로사용자인터페이스를개발하기위한방법 MVC는 3개의구성요소로구성 Model : 응용프로그램의자료를표현하기위한모델 View : 자료를시각적으로 (GUI 방식으로 ) 표현하는것 Controller: 사용자가 View를통해입력을하면 Model을변경해주는것 MVC Model 2
8.1 MVC 스윙모델 스윙의 MVC 모델 모델, 뷰, 컨트롤러를분리한 MVC 모델은상당히유용하고강력한프로그래밍모델이기때문에사용자인터페이스개발에많이적용 스윙을개발하면서 MVC 모델을그대로적용하기에는실제적인어려움이많아서 MVC를변형한모델을개발. 스윙에서는 MVC의뷰와컨트롤러를합쳐서 "UI delegate" 라는객체를정의. 스윙의 MVC 모델 내부상태, 자료관리 UI delegate 모양결정, 이벤트 MVC Model 3
MVC 스윙모델 스윙의모든 GUI 컴포넌트들은 UI delegate 부분과 Model 부분으로구성 UI delegate 부분은 GUI 컴포넌트의모양과사용자의입력에따른이벤트를처리 모델의역할 내부상태를알아본다. 내부상태를관리한다. 이벤트리스너를추가 / 삭제한다. 이벤트를발생시킨다. UI delegate 의역할 GUI 컴포넌트를그려준다. GUI 컴포넌트의위치정보를리턴한다. AWT 이벤트를처리한다. MVC Model 4
8.1 MVC 스윙모델 각컴포넌트의모델인터페이스와모델타입 (I) MVC Model 5
8.1 MVC 스윙모델 각컴포넌트의모델인터페이스와모델타입 (II) MVC Model 6
8.1 MVC 스윙모델 버튼모델예 MVC Model 7
예제 : CountButtonModel.java 8.1 MVC 스윙모델 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); MVC Model 8
8.1 MVC 스윙모델 예제 : 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); MVC Model 9
8.1 MVC 스윙모델 새로운컴포넌트 (ShipComponent) 만들기 MVC Model 10
8.1 MVC 스윙모델 예제 : 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 } MVC Model 11
8.1 MVC 스윙모델 예제 : 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(); MVC Model 12
8.1 MVC 스윙모델 예제 : 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 } MVC Model 13
8.1 MVC 스윙모델 예제 : 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(); MVC Model 14
8.1 MVC 스윙모델 예제 : 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); MVC Model 15
8.1 MVC 스윙모델 예제 : 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); MVC Model 16
8.1 MVC 스윙모델 예제 : ShipModel.java 1 public interface ShipModel { 2 public String getdata(); 3 } MVC Model 17
8.1 MVC 스윙모델 예제 : 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; MVC Model 18
8.1 MVC 스윙모델 예제 : 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()); MVC Model 19
8.1 MVC 스윙모델 결과 MVC Model 20
8.2.1 리스트 (JList) 리스트 (JList) 여러개의값들중에서하나혹은여러개를선택할수있는 GUI 컴포넌트 형태 리스트사용예 String [] data = { "ABC", "DEF", "GHI" }; JList list = new JList(data); JScrollPane pane = new JScrollPane(list); MVC Model 21
8.2.1 리스트 (JList) 리스트모델의상속관계 MVC Model 22
8.2.2 콤보박스 (JComboBox) 콤보박스 여러개의값들중에서하나만선택할수있는 GUI 컴포넌트 드랍다운메뉴라고도함 형태 콤보박스사용예 String[] data = { "ab", "cde" }; JComboBox c = new JComboBox(data); JComboBox c = new JComboBox(); c.additem("ab"); c.additem("cde"); MVC Model 23
8.2.2 콤보박스 (JComboBox) 예제 : 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); MVC Model 24
8.2.2 콤보박스 (JComboBox) 예제 : 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()); MVC Model 25
8.2.3 셀편집기와렌더러 셀렌더러 데이터값을화면에보여주기위해서사용되는클래스 리스트, 콤보박스, 테이블, 트리에서사용 보통 JLabel로부터상속받은클래스사용 셀편집기 셀데이터값을수정할수있도록지원하는클래스 리스트, 콤보박스, 테이블, 트리에서사용 보통 JTextField로부터상속받은클래스사용 MVC Model 26
8.2.3 셀편집기와렌더러 셀렌더러상속관계 MVC Model 27
예제 : IconCellRenderer.java 8.2.3 셀편집기와렌더러 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)); MVC Model 28
8.2.3 셀편집기와렌더러 예제 : 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()); MVC Model 29
8.2.4 스피너 (JSpinner) 스피너 마우스클릭으로여러개의값들중에서하나를선택할수있는 GUI 컴포넌트 형태 스피너사용예 SpinnerNumberModel scoremodel = new JSpinner(scoreModel); SpinnerNumberModel(0,0,100,5); MVC Model 30
8.2.4 스피너 (JSpinner) 예제 : 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); MVC Model 31
8.3 텍스트컴포넌트 텍스트컴포넌트 JTextField 한줄입력 JPasswordField 암호한줄입력 JFormattedTextField 포맷이텍스트의한줄입력 JTextArea 여러줄의텍스트 MVC Model 32
8.3 텍스트컴포넌트 예제 : 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); MVC Model 33
8.3 텍스트컴포넌트 예제 : 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 } MVC Model 34
8.4.1 탭팬 (JTabbedPane) 탭팬 탭을이용해서공간을효율적으로사용하기위한 GUI 컴포넌트 형태 탭팬사용예 JTabbedPane pane = JTabbedPane(); pane.addtab( One, icon, panel); MVC Model 35
8.4.2 트리 (JTree) 트리 계층적은데이터를표현하기위한 GUI 컴포넌트 형태 트리사용예 JMutableTreeNode root = new JMutableTreeNode(" 노드 "); JMutableTreeNode n1 = new JMutableTreeNode(" 노드1"); root.add(n1); JTree tree = new JTree(root); MVC Model 36
8.4.2 트리 (JTree) 예제 : 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); MVC Model 37
8.4.2 트리 (JTree) 예제 : 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 } MVC Model 38
8.4.3 테이블 (JTable) 테이블 많은레코드데이터를표현하기위한 GUI 컴포넌트 형태 테이블사용예 String head[] = { "A", "B" }; String data[][] = { {"a", "b"} }; JTable table = new JTable(data, head); MVC Model 39
8.4.3 테이블 (JTable) 예제 : 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); MVC Model 40
8.4.3 테이블 (JTable) 예제 : 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 } MVC Model 41
8.4.5 내부프레임 (JInternalFrame) 내부프레임 MDI(Multiple Document Interface) 형태를지원하기위한 GUI 컴포넌트 형태 내부프레임사용예 JInternalFrame f = new JInternalFrame(" 타이틀 ", true); f.setsize(400, 300); f.setvisible(true); MVC Model 42
8.4.5 내부프레임 (JInternalFrame) 예제 : 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); MVC Model 43
8.5 자바룩-앤-필 룩 - 앤 - 필 스윙 GUI 형태를동적으로변경할수있는방법을제공 기본으로제공되는룩-앤-필 자바 모티프 윈도우 기타 JDK 버전에따라약간씩다름 필요한경우에개발자가새로운룩-앤-필을개발할수있음 MVC Model 44
예제 : LookNFeelTest.java 65 if(o == metal) { 66 try { 8.5 자바룩-앤-필 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); MVC Model 45
8.6 드래그 -앤-드랍 드래그 - 앤 - 드랍 (Drag & Drop) 자바프로그램간혹은일반프로그램과자바프로그램간의드래그 - 앤 - 드랍을지원 용어및지원되는클래스들 드래그소스 (DragSource) : 드래그-앤-드랍이시작되는 GUI 컴포넌트 드래그타겟 (DropTarget) : 드래그-앤-드랍이끝나는 GUI 컴포넌트 Transferable : 드래그-앤-드랍을통해서전달되는데이터 DataFlavor : 드래그-앤-드랍을통해서전달되는데이터포맷 DnDConstants : 드래그-앤-드랍의동작방식 MVC Model 46
8.6 드래그 -앤-드랍 예제 : 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 } MVC Model 47
8.6 드래그 -앤-드랍 예제 : 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)); MVC Model 48
8.6 드래그 -앤-드랍 결과 MVC Model 49