(12)-23.10.10[JAVA]

DANA·2023년 10월 10일

KDT-구디아카데미

목록 보기
12/56

<시간 출력하기>

package com.week3;

import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Calendar;
// main스레드와 통신객체 사이에 경합이 벌어질 수 있어서 굳이 Thread 상속을 받았음 -> 이러면 보다 안정화 가져올 수 있다(메신저)
public class TimeServer extends Thread {
	//아래 소켓은 서버소켓에 접속해온 클라이언트의 소켓정보를 쥐고 있다.
	//TimeClient에서 new Socket(ip,port);호출될 때 그때 결정되므로 일단 null이다
	Socket client = null;
	public TimeServer(Socket client) {
		this.client = client;
	}
	@Override
	public void run() {
		try {
			ObjectOutputStream oos = new ObjectOutputStream(client.getOutputStream());
			while(true) {
				//서버소켓에 접속한 클라이언트 소켓을 가지고 OutputStream을 생성하면 writeObject메소드를 통해서
				//오브젝트단위로 메시지를 쓴다
				System.out.println("server run호출");
				oos.writeObject(getTime());
				try {
					sleep(1000);
				} catch (Exception e) {
					// TODO: handle exception
				} 
			}
		} catch (Exception e) {
			try {
				client.close();
			} catch (Exception e2) {
				// TODO: handle exception
			}
		}
	}
	private Object getTime() {
		// TODO Auto-generated method stub
		return null;
	}
	//서버측에서 CalendarAPI 를 이용해 현재 시간 정보를 반환하는 메소드 설계한다
	//반환타입과 리턴타입을 결정해 본다.- 파라미터는 필요없다. -리턴타입은 String한다.
	private String getTimeStr() {
		Calendar cal = Calendar.getInstance();
		int hour = cal.get(Calendar.HOUR_OF_DAY);
		int min = cal.get(Calendar.MINUTE);
		int sec = cal.get(Calendar.SECOND);

		return (hour < 10 ? "0" + hour : "" + hour) + ":" +
				(min < 10 ? "0" + min : "" + min)  + ":" +
				(sec < 10 ? "0" + sec : "" + sec) ;
	}
	public static void main(String[] args) {
		int port = 5000;
		// 선언과 생성을 나누어 하는 건 network는 반드시 예외처리를 해야 함
		// 사용된 자원은 반납해야 하므로 catch블록이나 finally 블록에서 닫아주어야 함
		ServerSocket server = null;
		Socket client = null;
		try {
			server = new ServerSocket(port);
		} catch (IOException e) {
			System.out.println("해당포트는 이미 사용중입니다.");
			try {
				server.close();				
			} catch (Exception e2) {
				// TODO: handle exception
			}
		}///////////////////// end of try
		//여기 까지 진행되었다면 포트도 점유했고 서버소켓도 정상적으로 만들어짐
		System.out.println("TimeServer started successfully...");
		while(true) {
			try {
				// 클라이언트 소켓이 접속해 올 때까지 기다리고 있다 - waiting 상태 다음 코드가 진행되지 않음
				client = server.accept();
				if(client !=null) {
					//System.out.println(client);
				}
				System.out.println("New client connected...");
				// 전변으로 선언된 client가 69번 라인에 실체가 생김
				TimeServer ts = new TimeServer(client); // 생성자 파라미터로 넘겨서 생성자 안에서 InputStream,OutputStream 생성함
				ts.start();
				System.out.println("New TimeServer Thread started...");
			} catch (Exception e) {
				System.out.println("Can't start server thread!!!");
				e.printStackTrace();
				try {
					client.close();
				} catch (Exception e2) {
					// TODO: handle exception
				}
			}
		}////////////////////// end of main 
	}//////////////////////// end of main //////////////////////


}//end of TimeServer
package com.week3;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

import javax.swing.JLabel;

public class TimeClient extends Thread {

	JLabel jlbTime = null;
	TimeView tView = null;
	public TimeClient() {
		
	}
	public TimeClient(JLabel jlbTime) { // 여기 메소드도 학습목표
		this.jlbTime = jlbTime;
	}
	public TimeClient(TimeView tView) {
		this.tView = tView;
	}
	// 콜백메소드 - actionPerformed - 개발자가 직접 호출하지 못한다
	@Override
	public void run() {
		System.out.println("run호출");
		Socket socket = null;
		ObjectOutputStream oos = null;
		ObjectInputStream ois = null;
		String timeStr = null;
		try {
			socket = new Socket("localhost",5000); //172.16.2.41
			oos = new ObjectOutputStream(socket.getOutputStream());
			ois = new ObjectInputStream(socket.getInputStream());
			while(true) {
				// TimeServer에서 1초마다 getTime()호출로 알아낸 시간 정보를 oos.writeObject(getTime())하면
				// 아래에서 들을 수 있다.
				timeStr = ois.readObject().toString();
				System.out.println(timeStr);
				// 아래 코드는 TimeView에서 생성한 JLabel콤포넌트에 직접 출력하는 문장
				// NullPointerException이 발생하지 않도록 맞는 생성자를 호출하기
				System.out.println("TimeClient: " + jlbTime);
				jlbTime.setText(timeStr); // 이 부분이 학습목표. 이렇게 쓸 수 있어야 한다.
				try {
					Thread.sleep(1000);
				} catch(InterruptedException e) {
					System.out.println(e.toString());
				}
			} //////////// end of while ///////////////
		} catch (Exception e) {
			System.out.println(e.toString());
		} finally {
			try {
				ois.close();
				oos.close();
				socket.close();
			} catch(Exception e2) {
				
			}
		}
	} ///////// end of run ///////////////
	
	public static void main(String[] args) {
		TimeClient tc = new TimeClient();
		tc.start();
	}
}

<클래스 쪼개기>

package com.week3;

import java.awt.Font;

import javax.swing.JFrame;
import javax.swing.JLabel;

public class TimeView {
	// 선언부 - 선언부에서는 메소드 호출 불가함
	JFrame jf = new JFrame();
	Font font = new Font("돋움체",Font.BOLD,30);
	JLabel jlbTime = new JLabel("현재시간정보",JLabel.CENTER);
	// TimeClient tc = new TimeClient(jlbTime);
	// 실제 현재시간 정보를 청취하는 TimeClient클래스에서 TimeView
	// JLabel과 JFrame을 모두 접근할 수 있어야 하니까 this를 넘긴다
	// TimeView를 받으면 전변 모두를 다 접근할 수 있어서 그렇게 했다
	// TimeView에서 생성한 화면이지만 사용은 TimeClient에서 하겠다면
	// 생성자의 파라미터를 통해서 현재 로딩된 TimeView 전체를 넘긴다
	TimeClient tc = new TimeClient(this);
	// 생성자
	TimeView(){
	}
	public void initDisplay() {
		System.out.println("TimeClient: " + jlbTime);
		tc.start();
		jlbTime.setFont(font);
		jf.add("North",jlbTime);
		jf.setSize(700,400);
		jf.setVisible(true);
	}
	// 메인메소드
	public static void main(String[] args) {
		TimeView tv = new TimeView();
		tv.initDisplay();
	}
}

<삼항 연산자>

package com.week3;

public class ThreeOper { // 삼항연산자

	public static void main(String[] args) {
		System.out.println(10+10); // 20
		System.out.println("10"+10); // 1010
		System.out.println("10"+(10+20)); // 1030
		int hour = 7;
		String result = (hour < 10 ? "0"+hour:""+hour);
		System.out.println(result);
	}
}

<계산기 구현>

package com.week3;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class CalcView implements ActionListener{
	JFrame jf = new JFrame();
	JTextField jtf_display = new JTextField("0");
	JPanel jp = new JPanel();
	JButton jbtnOne = new JButton("1");
	JButton jbtnTwo = new JButton("2");
	JButton jbtnPlus = new JButton("+");
	JButton jbtnEqual = new JButton("=");
	JButton jbtnBack = new JButton("<=");
	JButton jbtnClear = new JButton("C");
	// 연산자(+) 누르기 전에 입력된 값 담기
	String v1 = "";
	// 연산자(=) 누르고 난 뒤에 입력된 값 담기
	String v2 = "";
	// 연산자 담기(+,-,*,/)
	String op = "";
	public void initDisplay() {
		jtf_display.setHorizontalAlignment(JTextField.RIGHT);
		//이벤트 처리를 담당하는 핸들러 클래스의 인스턴스변수를 준다.
		jbtnOne.addActionListener(this);
		jbtnTwo.addActionListener(this);
		jbtnPlus.addActionListener(this);
		jbtnEqual.addActionListener(this);
		jbtnBack.addActionListener(this);
		jbtnClear.addActionListener(this);
		jp.add(jbtnOne);
		jp.add(jbtnTwo);
		jp.add(jbtnPlus);
		jp.add(jbtnEqual);
		jp.add(jbtnBack);
		jp.add(jbtnClear);
		jf.add("North",jtf_display);
		jf.add("Center",jp);
		jf.setSize(400, 400);
		jf.setVisible(true);
	}
	public static void main(String[] args) {
		CalcView cv = new CalcView();
		cv.initDisplay();
	}
	@Override
	public void actionPerformed(ActionEvent e) {
		String command = e.getActionCommand();
		if("1".equals(command)) {//너 숫자 1 버튼 누른거야?
			// 전처리하기 - 맨 앞에 0이 있는 경우 전처리함
			if("0".equals(jtf_display.getText())) {
				jtf_display.setText("");
			}
			jtf_display.setText(jtf_display.getText()+"1");
		}
		else if("2".equals(command)) {//너 숫자 2 버튼 누른거야?
			// 전처리하기 - 맨 앞에 0이 있는 경우 전처리함
			if("0".equals(jtf_display.getText())) {
				jtf_display.setText("");
			}
			jtf_display.setText(jtf_display.getText()+"2");			
		}
		else if("+".equals(command)) {//너 + 버튼 누른거야?
			System.out.println("더하기 버튼");
			// insert here - v1 담기
			v1 = jtf_display.getText();
			System.out.println("v1 :"+v1);
			op="+";
			jtf_display.setText("");
		}
		else if("=".equals(command)) {//너 = 버튼 누른거야?
			System.out.println("계산 결과는 얼마");			
			// insert here - v2 담기
			v2 = jtf_display.getText();
			System.out.println("v1: "+v1+", v2: " + v2 + ", op: "+op);
			double d1 = Double.parseDouble(v1);
			double d2 = Double.parseDouble(v2);
			String result = String.valueOf(d1+d2);
			jtf_display.setText(result);
		}		
		else if("<=".equals(command)) {//너 = 버튼 누른거야?
			System.out.println("한글자씩 지우기 구현");		
		}		
		else if("C".equals(command)) {//너 Clear 버튼 누른거야?
			jtf_display.setText("");
		}		
	}

}

<과제-2차 배열>
출근, 퇴근버튼이 눌러도 사라지지 않고
출퇴근 버튼 눌렀을 때 현재 시간 남겨지기
col은 이름으로

package com.week3;

import java.awt.Component;
import java.util.Vector;
 
import javax.swing.AbstractCellEditor;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
 
@SuppressWarnings("serial")
public class ExTableAddBtn extends JFrame {
    
    private Object[] objColNms = new Object[] { "이름", "출근", "퇴근", "출근버튼", "퇴근버튼" };
    private Object[][] datas = null;
    public static void main(String[] args) {
        new ExTableAddBtn();
    }
 
    private JFrame jf;
    private DefaultTableModel dtm;
    private JTable jtable;
    private JScrollPane jsp;
 
    public ExTableAddBtn() {
        jf = new JFrame("JTable Add Delete Button");
        jf.setLocationRelativeTo(null);
        jf.setSize(300, 300);
        datas = new Object[][]{ 
        			{ "나신입","08:59:00","17:00:00",null,null}, 
        			{ "나일등","08:59:00","17:00:00",null,null}, 
        			{ "나초보","08:59:00","17:00:00",null,null} 
        		};
        dtm = new DefaultTableModel(datas,objColNms);
        jtable = new JTable(dtm);
        jsp = new JScrollPane(jtable);
 
        jtable.getColumnModel().getColumn(3).setCellRenderer(new TableCell());
        jtable.getColumnModel().getColumn(3).setCellEditor(new TableCell());
        jtable.getColumnModel().getColumn(4).setCellRenderer(new TableCell());
        jtable.getColumnModel().getColumn(4).setCellEditor(new TableCell());
 
        jf.add(jsp);
 
        jf.setVisible(true);
    }
 
    @SuppressWarnings("rawtypes")
    public void JTableRemoveRow() {
        int row = jtable.getSelectedRow();
        if (row == -1)
            return;
 
        DefaultTableModel model = (DefaultTableModel) jtable.getModel();
        model.removeRow(row);
 
        int rowCnt = jtable.getRowCount();
 
        if (rowCnt > 0) {
            Vector vector = model.getDataVector();
            Object[][] objData = new Object[vector.size()][((Vector) vector.get(0)).size()];
            for (int i = 0; i < vector.size(); i++) {
                Vector vec = (Vector) vector.get(i);
                for (int j = 0; j < vec.size(); j++) {
                    objData[i][j] = vec.get(j);
                }
            }
 
            DefaultTableModel clonModel = new DefaultTableModel(objData, objColNms);
            JTable clonTable = new JTable(clonModel);
 
            jf.getContentPane().removeAll();
 
            jtable = clonTable;
            jsp = new JScrollPane(jtable);
            jtable.getColumnModel().getColumn(3).setCellRenderer(new TableCell());
            jtable.getColumnModel().getColumn(3).setCellEditor(new TableCell());
            jtable.getColumnModel().getColumn(4).setCellRenderer(new TableCell());
            jtable.getColumnModel().getColumn(4).setCellEditor(new TableCell());
 
            jf.add(jsp);
            jf.revalidate();
            jf.repaint();
        } else {
            DefaultTableModel clonModel = new DefaultTableModel(null, objColNms);
            JTable clonTable = new JTable(clonModel);
 
            jf.getContentPane().removeAll();
 
            jtable = clonTable;
            jsp = new JScrollPane(jtable);
 
            jf.add(jsp);
            jf.revalidate();
            jf.repaint();
        }
    } // end public void JTableRemoveRow()
 
    class TableCell extends AbstractCellEditor implements TableCellEditor, TableCellRenderer {
        JButton jb;
 
        public TableCell() {
            jb = new JButton("출근버튼");
            jb.addActionListener(e -> { // 람다식(최신문법)
                JTableRemoveRow();
            });
        }
 
        @Override
        public Object getCellEditorValue() {
            return null;
        }
 
        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
                int row, int column) {
            return jb;
        }
 
        @Override
        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row,
                int column) {
            return jb;
        }
    } // end class TableCell extends AbstractCellEditor implements TableCellEditor,
        // TableCellRenderer
}

<인터페이스 / 추상클래스, 추상메소드>

package com.step5;
// 추상 - 미정이다. 결정되지 않았다. 아직 모르겠다.
// 인터페이스는 추상클래스보다 더 추상적이어서 오직 추상메소드만 가짐
// abstract라는 예약어를 생략할 수 있다
public interface FlyBehavior {
	// 분명히 메소드 선언인데 세미콜론으로 끝남 - 추상메소드
	public abstract void fly();
}
package com.step5;
// 추상클래스 
// 추상클래스는 추상메소드와 일반메소드 모두를 가짐
// 생성자도 가짐
// 변수선언도 가능함
// 인터페이스는 일반메소드는 못 가짐
// 추상클래스와 인터페이스의 공통점은 둘 다 반드시 구현체 클래스가 있어야 한다
// 추상클래스의 구현체일 땐 extends 사용
// 인터페이스의 구현체일 땐 implements 사용함
public abstract class Duck {
	FlyBehavior flyBehavior = null;
	public Duck() {}
	public abstract void display();
	public void performFly() {
		flyBehavior.fly();
	}
	public void swimming() {
		System.out.println("모든 오리는 물 위에 뜬다.");
	}
}
package com.step5;
// Spring 수업을 위한 사전학습 - 결합도는 낮추고 독립성을 높여서 구현하도록 
// 추상메소드 중심 인터페이스 중심의 코딩을 전개하시오
public class DuckSimulation {

	public static void main(String[] args) {
		// 인스턴스화 3가지 유형
		// 네 번째는 선언부와 생성부의 타입이 다를 수 있다 - 다형성을 위한 전제조건
		// 생성부의 이름으로 결정된다
		Duck myDuck = new RubberDuck();
		myDuck.performFly(); // 날지 못합니다
		myDuck = new MallardDuck();
		myDuck.performFly(); // 날고 있어요
	}

}

package com.step5;

public class RubberDuck extends Duck {
	public RubberDuck() {
		// 날고 있어요 - FlyWithWings.java -> implements FlyBehavior
		// 날 수 없어요 - FlyNoWay.java ->  implements FlyBehavior
		flyBehavior = new FlyNoWay(); // FlyBehavior의 구현체 클래스로 결정할 수 있음
	}
	@Override
	public void display() {
		System.out.println("나는 고무오리입니다");
	}

}

package com.step5;
// implements는 그 추상메소드를 재정의 하는 것이다.
// 메소드 선언만 되어 있으므로 오리클래스가 되기 위한 명세서의 역할
public class FlyNoWay implements FlyBehavior {

	@Override
	public void fly() {
		System.out.println("나는 날 수 없습니다.");
	}

}
package com.step5;
// 동일한 메소드를 호출했다고 하더라도 구현체 클래스에 따라서 
// 어쩔 때는 날고, 또 어떤 클래스일 땐 날지 못한다 - 이걸 가능하게 해주는 것: 다형성(폴리모피즘)
// 다형성의 전제조건=> 인스턴스화를 하는 데 있어서 선언부의 타입과 생성부의 타입이 무조건 다를 때
// List list = new ArrayList();
// list = new Vector();
// list = new LinkedList();
public class FlyWithWings implements FlyBehavior {

	@Override
	public void fly() {
		System.out.println("나는 날고 있어요^^");

	}

}
package com.step5;

public class MallardDuck extends Duck {
	MallardDuck(){
		flyBehavior = new FlyWithWings();
	}
	@Override
	public void display() {
		System.out.println("나는 청둥오리입니다");
	}

}

<야구게임>

package com.step5;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Random;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import com.step5.BaseBallGameView;
//BaseBallGameView로 가야하는 전변이 있고
//BaseBallGameLogic로 가야하는 전변이 있고
//BaseBallGameEvent로 가야하는 전변이 있다.
public class BaseBallGameView implements ActionListener {
	//선언부 - 전역변수의 성격을 가진다.- 인스턴스변수.변수명으로 어떤 클래스 에서든 사용이 가능하다.
	JFrame jf = new JFrame();
	//이미지를 담은 물리적인 위치 선언하기.
	String 		imgPath = "D:\\workspace_java\\dev_java\\src\\com\\week2\\";
//	ImageIcon 	titleIcon = new ImageIcon(imgPath+"yagu.png");
	//ImageIcon 	bg = new ImageIcon(imgPath+"dreamballpark.jpg");
	Image img = null;
	JMenuBar 	jmb 		= new JMenuBar();
	JMenu	 	jm_game 	= new JMenu("게임");
	JMenuItem   jmi_new 	= new JMenuItem("새게임");
	JMenuItem   jmi_dap 	= new JMenuItem("정답");
	JMenuItem   jmi_clear 	= new JMenuItem("지우기");
	JMenuItem   jmi_exit 	= new JMenuItem("나가기");
	JMenu	 	jm_info 	= new JMenu("도움말");
	JMenuItem   jmi_detail 	= new JMenuItem("야구숫자게임이란?");
	JMenuItem   jmi_create 	= new JMenuItem("만든사람들");
	//중앙에 들어갈 속지 선언
	JPanel jp_center = new JPanel();
	//세자리 숫자를 입력 후 엔터를 쳤을때 사용자가 입력한 숫자와 숫자를 맞추기 위한 힌트문
	//을 출력해줄 화면.
	JTextArea jta_display = null;
	JScrollPane jsp_display = new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
	JTextField jtf_user   = new JTextField();
	//글꼴과 글꼴에 대한 스타일과 글자 크기를 정해줌.-인스턴스화를 통해서, 그 값들은 생성자의 파라미터로 결정됨
	Font f = new Font("Thoma",Font.BOLD,14);
	//동쪽에 들어갈 속지 생성하기
	JPanel jp_east   = new JPanel();
	//새게임, 정답, 지우기, 나가기 버튼 추가하기
	JButton jbtn_new 	= new JButton("새게임");
	JButton jbtn_dap 	= new JButton("정답");
	JButton jbtn_clear 	= new JButton("지우기");
	JButton jbtn_exit 	= new JButton("나가기");
	int my[]  = new int[3];
	int com[] = new int[3];//세자리 임으의 숫자를 담을 1차배열 선언 - BaseballGameLogic으로 보내야하는지? 아님 BaseballGameEvent에 있어야 하는지 기준 - 시야 -소스리뷰
	int cnt = 1;//++cnt 힌트 문장에서 순번을 출력하는 변수	- 야구 회차를 나타내는 전역변수로 한다.그 게임이 유지되는 동안에는  변해야 한다.
	//새게임이 시작(새게임을 알리는 메소드가 호출됨 -새게임일때 초기화 해야하는 변수가 반드시 존재함)되면 다시 0으로 초기화 해야한다.
	//생성자
	
	//사용자정의 메소드
	
	//세자리 임의의 숫자를 채번하는 메소드 구현하기
	public void ranCom() {
		Random r = new Random();
		// 첫 번째 자리는 중복검사가 필요없다
		com[0]=r.nextInt(10);
		// while문과는 다르게 무조건 한 번은 실행됨
		do {
			com[1]=r.nextInt(10);
		} while(com[0]==com[1]); // 중복된 숫자면 계속 돌아라
	
		do {
			com[1]=r.nextInt(10);
		} while((com[0]==com[2])||(com[2]==com[1])); // 중복된 숫자면 계속 돌아라
		}
	//사용자가 입력한 값을 판정하는 메소드를 구현해 봅시다.
	public String account(String user) {
		if(user.length()!=3) {
			return "세자리 숫자를 입력하세요.";
		}
		//사용자가 jtf_user에 입력한 숫자는 보기에는 숫자 처럼 보여도 알맹이는 문자열로 
		//인식을 합니다. 그래서 형전환을 한 후 my[]배열에 담아야 함니다.
		//문자열 "256"을 숫자로 담을 변수 선언
		int temp 	= 0;
		int strike 	= 0;//힌트로 사용될 스트라이크를 담을 변수 선언
		int ball 	= 0;//볼을 담을 변수 선언
		//strike와ball을 지역변수로 해야 하는건 매 회차 마다 값이 변해야 하기 때문이다.
		try {
			temp = Integer.parseInt(user);
		} catch (NumberFormatException e) {
			return "숫자만 입력하세요.";
		}
		return strike+"스  "+ball+"볼";
	}
	
	// 나가기 버튼이나 나가기 메뉴 아이템을 선택(클릭)했을때 호출되는 메소드 구현
	public void exit() {
		System.exit(0);
	}	
	
	//여기에 화면을 그리는 메소드 입양
	//화면을 그려주는 메소드 선언
	public void initDisplay() {
		jf.addWindowListener(new WindowAdapter() {
			public void windowOpened(WindowEvent we) {
				jtf_user.requestFocus();
			}
		});
		jta_display = new JTextArea();
		jta_display.setEditable(false);
		jsp_display = new JScrollPane(jta_display);
		jta_display.setOpaque(false);
		jf.setResizable(false);
		//jf.setContentPane(new BgPanel());
		//////////////// 툴바에 들어갈 이미지 버튼 추가하기 ///////////////
		//////////////// 메뉴 바 추가 시작 /////////////////
		jm_game.add(jmi_new);
		jm_game.add(jmi_dap);
		jm_game.add(jmi_clear);
		jm_game.add(jmi_exit);
		jm_info.add(jmi_detail);
		jm_info.add(jmi_create);
		jmb.add(jm_game);
		jmb.add(jm_info);
		//////////////// 메뉴 바 추가  끝   /////////////////
		System.out.println("initDisplay 호출 성공");
		//이벤트 소스와 이벤트 처리 클래스를 매핑하는 코드 추가
		//EventHandler ehandler = new EventHandler();
		//jtf_user.addActionListener(ehandler);//여기서 this는 자기자신 클래스를 가리킴.-BaseBallGame:내안에 actionPerformed
		jtf_user.addActionListener(this);//여기서 this는 자기자신 클래스를 가리킴.-BaseBallGame:내안에 actionPerformed
		jbtn_new.addActionListener(this);
		jbtn_dap.addActionListener(this);
		jbtn_clear.addActionListener(this);
		jbtn_exit.addActionListener(this);
		jmi_exit.addActionListener(this);
		jbtn_new.setBackground(new Color(158,9,9));
		jbtn_new.setForeground(new Color(212,212,212));
		jbtn_dap.setBackground(new Color(7,84,170));
		jbtn_dap.setForeground(new Color(212,212,212));
		jbtn_clear.setBackground(new Color(19,99,57));
		jbtn_clear.setForeground(new Color(212,212,212));
		jbtn_exit.setBackground(new Color(54,54,54));
		jbtn_exit.setForeground(new Color(212,212,212));
		jp_east.setLayout(new GridLayout(4,1));
		jp_east.add(jbtn_new);
		jp_east.add(jbtn_dap);
		jp_east.add(jbtn_clear);
		jp_east.add(jbtn_exit);
		jta_display.setFont(f);
		jta_display.setBackground(new Color(255,255,200));
		jta_display.setForeground(new Color(57,109,165));

		jf.setJMenuBar(jmb);
		jtf_user.setBackground(new Color(255,255,200));
		jp_center.setBackground(Color.green);
		jp_east.setBackground(Color.black);
		jp_center.setLayout(new BorderLayout(0,10));
		jp_center.add("Center",jsp_display);
		jp_center.add("South",jtf_user);
		jta_display.setLineWrap(true);
		jf.setLayout(new BorderLayout(10,20));
		jf.add("Center",jp_center);
		jf.add("East",jp_east);
		jf.setTitle("야구 숫자 게임 Ver1.0");
		jf.setSize(400, 300);
		jf.setVisible(true);
	}	
	
	//@는 annotation 이라고 읽는다. - 
	//부모가 정의한 메소드를 재정의하는것-실제 그 장치에 필요한 기능을 구현하시오.
	//부모(추상클래스-추상은 결정되지않음)가 정의할 수 없으니(서로 다른 장치라서)...
	//나를 구현하는 클래스 마다 그 기능에 차이가 있을테니 그 클래스에서 오버라이딩 하시오.
	//단 부모의 메소드를 훼손해서는 안됨
	//actionPerformed도 개발자가 직접 호출하는 메소드가 아니다
	//그럼 언제 누가 왜 호출하는 걸까요? - 콜백함수(javascript), 콜백메소드(자바)
	//누가? JVM이
	//언제? 버튼을 눌렀을 때 혹은 JTextField에서 엔터를 쳤을 때를 JVM이 감지(H/W-키보드-입력장치)해 내고
	//그 때 인터셉트(끼어들어서) 해서 필요한 처리를 개발자가 해낸다 - dependency injection(Spring F/W)
	@Override
	public void actionPerformed(ActionEvent e) {//파라미터자리에 ActionEvent 객체는 JVM에서 이벤트가 감지되었을때 대신 주입해줌
		System.out.println("actionPerformed 호출 성공");
		String label = e.getActionCommand(); // 감지된 클래스의 라벨 담기
		System.out.println("너가 누른 버튼의 문자열은 "+label+ " 입니다.");
		Object obj = e.getSource();//이벤트소스의 주소번지를담아줌.
		System.out.println(obj);
		if("지우기".equals(label)) {
			jta_display.setText("");
		}
		// 너 나가기 버튼이니?
		// |(하나)만 있을 땐 앞에 조건이 true면 실행문이 결정되었지만 뒤에 조건을 따짐
		// ||(두 개)만 있을 땐 앞에 조건이 true면 뒤에 조건이 false여도 어차피 실행됨 - 뒤에 조건을 안 따짐 - 일량이 줄어듦
		else if("나가기".equals(label)||obj==jmi_exit) { // or이니까 둘 중 하나만 true여도 호출된다
			exit(); // 사용자 정의 메소드 호출이다.
		} 
		//새게임을 누른거야?
		else if(obj == jbtn_new) {

		}
		//이벤트가 발생한 이벤트 소스의 문자열을 비교하기
		else if(e.getSource()==jtf_user) {
			//엔터이벤트가 적용되었을 때 후처리로 JTextField에 문자열을 빈문자열로 교체함
			//JTextArea가 선언부에서는 null이었지만 화면을 그리는 initDisplay()에서 인스턴스화를 마(생성)쳤으므로
			//NullPointerException이 발생하지 않았다. - UI통해서 테스트 할때 관전포인트
			//jta_display.setText("문자열");
			//숫자를 입력하고 엔터를 쳤을때 JVM이 actionPerfored를 호출하는 거니까 내부에서 출력해 볼 수 있다.
			System.out.println("엔터쳤을 때 : "+jtf_user.getText());
			//재사용성을 위해서 메소드 호출할수 있도록 연습- 메소드로 이관했을때 동일한 효과
			jta_display.append(cnt +"회 : "+jtf_user.getText()+"\n");
			cnt = cnt + 1;
			jtf_user.setText("");
		}///////////입력하고 엔터 쳤을 때
		else if(obj==jmi_dap||"정답".equals(label)) {
			// 1-먼저 채번(동사-기능-메소드 호출)하고 그 다음에 com배열에 있는 값을 출력해 준다.
			ranCom();
			jta_display.append("정답은 "+com[0]+com[1]+com[2]+"입니다.\n");
			// jta_display.append(com[0]+com[1]+com[2]); // 0
		}
	}//end of actionPerformed
	//메인메소드 - 최소한의 코드만 작성하도록 연습할것
	public static void main(String[] args) {
		BaseBallGameView bbGame = new BaseBallGameView();
		bbGame.initDisplay();		
	}

}

0개의 댓글