<시간 출력하기>
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();
}
}