Difference between r1.1 and the current
@@ -1 +1,556 @@
[[TableOfContents]]
== 일시 ==
8월 4일 13시 05분 ~ 14시 45분
== 참가자 ==
|| 유재범 || 참석 ||
|| 이지수 || 참석 ||
|| 김용준 || 참석 ||
|| 김정민 || 참석 ||
== 진행 상황 ==
* Frame, 레이블, 레이아웃과 AWT 컴포넌트
* 자바 입출력을 하려 했으나 발표자의 하드 트롤링으로 발표내용 급 변경
* [김용준]의 폭주로 예상치 못한 AWT 컴포넌트의 발표. ~~고통스럽다.~~
=== 발표 내용 ===
* 핵심 : 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 ||<|5> 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 : 컴포넌트의 크기 추가
}}}
== 다음 진행 ==
* [김용준] 학우의 File I/O
== 과제 ==
* 계산기 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;
}
}
}
}}}
=== 유재범 ===
{{{
}}}
=== 이지수 ===
{{{
}}}
=== 김용준 ===
{{{
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();
}
}
}}}
=== 김정민 ===
{{{
//다들 열심히 하는 모습이 보기 좋네요 굳굳
//네?
}}}
== 후기 ==
* 이상한 과제에 고통 받는 동기들의 원한이 들리지 않느냐!!!
* 하드 트롤링 - [유재범]
* 물론 안하셔도 됩니다. - [김용준]
* AWT 컴포넌트 설명 했는데 그것도 정리해서 올려줘 - [유재범]
* 아 과제하는거 구경할라했는데 소스를 걍 복붙해놔서 보기도 힘들고 실행시켜보기도 귀찮네... 님들 github안쓰세요?????
* 방학 중에는 아마 쓰는 일이 없을까 싶기도 합니다만... 8월 말에 다인 선배한테 쓰는 법 배우고 그 후에도 스터디가 살아 있다면 아마 그 때부터 쓰지 않을까 싶어요. 솔직히 개인적으로 이정도 양의 과제가 나올 줄 예상 못했습니다 - [유재범]
----
[한자공/시즌3]
3. 진행 상황 ¶
- Frame, 레이블, 레이아웃과 AWT 컴포넌트
- 자바 입출력을 하려 했으나 발표자의 하드 트롤링으로 발표내용 급 변경
- 김용준의 폭주로 예상치 못한 AWT 컴포넌트의 발표.
고통스럽다.
- 자바 입출력을 하려 했으나 발표자의 하드 트롤링으로 발표내용 급 변경
3.1. 발표 내용 ¶
- 핵심 : GUI의 기본 구성
- 자바 GUI의 기초인 Frame 클래스와 레이아웃 매니저에 대해 다룸
- 자바 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로 이름 붙였다고 한다.
- 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 어플리케이션의 작업대
- 프레임 : 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))이다.
- 이를 출력하는 메소드는 java.awt.Component의 show() (혹은 show(boolean))이다.
- 사용자에게 보여줘야 할지 말지에 대한 설정이 false(보여주지 않는 것)으로 되어 있기 때문이다.
- 위 코드를 보면 show가 가로 줄이 쳐져 있는 것을 볼 수 있다
- 간단히 말해 소멸 되었다는 것이다. JDK 1.1 이후에는 setVisible(boolean)이라는 메서드 대신 사용 된다.
- 간단히 말해 소멸 되었다는 것이다. JDK 1.1 이후에는 setVisible(boolean)이라는 메서드 대신 사용 된다.
- 화면 크기 조절 메소드 : java.awt.Component의 setSize(int width, int height). 단위는 픽셀
- 그 외 적정한 크기를 할당하도록 하는 메소드로 JVM의 pack()이 있다.
- 그 외 적정한 크기를 할당하도록 하는 메소드로 JVM의 pack()이 있다.
- 화면 위치 조절 메소드 : java.awt.Component의 setLocatino(int x, int y)
화면과 프레임의 크기 1. 화면의 크기 Dimension dimen = Toolkit.getDefaultToolkin().getScreenSize(); 2. 프레임의 크기 Dimension dimen1 = f.getSize();
- Dimension 클래스 : 특정한 사각형 영역을 관리하기에 편리하도록 만들어진 클래스
- 화면의 폭과 높이를 얻어내려면 이 클래스 안의 getWidth()와 getHeight()를 사용하면 된다.
- 자고로 좌표의 중심은 왼쪽 상층이다.
- 화면의 폭과 높이를 얻어내려면 이 클래스 안의 getWidth()와 getHeight()를 사용하면 된다.
- 제목 설정 방법은 두가지가 있다.
- 첫번째. Frame f = new Frame("제목부분");
- 두번째. f.setTitle("제목변경"); (java.awt.Frame 안에 있는 메소드 setTitle(String title)을 사용)
- 첫번째. Frame f = new Frame("제목부분");
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
- Fields
- java.awt.Component
필드 속성 | 필드명 | 내용 |
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
- 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
- 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
- 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 레이아웃 메니저
- CardLayout Manager : 프레임에 카드를 엎어 놓은 듯이 여러개의 Container를 상속받은 Panel 같은 객체를 포개 놓은듯한 배치의 레이아웃 매니저
(마치 슬라이드 배경색 바뀌듯)
- GridBagLayout Manager : 프레임의 좌측 상단을 기준으로 폭과 크기를 정하여 컴포넌트를 배치하는 고차원의 레이아웃 매니저
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 : 컴포넌트의 크기 추가
5. 과제 ¶
- 계산기 gui 만들기
- 필요하다면 아래 있는 Base를 이용해서 만들 것.
- 필요하다면 아래 있는 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.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(); } }
6. 후기 ¶
- 이상한 과제에 고통 받는 동기들의 원한이 들리지 않느냐!!!
- 하드 트롤링 - 유재범
- 물론 안하셔도 됩니다. - 김용준
- AWT 컴포넌트 설명 했는데 그것도 정리해서 올려줘 - 유재범
- AWT 컴포넌트 설명 했는데 그것도 정리해서 올려줘 - 유재범
- 아 과제하는거 구경할라했는데 소스를 걍 복붙해놔서 보기도 힘들고 실행시켜보기도 귀찮네... 님들 github안쓰세요?????
- 방학 중에는 아마 쓰는 일이 없을까 싶기도 합니다만... 8월 말에 다인 선배한테 쓰는 법 배우고 그 후에도 스터디가 살아 있다면 아마 그 때부터 쓰지 않을까 싶어요. 솔직히 개인적으로 이정도 양의 과제가 나올 줄 예상 못했습니다 - 유재범
- 방학 중에는 아마 쓰는 일이 없을까 싶기도 합니다만... 8월 말에 다인 선배한테 쓰는 법 배우고 그 후에도 스터디가 살아 있다면 아마 그 때부터 쓰지 않을까 싶어요. 솔직히 개인적으로 이정도 양의 과제가 나올 줄 예상 못했습니다 - 유재범