U E D R , A S I H C RSS

한자공/시즌3/20140804


1. 일시


8월 4일 13시 05분 ~ 14시 45분

2. 참가자

유재범 참석
이지수 참석
김용준 참석
김정민 참석

3. 진행 상황

  • Frame, 레이블, 레이아웃과 AWT 컴포넌트
    • 자바 입출력을 하려 했으나 발표자의 하드 트롤링으로 발표내용 급 변경
    • 김용준의 폭주로 예상치 못한 AWT 컴포넌트의 발표. 고통스럽다.

3.1. 발표 내용


  • 핵심 : GUI의 기본 구성
    • 자바 GUI의 기초인 Frame 클래스와 레이아웃 매니저에 대해 다룸

  • 자바 폼의 패키지들
    • 요약을 해보자

      ①pacakge1
      java.applet : 웹 페이지에 삽입되는 작은 애플리케이션인 애플릿을 지원하기 위한 API. 원칙적으로 애플리케이션과 시스템과의 인터페이스이나 그 자체가 웹 페이지 상의 그래픽 영역을 나타내므로 UI 컴포넌트 형태로 정의되어 있다.
      java.awt : 기본적인 2D 그래픽(자바 2D) 및 하부 윈도 시스템 컴포넌트를 감싼 무거운 컴포넌트(영어: heavyweight component)를 담고 있다.
      java.awt.color, java.awt.font, java.awt.geom : 색 공간(영어: color space) 및 프로파일, 벡터 그래픽 연산, 글꼴 등 자바2D의 일부가 되는 API를 담고 있다.
      java.awt.datatransfer, java.awt.dnd : 드래그 앤 드롭과 클립보드 관련 API를 정의하고 있다.
      java.awt.event : 키, 마우스 등 입력과 하부 윈도 시스템과의 통신을 위한 이벤트 및 리스너 인터페이스 정의를 담고 있다.
      java.awt.im, java.awt.im.spi : 다국어 입력을 위해 하부 윈도 시스템에서 제공하는 입력 방법과 인터페이스를 할 수 있게 하고 자바로 입력 방법을 작성할 수 있게 한다.
      java.awt.image, java.awt.image.renderable : 이미지 처리 및 입출력 기능을 제공한다.
      java.awt.print : 프린팅을 위한 기능을 제공한다
      
      ②pacakge2
      javax.swing : 스윙 컴포넌트들과 그에 딸린 모델(데이터 혹은 상태) 및 기타 API를 정의한다.
      javax.swing.border : 컴포넌트 테두리 관련 API들을 정의한다.
      javax.swing.event : 스윙 컴포넌트에서 사용되는 이벤트 객체 및 리스너 인터페이스를 정의한다.
      javax.swing.colorchooser, javax.swing.filechooser, javax.swing.table : 색 선택, 파일 선택 대화 상자, 테이블 등 복잡한 컴포넌트에 딸린 API를 정의하고 있다.
      javax.swing.plaf, javax.swing.plaf.basic, javax.swing.plaf.metal, javax.swing.plaf.multi : javax.swing에 정의된 컴포넌트들에 대해 룩앤필(look & feel)을 교체하기 위한 규약을 정의하고 있으며, basic, metal, synth, multi 등의 부 패키지에는 각각 서로 다른 룩앤필을 구현이 포함되어 있다. API가 공개된 룩앤필은 다른 룩앤필을 만드는데 활용하도록 만들어졌기 때문이다.
      javax.swing.text, javax.swing.text.html, javax.swing.text.html.parser, javax.swing.text.rtf : 텍스트 컴포넌트를 위한 API를 정의하고 있으며 부 패키지들에서는 HTML, RTF 같은 파일 형식을 읽거나 편집하기 위한 구현이 포함되어 있다.
      javax.swing.tree
      javax.swing.undo : Undo 지원을 위한 API를 정의하고 있다. 
      
      ③package3
      java.lang : 자바 언어와 관련된 핵심 API. String이 이 패키지에 속한다.
      java.sql : JDBC(Java DataBase Connectivity) 관련 API로 관계형 데이터베이스에 접속해서 질의를 던지고 결과를 받을 수 있게 지원한다.
      java.text : 문자열 및 날짜, 숫자 등을 포맷팅 할 수 있도록 지원하는 API
      java.util : 리스트, 맵 등 콜렉션 API와 기타 유용한 편의 API
      javax.print, javax.print.attribute, javax.print.attribute.standard, javax.print.event : 
      javax.sound.midi, javax.sound.midi.spi, javax.sound.sampled, javax.sound.sampled.sip : 
      javax.sql : 
      
    • java와 javax의 차이는 무엇인가?
      • swing 초기 개발 목적이 자바 1.1과 1.2 모두 실행 되는 것이었다. 그래서 자바 1.1에서는 선택적 라이브러리로, 자바 1.2에는 기본으로 들어가는데 문제는 java로 시작하는 패키지 이름은 다운로드된 코드에서는 쓸 수 없어서 javax로 이름 붙였다고 한다.
    • 출처 : http://ko.wikipedia.org/wiki/%EC%9E%90%EB%B0%94_%ED%94%8C%EB%9E%AB%ED%8F%BC,_%EC%8A%A4%ED%83%A0%EB%8D%94%EB%93%9C_%EC%97%90%EB%94%94%EC%85%98
    • 이 중 패키지 1은 AWT를 사용할 때 필요한 패키지들이다. 이 책에서는 java.applet, java.awt, java.awt.event 정도만 사용할 예정이다.
    • 패키지 2는 JFC를 사용 할 때 쓰는 패키지들로 대부분의 패키지를 사용할 줄 알아야 한다. (책에서 기대하라고 선전포고를 하고 있다.)
    • 패키지3은 부수적인 것들이다. java.sql, javax.sql은 데이터베이스를 위한 패키지들이고 나머지도 간간히 사용한다.

  • AWT 프레임과 레이블
    • 프레임 : form 어플리케이션의 작업대

package hanjagong_part3;
import java.awt.*;
public class Round17_Ex01 {
	public static void main(String[] ar){
		Frame f = new Frame();
		//f.show(true);
		//f.setVisible(true);
	}
}
  • 위 코드는 프레임을 출력하는 코드이다. 하지만 막상 실행을 시켜보면 아무것도 나오지 않는다.
    • 사용자에게 보여줘야 할지 말지에 대한 설정이 false(보여주지 않는 것)으로 되어 있기 때문이다.
      • 이를 출력하는 메소드는 java.awt.Component의 show() (혹은 show(boolean))이다.
  • 위 코드를 보면 show가 가로 줄이 쳐져 있는 것을 볼 수 있다
    • 간단히 말해 소멸 되었다는 것이다. JDK 1.1 이후에는 setVisible(boolean)이라는 메서드 대신 사용 된다.

  • 화면 크기 조절 메소드 : java.awt.Component의 setSize(int width, int height). 단위는 픽셀
    • 그 외 적정한 크기를 할당하도록 하는 메소드로 JVM의 pack()이 있다.
  • 화면 위치 조절 메소드 : java.awt.Component의 setLocatino(int x, int y)

화면과 프레임의 크기
1. 화면의 크기
Dimension dimen = Toolkit.getDefaultToolkin().getScreenSize();
2. 프레임의 크기
Dimension dimen1 = f.getSize();
  • Dimension 클래스 : 특정한 사각형 영역을 관리하기에 편리하도록 만들어진 클래스
    • 화면의 폭과 높이를 얻어내려면 이 클래스 안의 getWidth()와 getHeight()를 사용하면 된다.
    • 자고로 좌표의 중심은 왼쪽 상층이다.
  • 제목 설정 방법은 두가지가 있다.
    • 첫번째. Frame f = new Frame("제목부분");
    • 두번째. f.setTitle("제목변경"); (java.awt.Frame 안에 있는 메소드 setTitle(String title)을 사용)

1. 작업 영역을 분할하는데 필요한 클래스와 메서드
 - LayoutManager 클래스
 - jav.awt.Container 클래스의 setLayout(LayoutManager mgr)
2. 해당 작업 영역에 올려질 Component 클래스
3. 해당 Component 클래스를 작업 영역에 올릴 메서드
 - java.awt.Container 클래스의 add(Component cmp), add(Component cmp, int pos), add(String posname, Component cmp)
4. Layout 설정이 null일 경우 위치를 지정해 주는 메서드
 - java.awt.Component 클래스의 setBounds(int x, int y, int width, int height), setBounds(Rectangle rec)

  • Frame과 상위 클래스의 멤버들
    • java.awt.Component
      • Fields
필드 속성 필드명 내용
static final float CENTER_ALIGNMENT Component의 위치 지정에 사용되는 멤버필드(중앙, 상, 하, 좌, 우 방향)
static final float TOP_ALIGNMENT
static final float BOTTOM_ALIGNMENT
static final float LEFT_ALIGNMENT
static final float RIGHT_ALIGNMENT

  • methods
Return_type method 내용
Color getBackground() Component의 배경 색상
Rectangle getBounds() Component의 위치와 크기
Component getComponentAt(int x, int y) x와 y 위치의 Component
Cursor getCursor() Component에 적용된 커서
Font getFont() Component의 폰트
Color getForeground() Component의 글자 색상
int getheight() Component의 높이
Point getLocation() Component의 위치
Dimension getMaximumSize() Component의 최대 크기
Dimension getMininumSize() Component의 최소 크기
String getName() Component 이름
Container getParent() Component를 포함한 Container
Dimension getPreferredSize() Component의 적정 크기
Dimension getSize() Component의 크기
int getWidth() Component의 넓이
int getX() Component의 x축 위치
int getY() Component의 y축 위치
boolean hasFocus() Focus가 위치해 있는지를 확인
Void invalidate() Component를 갱신하지 않음
boolean isEnabled 활성화 되었는지를 판단
Void requestFocus() 커서를 위치시킴
Void setBackground(Color c) 배경 색상을 c로 설정
Void setBounds(int x, int y, int w, int h) 위치와 크기를 x, y, w, h로 설정
Void setBounds(Rectangle rec) 위치와 크기를 rec로 설정
Void setCursor(Cursor cur) 커서의 형태를 cur로 설정
Void setEnabled(boolean bool) 활성화를 true/false로 설정
Void setFont(Font f) 폰트를 f로 설정
Void setForeground(Color c) 글자 색상을 c로 설정
Void setLocation(int x, int y) 위치를 x, y로 설정
Void setLocation(Point p) 위치를 p로 설정
Void setName(String name) 이름을 name로 설정
Void setSize(Dimension dimen) 크기를 dimen으로 설정
Void setSize(int width, int height) 크기를 width와 height로 설정
Void setVisible(boolean bool) Display를 true/false로 설정
String toString() Component의 고유 이름
Void validate() Component를 갱신함

  • java.awt.Container
    • methods
Return_type Method 내용
Component add(Component comp) Component 추가
Component add(Component comp, int index) Component를 특정 위치에 추가
Component add(String name, Component comp) Component를 특정 이름에 추가
Component getComponent(int index) 특정 위치의 Component 얻기
int getComponentCount() Component의 개수
Component getComponents() 모든 Component 얻기
LayoutManager getLayout() 적용된 LayoutManager 얻기
Void remove(Component comp) Component 제거
Void remove(int index) 특정 위치의 Component 제거
Void removeAll() 모든 Component 제거
Void setLayout(LayoutManager mgr) LayoutManager 설정
  • 오버라이딩 된 메서드는 제외

  • jav.awt.Window
    • Constructs
Construct 내용
Window(Frame owner) 특정 Frame에 소속된 Window
Window(Window owner) 특정 Window에 소속된 Window
  • methods
Return_type Method 내용
void dispose() Window를 소멸시킨다.
Component getFocusOwner() 현재 Focus된 Component를 리턴
Window getOwner() 현재 Window가 포함된 Window
void hide() Window를 숨긴다
boolean isActive() Window가 활성화 상태인지를 확인
boolean isFocused() Window에 Focus가 있는지 확인
void pack() JVM이 적정 크기의 Window를 판단
void show() Window를 보여준다
void toBack() 현재 Window를 뒤로 숨긴다
void toFront() 현재 Window를 앞으로 보여준다

  • java.awt.Frame
    • Fields
필드 속성 필드명 내용
static final int ICONIFIED Frame의 아이콘화된 상태 피트를 표시
static final int MAXIMIZED_BOTH Frame의 최대 크기에 관한 상태 비트
static final int MAXIMIZED_HORIZ Frame의 가로축 최대 크기 비트
static final int MAXIMIZED_VERT Frame의 세로축 최대 크기 비트
static final int NORMAL 기본 크기를 표시하는 상태 비트

  • Constructs
Construct 내용
Frame() 기본 Frame 생성자
Frame(String title) Title을 지정하는 생성자

  • Methods
Return_Type Method 내용
satic Frame getFrames() 실행중인 모든 Frame을 얻기
Image getIconImage() Frame의 좌측 상단 이미지 얻기
Menubar getMenuBar() 설정된 MenuBar 객체 얻기
int getState() Frame의 현 상태 얻기
String getTitle() 현 Frame의 title 얻기
Boolean isResizable() 현 Frame의 크기 변경 가능 유무 확인
void setIconImage(Image img) 좌측 상단의 이미지 변경하여 설정
void setMenuBar(MenuBar mb) MenuBar를 설정
void setResizable(boolean bool) Frame 크기 변경 가능 유무 설정
void setState(int state) Frame의 상태 설정
void setTitle(String title) Frame의 title 설정

  • AWT 레이아웃 메니저
    • java.awt.Container 클래스의 setLayout(LayoutManager mgr)메서드를 사용해서 적용
    • FlowLayout Manager : 컴포넌트를 프레임상에 원래의 크기대로 차례로 배치하는 레이아웃 매니저
      • 생성자 : FlowLayout(), FlowLayout(int pos) // pos = CENTER, LEFT, RIGHT
    • GridLayoutManager : 프레임을 그리드로 나누어 컴포넌트를 차례대로 배치하는 레이아웃 매니저
      • 생성자 : GridLayout(int x, int y), GridLayout(int x, int y, int xgap, int ygap)
      • 행과 열로 구분해주는 생성자가 존재
      • FlowLayout과 마찬가지로 add(Component comp)를 사용. 하지만 컴포넌트의 크기가 프레임의 크기와 행, 열의 갯수에 영향을 받는다.
    • BorderLayout Manager : 프레임을 5개 방향(동서남북과 중앙)으로 나누어 컴포넌트를 특정 방향으로 배치하는 레이아웃 매니저
      • 생성자 : BorderLayout(), BorderLayout(int xgap, int ygap)
      • "BorderLayout.멤버_필드" 에서 멤버필드는 모두 대문자, add(component comp)에 들어가는 방향은 첫글자만 대문자이다.
      • this.add(); 두개를 or로 묶어서 대각선 방향도 설정 할 수 있다.
      • 다른 자리가 채워져 있지 않으면 Center의 컴포넌트가 그 자리를 매우게 된다.
  • CardLayout Manager : 프레임에 카드를 엎어 놓은 듯이 여러개의 Container를 상속받은 Panel 같은 객체를 포개 놓은듯한 배치의 레이아웃 매니저 (마치 슬라이드 배경색 바뀌듯)
    • 생성자 : CardLayout(), CardLayout(int hgap, int vgap)
      • 원하는 카드를 불러낼 때에는 show() 메서드로 원하는 위치에 원하는 카드를 식별자로 부른다.
      • CardLayout으로 여백 조정 가능
  • GridBagLayout Manager : 프레임의 좌측 상단을 기준으로 폭과 크기를 정하여 컴포넌트를 배치하는 고차원의 레이아웃 매니저
    • 생성자 : GridBagLayout()
    • 관련 클래스 생성자 : GridBagConstraints(), GridBagConstraints(int gridx, int gridy, int gridwidth, int gridheight, int weightx, int weighty, int anchor, int fill, int insets, int ipadxm int ipady)

gridx, gridy : 컴포넌트의 x, y의 위치
gridwidth, gridheight : 컴포넌트의 default 크기에 대한 폭과 높이의 소속 배율
weightx, weighty : 컴포넌트 각 영역의 크기 비율
anchor : 영역 내부에서의 컴포넌트 위치(CENTER, NORTH, SOUTH, WEST, EAST, NORTHWEST, NORTHEAST, SOUTHWEST,SOUTHEAST)
fill : 영역을 채우기 위한 속성 지정(NONE, BOTH, VERTICAL, HORIZONTAL) 
insets : 컴포넌트의 영역 내부에서의 여백
ipadx, ipady : 컴포넌트의 크기 추가


4. 다음 진행

5. 과제

  • 계산기 gui 만들기
    • 필요하다면 아래 있는 Base를 이용해서 만들 것.

  • Base

import java.util.Scanner;

public class base {
	public static void main(String [] args){
		Scanner scan = new Scanner(System.in);
		String input;
		
		System.out.println("x ? y or exit");
		while( true )
		{
			System.out.print("Calculate : "); 
			input = scan.nextLine();
			if(input.equals("exit")) break;
			Calculation(input);
		}		
		scan.close();
	}
	
	static void Calculation(String input){
		int x = 0, y = 0;
		String[] tmp = input.split(" ");

		try {
			x = Integer.parseInt(tmp[0]);
			y = Integer.parseInt(tmp[2]);
		} 
		catch (NumberFormatException e) {
			System.out.println("Insert only a number!");
			return;
		} catch (ArrayIndexOutOfBoundsException e) {
			System.out.println("Insert only this form!(x ? y)");
			return;
		} 
		
		switch(tmp[1])
		{
			case "+": System.out.println(x+y); break;
			case "-": System.out.println(x-y); break;
			case "*": System.out.println(x*y); break;
			case "/":
				try{
					System.out.println(x/y);
				} catch (ArithmeticException e){
					System.out.println("Don't divide by 0!");
					return;
				}
				break;
		}
	}
}

5.1. 유재범

5.2. 이지수

5.3. 김용준

package Calculator_140728;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import Calculator_140728.base;


public class gui_v1 {
	public static void main( String [] args){
		 new Calculator("계산기");
	}
}


class Calculator extends JFrame{
	String[] strOpt = { "/", "*", "-", "+", "C", "="};
	String strFm = ""; //수식라벨을 위한 스트링
	String strTf = ""; //텍스트 필드를 위한 스트링
	String strCal = ""; //계산을 위한 스트링
	String result = "0"; //결과값을 위한 스트링
	
	//=을 위한 변수
	Boolean countE = false;// 연속 = 기능 비활성화
	int tmpE; 
	String strE;
	//연속 연산을 위한 변수
	Boolean countO = false;// 연속 연산 기능 비활성화
	Boolean countP = false;// 연산자 변경
	String tmpO;//이전 입력받은 수

	
	JButton[] num = new JButton[10];
	JButton[] opt = new JButton[strOpt.length];

	JLabel fm = new JLabel(); //현재 계산식 보는 라벨
	JTextField tf = new JTextField("0");//숫자와 연산
	
	JPanel see = new JPanel();
	JPanel input_num = new JPanel();
	JPanel input_opt = new JPanel();
	
	private void compose() {
		Container container = this.getContentPane();
		
		container.setLayout(new BorderLayout(4,7));

		//연산자
		input_opt.setLayout(new GridLayout(4,1,10,10));
		for(int i = 0; i < opt.length; i++)
		{
			opt[i] = new JButton(strOpt[i]);
			opt[i].setFont(new Font("굴림", Font.BOLD, 15));
			if(i < 4) input_opt.add(opt[i]);
		}
		container.add("East",input_opt);
		
		//라벨과 텍스트박스
		see.setLayout(new GridLayout(2,1,0,2));
		see.add(fm);
		see.add(tf);
		fm.setFont(new Font("굴림", 0, 12));
		tf.setFont(new Font("굴림", Font.BOLD, 21));
		container.add("North",see);
		
		//숫자 부분
		input_num.setLayout(new GridLayout(4,3,3,10));
		for(int i = 0 ; i <= 9 ; i++)
		{
			num[i] = new JButton(Integer.toString(i));
			num[i].setFont(new Font("굴림", Font.BOLD, 19));
		}
		for(int i = 2 ; i >= 0 ; i--)
			for(int j = 1 ; j <= 3 ; j++) input_num.add(num[3*i+j]);
		input_num.add(num[0]);
		input_num.add(opt[4]);
		input_num.add(opt[5]);
		container.add("Center",input_num);
		
	}
	
	public Insets getInsets()
	{//여백을 주기 위한 메소드 오보라이딩
		Insets i = new Insets(30,15,15,15);
		return i;
	}
	
	private void setevent() {
		for(JButton e : num) e.addActionListener(new MyAction());
		for(JButton e : opt) e.addActionListener(new MyAction());
	}
	
	
	class MyAction implements ActionListener{

		@Override
		public void actionPerformed(ActionEvent e) {
			Object who = e.getSource();
			
			for(int i = 0; i < num.length; i++){
				if(who == num[i]){
					strTf += i;
					tf.setText(strTf);
					countE = false;// 연속 = 기능 비활성화
					countP = false;// 연산자 변경 비활성화
				}
			}
			
			for(int i = 0; i< opt.length; i++)
				if(who == opt[i]) operation(i);
			
		}
		private void operation(int nowOpt){
			switch(nowOpt)
			{
			default: // 연산자들 기능 구현
				if (tf.getText().equals("0"))
				{// 초기 0값
					strFm = "0 "+strOpt[nowOpt]+" ";
					fm.setText(strFm);
				} 
				else if(tf.getText().equals(result) && countP)
				{// 이전 값과 같을 때 연산자 변경
							try{
							strFm = fm.getText().substring(0, fm.getText().length()-2) + strOpt[nowOpt]+ " ";
							} catch (StringIndexOutOfBoundsException e) 
							{// =을 한 후 연산 결과에서 다시 연산할 때
								strFm = tf.getText() + " " + strOpt[nowOpt] + " ";
								strTf = "";
							}
							fm.setText(strFm);
				}
				else 
				{// 연산
					tmpO = tf.getText();
					if(countO){// 연속 연산 
						strCal = result + strFm.substring(strFm.length()-3,strFm.length()) + tf.getText();
						result = base.Calculation(strCal);
						tf.setText(result);
						countP = true;
					}
					else {// 첫 연산
						countO = true;// 연속 연산 기능 활성화
						result = tf.getText();
					}
					strFm += tmpO + " " + strOpt[nowOpt] + " ";
					
					fm.setText(strFm);
					strTf = "";//처음 버튼 입력을 받기 위한 텍스트 필드 초기화
				}	
				break;
				
			
			case 4: // C 기능 구현
				strFm = "";
				strTf = "";
				result = "0";
				countE = false;// 연속 = 기능 비활성화
				countO = false;// 연속 연산 기능 비활성화
				countP = false;// 연산자 변경 비활성화
				fm.setText(strFm);
				tf.setText("0");
				break;
				
				
			case 5:// = 기능 구현
				if(countE){// 연속 = 기능
					strCal = result + strE + tmpE;
					result = base.Calculation(strCal);
				} else {// 일반 = 기능
					try{
					tmpE = Integer.parseInt(tf.getText());//마지막 연산한 숫자
					strE = strFm.substring(strFm.length()-3,strFm.length());//마지막 연산자
					
					if(strFm.length() == 4) strCal = strFm + tf.getText();// 단순 수식 인 경우
					else strCal = result + strFm.substring(strFm.length()-3,strFm.length()) + tmpE;//복합 수식인경우
					
					result = base.Calculation(strCal);
					
					countE = true;// 연속 = 기능 활성화 
					countO = false;// 연속 연산  기능 비활성화
					countP = false;// 연산자 변경 비활성화
					
					} catch (StringIndexOutOfBoundsException e) 
					{//아무런 연산하지 않고 숫자 = 했을때 예외처리
						result = tf.getText();
						strTf = "";
					}
				}
				strFm = "";//수식라벨 리셋
				
				fm.setText(strFm);
				tf.setText(result);
		}
		
	}
		
		
	}
	public Calculator (String title){
		super.setVisible(true);
		super.setTitle(title);
		super.setSize(218,313);
		super.setResizable(false);
		
		//화면 중앙 배치
		Dimension d = super.getToolkit().getScreenSize();
		super.setLocation(d.width/2 - super.getWidth()/2, d.height/2 - super.getHeight()/2);
		
		//종료
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		this.compose();
		this.setevent();
	}
}

5.4. 김정민

//다들 열심히 하는 모습이 보기 좋네요 굳굳
//네?

6. 후기

  • 이상한 과제에 고통 받는 동기들의 원한이 들리지 않느냐!!!
  • 하드 트롤링 - 유재범
  • 물론 안하셔도 됩니다. - 김용준
    • AWT 컴포넌트 설명 했는데 그것도 정리해서 올려줘 - 유재범
  • 아 과제하는거 구경할라했는데 소스를 걍 복붙해놔서 보기도 힘들고 실행시켜보기도 귀찮네... 님들 github안쓰세요?????
    • 방학 중에는 아마 쓰는 일이 없을까 싶기도 합니다만... 8월 말에 다인 선배한테 쓰는 법 배우고 그 후에도 스터디가 살아 있다면 아마 그 때부터 쓰지 않을까 싶어요. 솔직히 개인적으로 이정도 양의 과제가 나올 줄 예상 못했습니다 - 유재범


Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2021-02-07 05:31:31
Processing time 0.0666 sec