반응형

**Event처리

=>Event는 외부에서 발생하는 사건

=>자바의 awtswing의 이벤트 처리는 Listener인터페이스나 Adapter클래스가 처리합니다.

1.이벤트 처리 방법

=>처리하고자 하는 이번트의 Listener인터페이스를 Implements하거나 Adapter클래스를 상속받은 클래스의 인스턴스를 생성

=>컴포넌트.add이벤트리스너(앞에서 생성한 인스턴스);

 

=>이러한 방식의 처리를 Delegate(위임)를 이용한 처리 방식

이벤트가 발생한 객체가 이벤트를 처리하는 것이 아니고 이벤트가 발생한 객체가 다른 객체에게 이벤트 처리를 위임하는 방식

컴포넌트는 출력에만 집중하고 다른 작업은 별도의 객체가 처리하는 것이 유지보수에 유리

 

=>이벤트 처리하는 메소드를 확인

이 메소드의 매개변수를 이용하면 이벤트가 발생한 객체에 대한 정보를 가져올 수 있습니다.

자바에서는 getSource()를 호출하면 이벤트가 발생한 객체에 대한 참조를 리턴받을 수 있습니다.

가지고 있는 메소드들이 이벤트별로 다른데 이 메소드들이 이벤트에서 사용할 정보를 리턴해줍니다.

키보드 이벤트가 어떤 이벤트 인지

 

2.이벤트 처리 실습

=>버튼을 누르거나 메뉴를 누르는 경우 또는 TextField에서 Return키를 누르는 경우를 처리할 때는 ActionListener를 이용해서 처리

=>버튼과 텍스트 필드를 만들고 버튼을 누르면 텍스트 필드에 입력된 내용을 콘솔에 출력

 

1) Anonymous클래스를 이용하는 방법

디자인 처리랑 이벤트 처리가 같이 되여있다.

책은 같이 사용하는 것으로 되여있다.

책과 실제로 일하는 것은 다르다.

실제 연습할 때는 분할 해서 해야 한다.

=>실습

public class MyWindow extends Frame {

       private Button btn;

       private TextField tf;

      

       public MyWindow() {

               //여러개의 컴포넌트를 묶어줄 container생성

               //안드로이드에서는 layout이다.

               Panel p  = new Panel();

              

               //컴포넌트들을 생성

               btn = new Button("click");

               tf = new TextField(30);

              

               //버튼의 이벤트 처리를 위한 ActionListener인터페이스의 anonymous clss생성

               //자바에서는 listener 대부분 인터페이스이다.

               ActionListener listener = new ActionListener() {

                      //버튼을 누르거나 텍스트 필드에서 Return누르거나 메뉴를 누르면 호출되는 메소드

                      @Override

                      public void actionPerformed(ActionEvent e) {

                             //입력한 내용 가져옥

                             String msg = tf.getText();

                             //출력

                             System.out.println(msg);

                      }

               };

               //btn에서 Action이벤트가 발생하면 listener 대신 처리하도록 위임(Delegation)

               //btn.addActionListener(listener);

              

               //컴포넌트들을 컨테이너에 배치

               p.add(tf);

               p.add(btn);

              

               //컨테이너를 윈도우에 배치

               add(p);

              

               //Frame 기본 설정

               setTitle("이벤트 처리");

               setLocation(100, 100);

               setSize(300, 400);

               setVisible(true);

       }

 

}

 

 

2) .별도의 이벤트 처리 클래스를 생성해서 이벤트를 처리

이벤트 처리하는 것은 handler가 있다.

나중에 연결만해주면 된다.

하지만 생성자를 생성하는 것을 알아야 한다.

작업을 나누어서 하는 것이 편하다ㅏ.

ActionListener인터페이스를 impelements한 클래스를 생성 - EventHandler

public class EventHandler implements ActionListener {

       private TextField tf;

      

       //생성자 -TextField 1개를 주입받는 생성자

       public EventHandler(TextField tf) {

               this.tf = tf;

       }

 

       @Override

       public void actionPerformed(ActionEvent e) {

               String msg = tf.getText();//오류가 난다. TextFiled 업다.

               System.out.println(msg);

       }

 

}

 

=>MyWindow클래스의 생성자에서 이벤트 연결

               //이벤트 처리를 위한 인스턴스를 생성

               //다른데에서 사용하고 싶을 생성자를 해서 넣어주면 사용 가능하다.

               EventHandler handler = new EventHandler(tf);

               btn.addActionListener(handler);

 

 

 

3.인터페이스를 이용하는 방법

1)인터페이스를 구현한 클래스를 만들고 인스턴스를 만드는 방법

=>유지보수를 위해서는 이 방식을 권장

=>생성자나 Setter메소드를 이용해서 데이터를 넘겨야 하는 어려움이 있음

 

2)인터페이스를 가지고 Anonymous Class를 만드는 방법

=>일반적인 자바(안드로이드)책에서 많이 사용하는 방법

=>이 방법은 컴포넌트가 구현된 클래스에 만들기 때문에 클래스의 변수 사용이 자유로워서 많이 이용

 

3)특수한 인터페이스의 경우는 람다를 이요하는 방법

=>Android Studio는 이 방식으로 최적화

 

4.Event Routing

=>여러 개의 이벤트를 하나의 인스턴스가 처리하도록 하는 방법

=>1개의 이벤트를 1개의 인스턴스가 처리하도록 하면 여러 개의 이벤트를 처리 할때 인스턴스의 개수가 늘어나고 제어하기가 어려워집니다.

=>이 때는 이벤트 처리 메소드에서 이벤트가 발생한 인스턴스를 구분해서 분기를 해야 합니다.

awtswing에서는 이벤트 처리 메소드의 매개변수가 getSource()를 호출하면 이벤트가 발생한 객체의 참조를 리턴하기 때문에 이를 이용해서 구분할 수 있고 ActionEvent의 경우는 getActionCommand()를 호출하면 문자열을 리턴해주는데 이 문자열이 버튼의 텍스트입니다.

getSource()를 사용하는 경우는 배열이나 List인 경우

배열이나 List는 반복문을 사용할 수 있다.

 

Button [] btn = new Button[3];

for(int i = 0; i<3, i++){

System.out.println("버튼" +"i")

}

버튼을 3개 만들 때

Button btn1, btn2, btn3;

btn1 = new Button("버튼1");

btn2 = new Button("버튼2");

btn3 = new Button("버튼3");

 

배열이나 리스트 이용하면 비교하기도 편하고

관리하기도 편하다.

=>이전 Frame에 버튼을 2개 추가해서 이벤트 라우팅 구현-MyWindow클래스에서 작업

1)인스턴스 변수로 버튼을 2개 추가

       private Button btn1, btn2;

       private Button[] buttons = new Button[2];

 

2)생성자 메소드에서 버튼 2개를 만들어서 윈도우에 추가

       //버튼을 생성해서 패널에 추가

               btn1= new Button("button1");

               p.add(btn1);

              

               btn2= new Button("button2");

               p.add(btn2);

              

               //버튼의 이벤트 처리 -라우팅을 이용하지 않는 경우

               // 경우 많으면 힘들다.

               /*ActionListener event1 = new ActionListener() {

                      //버튼을 누르거나 텍스트 필드에서 Return누르거나 메뉴를 누르면 호출되는 메소드

                      @Override

                      public void actionPerformed(ActionEvent arg0) {

                             System.out.println("버튼1 클릭했습니다.");

                      }

               };

               btn1.addActionListener(event1);

              

               ActionListener event2 = new ActionListener() {

                      //버튼을 누르거나 텍스트 필드에서 Return누르거나 메뉴를 누르면 호출되는 메소드

                      @Override

                      public void actionPerformed(ActionEvent arg0) {

                             System.out.println("버튼2 클릭했습니다.");

                      }

               };

               btn2.addActionListener(event2);*/

              

               //이벤트 라우팅을 이용하는 방법

               ActionListener eventRouting = new ActionListener() {

                      //버튼을 누르거나 텍스트 필드에서 Return누르거나 메뉴를 누르면 호출되는 메소드

                      @Override

                      public void actionPerformed(ActionEvent arg0) {

                             //arg0.getActionCommand() 경웬느 text 사용해야 한다.

                             /*switch(arg0.getActionCommand()) {

                             case "button1":

                                    System.out.println("버특1클릭");

                                    break;

                             case "button2":

                                    System.out.println("버특2클릭");

                                    break;

                             }*/

                             System.out.println(arg0.getActionCommand() +" 예약");

                      }

               };

               btn1.addActionListener(eventRouting);

               btn2.addActionListener(eventRouting);

 

=>P 만들고 후에 코드를 추가해야 합니다.

패널을 만들고 해야 한다.

 

5.ItemEvent

=>체크박스 라디오 버튼 이나 콤보박스(Choice) 선택을 변경하는 경우에 발생하는 이벤트

=>ItemListener인터페이스 처리

=>이벤트 처리 메소드의 매개변수가 getItem() 호출하면 어떤 Item 이벤트가 발생했는지 있고 getStateChange()메소드를 호출하면 어떤 상태로 변경되었는지 확인이 가능

 

6.TextListener

=>TextField TextArea에서 텍스트의 변경이 발생했을 때를 처리하는 리스너

=>TextValueChanged(TextEvent e)메소드를 이용해서 처리

=>텍스트가 변경될 상태 변화에 따라 메시지를 출력하거나 유효성을 검사하는 용도로 사용

 

영문대소문자 그리고 숫자 특수문자가 1 이상이면 강함이라고 출력

그렇지 않은 경우에는 약함이라고 출력

특수문자는 영문 대소문자가 아니고 숫자도 아니면 특수문자로 판단

 

               //텍스트 필드나 텍스트 에어리어의 문자열이 변경될 처리를 위한 인스턴스

               TextListener t1 = new TextListener() {

                     

                      @Override

                      public void textValueChanged(TextEvent e) {

                             //텍스트 필드에 입력된 문자열을 가져오기

                             String msg = tf.getText();

                             //대소문자 숫자 ,특수문자 개수를 저장할 변수를 생성

                             int dae = 0;

                             int so = 0;

                             int su = 0;

                             int etc =0;

                            

                             //문자열을 문자단위로 접근

                             for(int i = 0;i < msg.length(); i++) {

                                    //앞에서 부터 한글자씩 가져오기

                                    char ch = msg.charAt(i);

                                    //System.out.println(ch);

                                    if(ch >= 'A' && ch <= 'Z') {

                                            dae += 1;

                                    }else if(ch >= 'a' && ch <= 'z') {

                                            so += 1;

                                    }else if(ch>= '0'  && ch <= '9'){

                                            su += 1;

                                    }else {

                                            etc += 1;

                                    }

                             }

                            

                             /*if(dae >0 && so > 0 && su >0 && etc>0) {

                                    System.out.println("강함");

                             }*/

                            

                             if(dae * so * su  * etc != 0) {

                                    System.out.println("강함");

                             }else {

                                    System.out.println("약함");

                             }

                      }

               };

               tf.addTextListener(t1);

 

**keyListener

=>키보드 이벤트를 처리하기 위한 리스너

1)처리를 위한 메소드

void keyPressed(keyEvent e);키보드를 누를

 

void keyReleased(keyEvent e);키보드에서 손을

 

void keyTypers(keyEvent e);키보드를 누르고 누른 키가 문자 키일 호출되는 메소드

keyPressed 키보드 위치만을 감지를 해서 대소문자 구분을 하지 못했고   keyTypers 대소문자 구분을 했습니다.

 

2)keyEvent클래스

=>모든 key값이 상수로 정의되어 있습니다.

=>getKeyChar() 이용해서 누른 문자를 가져올 있고  getKeyCode() 이용해서 누른 키보드의 숫자 값을 가져올 있습니다.

 

 

c, java, c# ..

옵션을 만들때 int enum 이용

int enum =>정수

python 문자열로 만든다.함수를 찾아도 어려운 이유가 여기 있다. 옵션들이 문자로 되여있다.

문자열 dictionary

color = ""

 

성별

python => String str = "";

 

c,java int gender  ->0 남자

                    ->1 여자

숫자 경우 2여도 되고 3 되고

java, c 상수 만들 경우 대문자로 쓴다.

int MAN = 0; //남자

int MAN = 1;

 

=> 바꿀 경우

final int WOMAN = 0;

       int MAN =1;

 

옵션 -> 택일 : 일련번호사용 (성별 ) - 영문자( A: 65, B : 66, C:67  ..)

     -> 다중선택(취미등 ) : 2 지수승 사용

취미 현재 2개이다

독서

컴퓨터

ð  4가지 경우가 있다.

1.  하나도 선택 안한

2.  독서

3.  컴퓨터

4.  독서 + 컴퓨터

독서 , 컴퓨터 , 복싱 = > 8

독서 ,컴퓨터 , 복싱 , 1 = > 16

여러개 옵션을 사용한 것은 이렇게 사용하면 안된다. 그래서 비트로 한다.

 

복싱

컴퓨터

독서

 

0

0

0

 

1

1

1

 

독서    1

컴퓨터  2

복싱    4

독서 + 복싱 : 5

하나의 BIT 하나이다.

옵션이 많으면 감당할 없다. 4, 5, 6, 7.....

그래서 1인지 확인 해야 한다. 1인지 확인 하는 방법은 &1 이다.나머지는 0이니깐

 

& 0 & 1 =>0

  1 & 1 =>1

 

키보드 문자키는 같이 못눌린다.

 

CTRL: 128

ALT : 512

512 640이나 물어보는 것은 낭비이다.

그래서 & 512한다.

0 & 512 => 0

0 아닌것 하고 하면 512

CTRL 경우에는 & 128

 

두가지

판단 ALT, SHIFT, ALT, MOUSE 감지

 

특정 os 타겟팅  ->여기는 숫자로 쓰준다. 확정되여있다.

swift(Object -c)       ios

andriod  ->안드로이드

vc ++ vc## -> windows 윈도우용

 

shift : 4

 

java->플랫폼의 독립적 운영체제마다 달라서 확정 주지 않다. 운영체제 특징도 많이 알아야 한다. 운영체제마다 값이 다르기 때문이다.

자바는 shift 4

thread 운영체제제에서  thread우선순위가 다르다.

window 10 이고 7이다.

 

 

자바나 ,python 윈도우형이 별로 없는 이유가 vc++, vc##편하기 때문이다.

 

ctrl+->   -> 가속도 10으로

ctrl+s ->자동 발사 s-> 싸는

 

 

 

3) 방향키를 이용해서 레이블을 움직이고 control + x 누르면 프로그램 종료하는 윈도우

KeyWindow

//키보드 이벤트 처리를 위한 인스턴스를 생성

               KeyListener listener  = new KeyListener() {

                      //키보드를 눌렀을 호출되는 메소드

                      @Override

                      public void keyPressed(KeyEvent arg0) {

                             //조합키 확인: shift -1, control -2 , alt -8

                             int modifiers = arg0.getModifiers();

                             //System.out.println(modifier);

                             //contlol+ X이면 종료

                             if((modifiers &2 ) != 0) {

                                    //별도로 누른 키가 X인지 확인 -대소문자 구분해서 하고자 하는 경우는 getKeyChar()

                                    int key = arg0.getKeyCode();

                                    if(key == KeyEvent.VK_X) {

                                            System.exit(0);

                                    }

                             }

                            

                             //System.out.println("아무 키나 누르면 호출됩니다.");

                             //대다수의 프로그램 언어가 유사하게 만들어졌다.

                            

                             //KeyChar 대소문자 구분 a->a A->A

                             //System.out.println(arg0.getKeyChar());

                             //keyCode 대소문자 구분 안함: a->64 A->65 방향키

                             //System.out.println(arg0.getKeyCode());

                            

                             //현재 레이블의 위치 가져오기

                             int x = lbl.getLocation().x;

                             int y = lbl.getLocation().y;

                            

                             //누른 키보드 가져오기

                             int code = arg0.getKeyCode();

                             switch(code){

                             case KeyEvent.VK_UP:

                                    y = y -5;

                                    break;

                             case KeyEvent.VK_DOWN:

                                    y = y + 5;

                                    break;

                             case KeyEvent.VK_LEFT:

                                    x = x -5;

                                    break;

                             case KeyEvent.VK_RIGHT:

                                    x = x + 5;

                                    break;

                             }

                             lbl.setLocation(x, y);

                      }

                      //키보드에서 손을 호출되는 메소드

                      @Override

                      public void keyReleased(KeyEvent arg0) {

                             //System.out.println("키보드에서 손을 때면 무조건 호출");

                      }

                      //문자키를 눌렀을 호출되는 메소드

                      @Override

                      public void keyTyped(KeyEvent arg0) {

                             //System.out.println("문자 키를 눌렀을 호출");

                      }

               };

               //윈도우에 키보드 이벤트 리스터를 연결

               this.addKeyListener(listener);

 

 

8.MouseListener

=>마우스 이벤트를 처리해주는 리스터

=>클릭 , 영역에 마우스가 들어온 경우 , 영역에서 벗어나는 경우 ,마우스는 누를 , 마우스에서 손을 땔때 처리를 위한 메소드가 존재

=>MouseEvent에서는 마우스의 좌표를 리턴해주는 메소드와 클릭 횟수 등을 리턴해주는 메소드가 존재

 

 

9.MouseMotionListener

=>마우스를 드레그 때를 처리해주는 리스너

=>버튼을 누르고 움직일 때는 위한  Dragged메소드와 마우스를 움직이면 무조건 호출되는 Moved 메소드가 존재

 

 

10.WindowListener

=>윈도우 이벤트를 처리해주는 리스너

=>윈도우 관련된 7개의 이벤트 처리 메소드가 존재

=>윈도우의 종료 버튼을 누를 처리를 위한 메소드는 windowClosing

이전 윈도우의 생성자에 종료 버튼을 누를 프로그램이 종료되도록 이벤트 처리 코드를 추가

WindowListener windowListener = new WindowListener() {

                      //7개가 만들어진다.

                      @Override

                      public void windowActivated(WindowEvent e) {

                             // TODO Auto-generated method stub

                            

                      }

                     

                      @Override

                      public void windowClosed(WindowEvent e) {

                             // TODO Auto-generated method stub

                            

                      }

                     

                      @Override

                      public void windowDeactivated(WindowEvent e) {

                            

                      }

                     

                      //종료 버튼을 누를 호출되는 메소드

                      @Override

                      public void windowClosing(WindowEvent e) {

                             //프로그램 종료

                             System.exit(0);

                      }

                     

                      @Override

                      public void windowDeiconified(WindowEvent e) {

                            

                      }

                     

                      @Override

                      public void windowIconified(WindowEvent e) {

                            

                      }

                     

                      @Override

                      public void windowOpened(WindowEvent e) {

                            

                      }

               };

               //윈도우 이벤트 연결

               this.addWindowListener(windowListener);

사용하지도 않는 메소드를 overriding해놓았다.

 

 

11.이벤트 처리를 Listener인터페이스를 이용해서 처리하도록 하면 실제 사용하는 메소드는 1 밖에 없는 인터페이스의 메소드는 전부 추상 메소드라서 반드시 재정의 해야 합니다.

java awt에서는 메소드가 2 이상인 Listener들을 Adapter클래스에 비여있는 내용으로 구현해서 필요한 메소드만 재정의 있도록 Adapter class 제공합니다.

Adapter class 전부 추상 클래스라서 직접 인스턴스를 생성하지 못합니다.

 

앞의 윈도우 이벤트 처리 구문을 수정

               //Listener 인터패이스라서 모든 메소드를 구현해야 하지만

               //Adapter 추상클래스라서 추상메소드 필요한 메소드만 구현하면 됩니다.

               WindowAdapter windowListener= new WindowAdapter() {

                      //종료 버튼을 누를 호출되는 메소드

                      @Override

                      public void windowClosing(WindowEvent e) {

                             //프로그램 종료

                             System.exit(0);

                      }

               };

               //윈도우 이벤트 연결

               this.addWindowListener(windowListener);

 

 

**Swing

=>jvm 자원을 이용해서 GUI(Graphic User Interface)프로그래밍

=>플랫폼에 독립적인 프로그래밍

=>AWT보다 속도도 빠르고 효율적

 

**Container

1.JFrame

=>윈도우 클래스

=>종료 기능을 부여할 때는 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) 호출

=>pack이라는 메소드를 제공해서 윈도우 전체 크기를 하위 COmponent들을 배치한 크기로 설정

=>setIconImage(Image image) 이용해서 아이콘 설정 가능

 

2.전체 화면 크기 구하기

Tookit toolkit = Tookit.getDefaultToolkit();

Dimension size = toolkit.getScreenSize();

 

3.JPanel

=>패널 클래스

=>생성자에 Panel(boolean isDoubleBuffered):더블 버퍼링 여부를 설정

더블 버퍼링: 출력할 내용을 메모리에 저장해두고 출력하는 방식

            메모리 사용량은 늘어나지만 다음에 다시 출력할 출력 속도를 빠르게 해줍니다.

4.JScrollPane

=>스크롤 기능을 가진 클래스

=>부모 화면보다 컴포넌트를 배치할 사용

=>생성자를 호출해서 인스턴스를 만들 하위 컴포넌트를 대입

 

 

**Swing 일반 컴포넌트

1.경계선 설정 기능(Border)

=>setBorder메소드에 AbstractBorder클래스의 하위 클래스 인스턴스를 대입하면 경계선이 만들어집니다.

=>AbstractBorder클래스의 하위 클래스 :BevelBorder, CompoundBorder, EmptyBorder, EctchedBorder, TitleBorder

 

2.Component 마우스를 올리면 보여지는 tooltip 설정 기능

=>setTooltipText메소드에 문자열을 대입하면 툴팁이 만들어집니다.풍선 도움말

 

 

3.JLabel

=>문자열 출력을 위한 컴포넌트

=>생성자에서 Icon 대입하면 이미지 출력 가능

맞춤 설정도 가능합니다.

 

 

 

 

4.버튼

=>AbstractButton(추상클래스) 클래스로 부터 상속받은 클래스를 이용

=>JButton,JTOGGLEButton,JRadioButton 으로 구분

=>현재 윈도우에 버튼을 추가해서 버튼을 누를 마다 애니메이션을 시작하고 중지하는 기능을 구현

=>스레드를 만들어야 하는 순간

중간중간 다른 작업을 수행할 있도록 만들어야

실행 중간에 멈출수 있도록 해야

네트워크에서 다운로드나 업로드를 받을 (오랜 시간이 걸리는 작업)

상바대는 작업이라면 버튼 하나면 된다. 시작 중지

public class MyFrame extends JFrame {

       JLabel lbl;

       ImageIcon icon;

       JButton btn;

       //여기에서 만든 변수는 자동 초기하된다.

       //애니메이션을 수행할 스레드 변수

       Thread th;//자바는 네트워크 작업할 스레드 필수 하니깐

       public MyFrame() {

               JPanel p = new JPanel();

               //JLabel lbl = new JLabel("문자열");

               //이미지를 가지고 아이콘을 생성

               //이미지 파일 크기 그래도 성성됩니다.

               icon = new ImageIcon("C:\\project\\JAVA_PROJECT\\java\\src\\java\\img\\heli1.png");

               lbl = new JLabel(icon);

               p.add(lbl);

              

               //버튼을 만들어서 패널에 추가

               btn =   new JButton("시작");

               p.add(btn);

              

               //버튼을 누를 이밴트 처리를 위한 인스턴스를 생성

               //위임해도 실행하는데는 아무런 영향이 없다.

               ActionListener listener = new ActionListener() {

                      @Override

                      public void actionPerformed(ActionEvent e) {

                             switch(e.getActionCommand()) {

                             case "시작":

                                    btn.setText("중지");

                                    //스레드를 생성해서 시작

                                    th = new Thread() {

                                            String[] images = {"heli1.png" ,"heli2.png","heli3.png"};//images[i%images.length]

                                            public void run() {

                                                   try {

                                                          int i = 0;

                                                          while(true) {

                                                                 //0.1초마다 대기

                                                                 Thread.sleep(100);

                                                                 //아이콘 생성

                                                                 icon = new ImageIcon("C:\\project\\JAVA_PROJECT\\java\\src\\java\\img\\"+(i%10)+".png");

                                                                 lbl.setIcon(icon);

                                                                 i += 1;

                                                          }

                                                   }catch (InterruptedException e) {

                                                          return ;

                                                   }

                                            }

                                    };

                                    th.start();

                                   

                                    break;

                             case "중지":

                                    btn.setText("시작");

                                    //스레드를 중지

                                    th.interrupt();

                                    break;

                             }

                      }

               };

               btn.addActionListener(listener);

               add(p);

              

               //Frame 기본 설정

               setTitle("이미지 레이블");

               setLocation(100, 100);

               setSize(1000, 1000);

               setVisible(true);

               //종료 기능 부여

               setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

              

               //이미지 교체 애니메이션

               //현재는 코드가 진행이 안된다.

               /*String[] images = {"heli1.png" ,"heli2.png","heli3.png"};*/

               /*int i = 0;

               while(true) {

                      try {

                             Thread.sleep(50);

                             //icon = new ImageIcon("C:\\project\\JAVA_PROJECT\\java\\src\\java\\img\\"+(i%10)+".png");

                             icon = new ImageIcon("C:\\project\\JAVA_PROJECT\\java\\src\\java\\img\\heli"+(i%3)+".png");

                             lbl.setIcon(icon);

                             i = i+ 1;

                      } catch (InterruptedException e) {

                             // TODO Auto-generated catch block

                             e.printStackTrace();

                      }

               }*/

               //시작하고 중지 스레드 interrupte걸어서

              

               /*for(int i = 0 ; i< 10; i++) {

                      try {

                             Thread.sleep(1000);

                             System.out.println(i);

                             //lbl.setText("레이블:"+i);

                            

                             icon = new ImageIcon("C:\\project\\JAVA_PROJECT\\java\\src\\java\\img\\"+i+".png");

                             //끝부분만 바꾸면 바꿀 있다.

                             lbl.setIcon(icon);

                            

                      } catch (InterruptedException e) {

                      }

               }*/

       }

}

 

 

5.JTextField

=> 줄의 문자열을 입력받기 위한 컴포넌트

=>현재 커서의 위치를 getCaretPosition으로 가져오고 setCaretPosition(int position)으로 설정

마우스 포인터를 cursor하는 경우도 있지만 caret이라고 하는 경우도 있습니다.

cursort 데이터를 단위로 하나씩 접근하는 포인터의 의미로도 사용

 

6.JPasswordField

=>비밀번호를 입력받기 위한 컴포넌트

=>보여지는 문자를 echoChar라고 합니다.

=>입력한 내용을 가져올 때는 getText deprecated 되서 getPassword 사용하는 것을 권장

 

 

7.JTextArea

=>여러 입력을 위한 컴포넌트

=> 바꿈 모드 설정을 위한 setLineWrap(boolean warp). setWrapStyle(boolean word):단어 단위 바꿈

 

8.JComboBox

=>콤보박스

=>여러 개의 항목 중에서 화면에 하나만 출력하고 하나만 선택할 있도록 해주는 컴포넌트

 

9. JList

=>리스트 또는 리스트 박스

=>여러 개의 항목 여러 개를 화면에 출력할 있고 여러 개를 선택하도록 있도록 해주는 컴포넌트

=>ComboBox JList 용도가  Radio CheckBox 같은데 항목이 많을 Radio CheckBox 영역을 너무 많이 차지 하기 때문에 이런 경우에는 comboBox List 사용

항목의 개수 때문에

 

 

10.JTable

=>테이블 모양으로 데이터를 출력하는 컴포넌트

1)생성자

JTable():비여있는 상태로 생성

JTable(int rows, int cols);행과 수를 지정해서 생성

JTable(TableModel model): 데이터 모델을 이용해서 생성 -MVC구현을 위해서 존재

 

2)데이터 출력

setValueAt(Object value, int row, int col):row col 해당하는 셀에 value toString 결과를 출력

 

setModel(TableModel model);테이블 모델을 만들어서 출력

 

3) DefaultTableModel

DefaultTableModel()

DefaultTableModel(int 행개수, int 열개수)

DefaultTableModel(Object [][]data, Object[] columnName):첫번째 매개변수는 셀에 출력할 데이터의 이차원배열이고 뒤의 데이터는 컬럼이름 배열

 

4)테이블 모델을 이용해서 데이터를 설정한 경우의 데이터 편집

addRow(Object[] data)

insertRow(int row,Object[] data)

moveRow(int start, int end, int to);start부터 end까지의 행을 to 위치로 이동

 

updateUI();다시 출력

 

5)테이블 모델을 이용하기를 권장하는 이유

=>JTable 출력하는 모양에만 관여를 하고 실제 데이터의 삽입과 삭제는 TableModel 관여

 

**Pane

=>특정 목적에만 이용하도록 만든 컴포넌트

1.JScrollPane

=>스크롤을 만들어주는 컴포넌트

 

2.JEditorPane

=>텍스트를 출력하기 이한 컴포넌트

=>TextArea 다른 점은 URL 연결해서 HTML 출력할 있고 RTF포맷도 출력이 가능

 

3.JTabbedPane

=>탭을 만들기 위한 컴포넌트

 

4)javax.swing.JOptionPane

=>메시지나 줄의 입력을 받기 위한 대화상자

1)MessageDialog

=>단순 메시지 출력을 위한 대화상자

=>JOptionPane.showMessageDialog() 이용해서 생성

 

2)ConfirmDialog

=>버튼을 2 이상 배치해서 생성한 버튼에 따라 다른 작업을 하고자 사용

=> JOptionPane.showConfirmDialog() 이용해서 생성

누른 버튼의 인덱스를 리턴합니다.

 

3)InputDialog

=>하나의 텍스트필드를 배치해서 줄의 텍스틀 입력받을 있는 대화상자

=> JOptionPane.showInputDialog() 이용해서 생성

확인 버튼을 누르면 입력한 내용이 String으로 리턴되고 취소버튼을 누르면 null 리턴됩니다.

입력한 내용이 없는데 확인을 누르면 null 아니고 "" 리턴됩니다.

 

 


showMessageDialog
(Component parentComponent, Object message, String title, int messageType, Icon icon)

Brings up a dialog displaying a message, specifying all parameters.

 

               //showMessageDialog(Component parentComponent, Object message, String title, int messageType, Icon icon)

               //단순한 메시지 출력 - 리턴값이 없습니다.

               //JOptionPane.showMessageDialog(this, "메시지","제목",JOptionPane.ERROR_MESSAGE);

               //ERROR_MESSAGE red

              

               //2 이상의 버튼을 배치해서 confirm 받는 메소드

               /*

               int result = JOptionPane.showConfirmDialog(this, "정말로 삭제","삭제",JOptionPane.YES_NO_CANCEL_OPTION);

               if(result == JOptionPane.YES_OPTION) {

                      JOptionPane.showMessageDialog(this, "yes","제목",JOptionPane.ERROR_MESSAGE);

               }else if(result == JOptionPane.NO_OPTION) {

                      JOptionPane.showMessageDialog(this, "no","제목",JOptionPane.ERROR_MESSAGE);

               }else {

                      JOptionPane.showMessageDialog(this, "cancel","제목",JOptionPane.ERROR_MESSAGE);

               }*/

              

               //한줄의 텍스트를 입력받는 대화상자를 출력

               //입력한 내용이 없는 상태에서 확인을 누르면 ""

               //

               String name = JOptionPane.showInputDialog(this,"이름을 입력하세요","");

               System.out.println(name);

 

**메뉴

=>JMenuBar, JMenu, JMenuItem(JMenuItem, JCheckBoxMenuItem, JRadioButtonMenuItem)

=>메뉴에 setMnemonic(int 단축키) 설정하면 alt 조합해서 단축키로 사용 가능

응용프로그램을 만들 alt 포함해서 단축키를 만드는 것은 권장하지 않습니다.

미국에서 메뉴에 대한 단축키를 alt 사용한다.

ctrl 단독으로 많이사용한다.

 

**Stream

1.  입출력 Stream

2.  1.8에서 등장한 Map Reduce 프로그래밍일 위한 스트림 ->우리가 하는

 

 

 

반응형

'Study > Java' 카테고리의 다른 글

java-15  (1) 2020.10.05
java-14  (0) 2020.10.04
java-12  (0) 2020.10.02
java-11  (0) 2020.10.01
java-10  (0) 2020.09.30
반응형

상호배제 : 스레드가 수정하고 있는 공유자원은 다른 스레드가 수정할 수 없다.

변수에 volatile :long,double 같은 64bit 자료형

예약으로 되여있지만 거의 사용하지 않는다.

synchronized: 이 메소드가 끝났을 때 까지 나머지는 대기 해야 한다.

synchronized(객체명): 이 블록내에서 이 객체는 동기화가 된다.

이 객체는 다른 것들이 사용할 수 없다.

volatile :특수 변수의읽고 쓰기 작업에 대해 원자성을 보장해주는 예약어

윈도우 64BIT는 문제가 없는데

a영역을 하는 중 thread 가 들어오면 문제가 생긴다.

vabtile a

a작업 다 끝나야 b 쪽에서 다 하고 끝난다.

 

메소드의 결과형 앞에 SYNCHRONIZED를 추가

이것이 문제가 된다.

 

int x = 0;

 

threa 형식으로 할때

a();수행하다가 sleep를 하면 b를 진행()

a()에서 1를 만들었는데 2가 된다.

 

 

synchronized a 순서데로 한다. 다른 스레드가 끼여들지 못하게끔

비동기는 왔다 갔다 할 수 있다. asynchronized

 

threadshare로 해서 만들었다.

 

스레드는 우선순위를 정할 수 없다.

 

**Mutual Exclusion

=>하나의 스레드가 수정 중인 공유자원을 사용이 끝나기 전에 다른 스레드가 수정하면 안된다.

 

1.volatile

=>변수앞에 붙이는 예약어로 변수가 연산에 사용될 때 원자성을 보장

원자성 :작업이 완전히 끝나기 전에는 다른 작업이 끼어들 수 없다.

=>32bit시스템에서 64bit자료형인 long, double을 멀티 스레드 환경에서 사용하다 보면 작업이 완료되기 전에 다른 스레드에서 사용해서 잘못된 결과를 사용할 수 있습니다.

이 경우에 volatile을 보여주면 위와 같은 상황이 발생ㅇ하지 않습니다.

 

2. synchronize메소드

=>메소드 결과형 앞에 synchronized를 붙이면 메소드를 동기화해서 실행

=>이 메소드가 완료되기 전에는 다른 스레드가 수행될 수 없도록 합니다.

 

파일 입출력은 cpu가 필요없다.direct memory access (DMA) 데이터 옮길 때는 CPU가 필요하다.

CPU가 읽고 다 읽으면 INTERRUPT준다.

다운로드 받는 동안 다른 것 가능하다.

 

GUI에서는 오래 시간 하면 뒤에로 간다.

계산하고 , 화면 출력하는 것은 오래 걸려서 뒤에서 뺀다.

 

3. synchronized블럭

synchronized (인스턴스 ) {

           코드 작성

}

=>블럭 내에서 인스턴스를 사용하는 부분만 동기화가 됩니다.

한번에 이루어져야 하는 부분만 동기화 할 수 있습니다.

 

//Runnable:스레드로 동작할 있도록 해주는 인터페이스

public class ThreadImpl implements Runnable {

 

       //인덱스 변수와 합께를 저장할 변수

       private int idx;

       private int result;

      

       //result 리턴하는 메소드

       public int getResult() {

               return result;

       }

      

       //idx 값을 1 증가하면서 result 추가하는 메소드

       //10000 수행하는 메소드

       //메소드 앞에 SYNCHRONIZED 붙으면 멀티 스레드 환경이더라도 메소드의 수행이 종됴될 까지

       //다른 작업은 수행할 없습니다.

       //방법 1 -스레드 끝나고 하면 의미가 없다.

       /*private synchronized void sum() {

               for (int i = 0; i < 10000; i++) {

                      idx += 1;

                      try {

                             Thread.sleep(1);

                      }catch(Exception e) {}

                      result += idx;

               }

       }*/

      

       //방법 2 - 일부분으로 해서 사용한다.

       private void sum() {

               for (int i = 0; i < 10000; i++) {

                      // 블록 안에서this(자기 자신) 메소드를 사용하는 부분을 동기화

                      synchronized(this) {//동기화 블록을 추천한다.

                             idx += 1;

                             try {

                                    Thread.sleep(1);

                             }catch(Exception e) {}

                             result += idx;

                      }

               }

       }

       //스레드로 동작할 내용을 작성하는 메소드

       @Override

       public void run() {

               sum();

       }

 

}

 

 

public class MutexMain {

       public static void main(String[] args) {

               //Runnable인터페이스를 implements 클래스에 인스턴스 생성

               ThreadImpl threadImpl = new ThreadImpl();

              

               //Thread클래스의 생성자에 대입해서 thread인트턴스 생성

               Thread th1 = new Thread(threadImpl);

               Thread th2 = new Thread(threadImpl);

               //스레드는 비동기 이다.

               th1.start();

               th2.start();

               //스레드가 하나일 경우 문제가 없지만 두개 경우 문제가 생긴다.

              

               //System.out.println(threadImpl.getResult()); //0이다.

               //동기화는 순서이다.

               //네이버 비동기로 한다.

              

               try{

                      //스레드의 수행이 끝나면 결과를 출력

                      Thread.sleep(40000);

                      System.out.println(threadImpl.getResult()); //

               }catch(Exception e) {

               }

              

       }

}

 

**생산자와 소비자 문제

=>공유 자원을 생성하는 스레드와 사용하는 스레드가 동시에 동작 중일 때 소비자 스레드는 생산자 스레드가 공유 자원을 생성을 해주었을 때 동작을 해야 합니다.

공유자원을 생성하지 않은 상태에서 소비자 스레드가 동작하게 되면 예외가 발생합니다.

 

1.wait 메소드

=>스레드의 작업을 대기 시키는 메소드

wait() :notity()가 호출 될 때 까지 대기 -싸인을 주는 것

wait(long msec): 매개변수로 대입된 시간만큼 대기

 

2.notify메소드

=>대기 중인 스레드에게 신호를 보내서 작업을 수행하도록 해주는 메소드

notify():wait중인 스레드 중 1개 에게만 신호를 보내는 메소드

notifyAll():wait중인 모든 스레드에게 신호를 보내는 메소드

 

3.주의할 점

=>wait notify메소드는 Object클래스의 메소드

=>waitnotifysynchronized메소드에서만 동작

메소드가 synchronized메소드가 아니면 예외가 발생합니다.

 

4.실습

1) 공유 자원 클래스

=>List를 인스턴스 변수로 받고 List에서 데이터 1개를 꺼내서 출력하는 메소드 와 List 데이터 1개를 저장하는 메소드를 소유

//공유 자원을 소유할 클래스

public class Product {

       //공유자원 변수

       private List<Character> list;

      

       //생성자 -list 초기화

       public Product() {

               list = new ArrayList<Character> ();

       }

      

       //데이터 1개를 받아서 저장하는 메소드

       public void put(Character ch) {

               list.add(ch);

               System.out.println(ch+" 입고 되었습니다");

               try {

                      Thread.sleep(1000);

               } catch (InterruptedException e) {}

               System.out.println("입고 현재 수량:" +list.size());

       }

      

       //데이터 1개를 꺼내서 출력하는 메소드

       public void get() {

               //첫번째 데이터를 삭제하고 리턴

               Character ch = list.remove(0);

               System.out.println(ch+" 출고 되었습니다");

               try {

                      Thread.sleep(1000);

               } catch (InterruptedException e) {}

               System.out.println("출고 현재 수량:" +list.size());

       }

}

 

 

2)생산자 스레드

=>앞에서 만든 Product 생성자의 매개변수로 받아서 스레드를 26 데이터를 삽입

a-z

=>Thread클래스로 부터 상속받는 Producer클래스

public class Producer extends Thread {

       private Product product;

      

       //외부에서 인스턴스 주입받아서 객체를 생성하는 생성자

       public Producer(Product product){

               this.product = product;

       }

 

 

       //스레드로 동작하는 메소드

       public void run() {

               for (char i = 'A';i <= 'Z'; i++) {//i = i+1인터로 가능성이 있다.

                      product.put(i);

               }

       }

 

}

 

3)소비자 스레드

=>Product를 외부에서 받아서 스레도로 26get동작

=>Thread클래스로부터 상속 받는 Customer

public class Customer extends Thread {

       //공유 자원 변수

       private Product product;

      

       //외부에서 주입 받는 생성자

       public Customer(Product product) {

               this.product = product;

       }

      

       public void run() {

               for(int i = 0; i < 26; i++) {

                      product.get();

               }

       }

}

 

4)main메소드를 소유한 Main클래스

예외 처리해도 좋지만

100 개 수집시 구글이 크롤링 한다.

순차적으로 사용하면 예외처리 하지 않고 예외처리 해주면 중간에 멈춰도 작업 할 수 있다. 동시에 하면 시간이 빠르다.

daemon은 같이 죽는다. 같이 죽을려면 daemon하면 된다.

출고가 오류난다. 출고는 입고한 다음 해야 한다.

public class Main {

 

       public static void main(String[] args) {

               //공유 자원 생성

               Product product = new Product();

              

               //Thread 클래스를 상속받은 클래스의 인스턴스를 만들고 스래데로 동작

               Customer customer = new Customer(product);//꺼내는

               Producer producer = new Producer(product);//저장하는

              

               //thread 직접 start  가능하다.

               //runable thread한다음 start해야 한다.

               customer.start();

               producer.start();

              

       }

 

}

 

 

 

5).이 상태에서 실행하면 customer스레드가 예외를 발생시킵니다.

product에 데이터가 없는데 읽을려고 해서 예외 발생

특정 조건을 만족하지 않으면 wait를 호출해서  대기모드로 만들고 조건이 만족되면 norify를 호출해서 wait중인 스레드를 깨워주면 됩니다.

synchronized에서만 가능하다.

 

6)Product클래스의 메소드를 수정

notify wait하면서 기다리고 계속 깨워줘야 한다.

       //데이터 1개를 받아서 저장하는 메소드

       public synchronized void put(Character ch) {

               if(list.size() >2) { //2개이상 생산하지 않는다.

                      //2 만들고 대기한다.

                      try {

                             wait();

                      } catch (InterruptedException e) {

                             e.printStackTrace();

                      }

               }

               list.add(ch);

              

               //데이터 추가후  신호룰 보내준다.

               notify();

              

               System.out.println(ch+" 입고 되었습니다");

               try {

                      Thread.sleep(1000);

               } catch (InterruptedException e) {}

               System.out.println("입고 현재 수량:" +list.size());

       }

      

       //데이터 1개를 꺼내서 출력하는 메소드

       //synchronized 붙지 않으면 jvm 모니터링을 하지 않기 때문에 신호를 보낼 없습니다.

       public synchronized void get() {

               //list 데이터가 없으면 대기

               if(list.size() == 0) {

                      try {

                             wait();

                      } catch (InterruptedException e) {

                             e.printStackTrace();

                      }

               }

               //첫번째 데이터를 삭제하고 리턴

               Character ch = list.remove(0);

               notify();//잠자고 있으면 깨워라

               System.out.println(ch+" 출고 되었습니다");

               try {

                      Thread.sleep(1000);

               } catch (InterruptedException e) {}

               System.out.println("출고 현재 수량:" +list.size());

       }

 

캐릭터를 만들어서 모든 캐릭터 정보를 했으면 아무런 문제도 없다.

 

 

공경력 = 무기 + _ + 공성원

공성원이 0으로 된다.

공경력 계산을 할 때는 wait()하다가 공성정보 읽고 (notify)로 해서

방어력

 

multi -thread동시에 읽을 경우 문제가 생긴다. 그래서 공성정보 먼저 읽으면 무제 없다.

m 두번 눌리면 새 창을 만들다가 창으로 바꿘다.

m은 두번 눌려서 되는 원인이 공성정보가 후에 조회 되였다.

그래서 어떤 것 되고 해야 한다.

 

 

로그인시

id

pw

 

기타정보 를 따로 읽어도 되는데 로그인 정보를 읽으려면 위에것 먼저 조회하고 해야 한다.

 

 

처음에는 작업2를 하면 안된다. wait하고 작업1에서 notify만 하면 된다.

업무에 대한 이해를 알아야 한다.

 

DeadLock: 결코 발생할 수 없는 사건을 무한정 기다리는 것

select - shared lock

insert,update, delece - executed lock

 

toad등에서 insert, update, delete lock을 한다.

eclipse에서 insert할 경우 안된다. 기다려야 한다.

commit/rollback할 때 까지 기다린다.

기다리고만 한다.

select 는 된다.

 

awt, swing으로 하면 안드로이드 하면 된다.

 

**Semaphore

=>공유자원을 동시에 사용할 수 있는 스레드의 개수를 설정할 수 있는 클래스

=>이 클래스를 이용하면 동시에 수행되는 스레드의 개수를 지정 가능

1.생성자

Semaphore(int permit): 동시에 수행될 스레드 개수

2.메소드

acquire():공유자원에 lock을 설정하는 메소드, 이 메소드가 호출되면 공유자원 개수가 1개 줄어듭니다.

release()"공유자원에 lock을 해제하는 메소드, 이 메소드가 호출되면 공유자원 개수가 1개 늘어납니다.

 

3.작업 방법

=>Semaphore클래스의 인스턴스를 스레드 외부에서 생성

=>Semaphore인스턴스를 스레드에게 전달해서 공유자원을 사용하는 부분에서 이용

 

4.실습

1) 세마포어가 적용된 스레드 클래스

 

public class ThreadEx extends Thread {

       public void run() {

               System.out.println("몬스터 생성");

               try {

                      Thread.sleep(3000);

               } catch (InterruptedException e) {

                      e.printStackTrace();

               }

               System.out.println("몬스터 소멸");

       }

}

 

public class SemaphoreMain {

       public static void main(String[] args) {

               //만드는 만큼 몬스타가 생긴다.

               for (int i = 0; i < 20; i++) {

                      ThreadEx th = new ThreadEx();//20개가 동시에 진행된다.

                      th.start();

               }

              

              

       }

}

 

 public class ThreadEx extends Thread {

       //세마포어 변수

       private Semaphore sem ;

      

       //외부에서 Semaphore 주입받습니다.

       public ThreadEx(Semaphore sem) {

               this.sem = sem;

       }

      

       public void run() {

               try {

                      //lock 취득 - 사용 개수가 1 줄어듬

                      sem.acquire();//3,2,1,0

                      //몬스터를 몇개 만들고 없에버린다.

               } catch (InterruptedException e1) {

                      // TODO Auto-generated catch block

                      e1.printStackTrace();

               }

               System.out.println("몬스터 생성");

               try {

                      Thread.sleep(3000);

               } catch (InterruptedException e) {

                      e.printStackTrace();

               }

               System.out.println("몬스터 소멸");

               //몬스타를 죽고 난다음 release하라고 해야 한다.

               sem.release();//하나씩 늘어난다.

       }

}

 

2)main메소드

public class SemaphoreMain {

       public static void main(String[] args) {

               //동시에 실행시키고 싶은 개수 만큼

               //동시에 3 까지 실행되는 세마포어 생성

               Semaphore sem = new Semaphore(3);

               //만드는 만큼 몬스타가 생긴다.

               for (int i = 0; i < 20; i++) {

                      ThreadEx th = new ThreadEx(sem);//20개가 동시에 진행된다.

                      th.start();

               }

       }

}

 

스레드는 동시에 진행하는 것이아니다.

 

 

**병렬처리

=>동시에 2개 이상의 작업을 수행하는 것

=>자바에서는 fork&join프레임워크(1.7)와 스트림 API(1.8)에서 제공

1부터 100까지의 합계를 구하는 경우 프로세스가 2개 이상이라면 1-50까지를 하나의 프로세스가 계산하고 다른 프로세서가 51- 100까지의 합을 계산해서 더하면 훨씬 효율적으로 작업을 할 수 있게 됩니다.

=>리턴 값 여부에 따라 달라질 수 있는데 작성 방법

작업을 수행하고 RETURN여부에 따라서 상속받는 것이 다른다. RecursiviAction(리턴 값이 없는 경우)이나 RecursiveTask(리턴 값이 있는 경우) 클래스를 상속받는 클래스를 생성하고 compute메소드를 재정의해서 작업을 어떻게 분할해서 수행할지 작성하고 결과를 리턴하면 됩니다.

RecurisiveTask는 리턴할 데이터 타입으로 제너릭을 적용해야 하고 compute의 리턴 타입도 일치해야 합니다.

 

//1-60 60 걸려야 한다.보통은

작업을 나누어서 해야 하기 때문에 정도 까지는 걸린다.

 

//1부터 60까지의 합계를 분할새어 수행하는 클래스

public class ParallelProcessing extends RecursiveTask<Integer>{

       //합계를 시작할 결과 끝나는 값을 저장할 인스턴스변수

       public int start;//생성자 안만들고 public으로 하기

       public int end;

      

       //생성자를 이용해서 start end 주입받기

       public ParallelProcessing(int start,int end) {

               this.start = start;

               this.end  = end;

       }

      

       //start부터 end까지의 합계를 구해서 리턴하는 메소드

       private int sum() {

               System.out.println("start:" + start +" end:"+end);

               int r =0;

               for(int i = start; i <= end; i++) {

                      r += i;

                      try {

                             Thread.sleep(1000);

                      } catch (InterruptedException e) {}

               }

               return r;

       }

 

       @Override

       protected Integer compute() {

               if(end - start < 10) {

                      return sum();

               }

              

               int half =  (end + start)/2;

              

               //1부터 15, 16 - 30

               //10보다 작을 까지 쪼개서 한꺼번에 실행시킨다.

               //자기가 자기를 계속 호출한다.ParallelProcessing

               ParallelProcessing p1 = new ParallelProcessing(start,half);

               ParallelProcessing p2 = new ParallelProcessing(half+1,end);

               /*p1.start = 1;

               p1.end = 30;

              

               p2.start = 31;

               p2.end = 60;*/

              

               //첫번째 적업 실행

               p1.fork();

               //첫번째 작업 결과에 두번째 작업 결과를 더해서 리턴

               return p2.compute() + p1.join();

       }

 

}

 

public class Main {

       public static void main(String[] args) {

               ParallelProcessing p = new ParallelProcessing(1, 60);

               //위의 작업을 나누어서 있는 pool 생성

               ForkJoinPool pool = new ForkJoinPool();

               //pool 작업을 대입해서 실행

       System.out.println(pool.invoke(p));//java.lang.StackOverflowError 스택이 터져버렸다.

       }

}

 

 

 

 

**java GUI

1.awt

=>운영체제의 자원을 이용해서 GUI프로그래밍

=>운영체제 별로 다르게 출력될 수 있습니다.

=>운영체제에 종속적이라고 느리고 무겁습니다.

 

2.swing

=>jvm자원을 이용해서 GUI프로그래밍

=>운영체제에 독립적이고 속도가 AWT보다는 빠릅니다.

=>SWING의 대부분의 클래스는 AWT로 부터 상속받았습니다.

 

3.javaFX

=>가볍고 풍부한 UI제공

=>레이아웃 , 스타일 ,애플리케이션 로직의 분리:MVC구현

=>HTML이나 CSS도 사용이 가능

=>swing으로 만들어져 있는 많안 애플리케이션들이 javaFX로 변환되고 있는 중

 

4.awt swing의 이벤트 처리 방식이 안드로이드 이벤트 처리 방식

awtswing은 이벤트 처리 클래스가 별도의 클래스로 존재하는데 안드로이드에서는 뷰의 내부 클래스로 존재

 

 

**AWT

=>운영체제에 종속적인 GUI프로그래밍

=>최근에는 거의 사용 안함

 

 

1.GUI화면 구성 요소

1)COMPONENT

=>화면에 보여지는 개체들의 최상위 클래스

 

2)cONTAINER

=>COMPOENT로 부터 상속을 받아서 다른 컴포넌트들을 묶어서 출력하기 위한 컴포넌트

=>단독으로 출력가능한 객체 :Frame, Dialog

=>단독으로는 출력이 안되는 객체: Panel, Window

=>브라우저를 이용해서 출력하는 객체 :Applet -사용을 금기시 함

html5에서는 별도의 플러그 없이 앱 애플리케이션을 구현하자는 주의여서 active -X, apple, flash등의 사용을 배제

 

 

2.Component의 주요 메소드

Color getBackground(), void setBackground(Color color)->배경색 관련 메소드

Cursor getCursor(),void setCursor(Cursor cursor)->마우스 커서 관련 메소드

Font getFont(), void setFont(Font font) ->포트

Color getForeground(), void setForeground(Color color) -> 글자 색

Point getLocation(), void setLocation(Point)->좌표

Dimension getSize(), void setSize(Dimension dimension)->크기

=>크기와 좌표는 분할해서 2개로 설정해도 된다.

Rectangle getBounds(), void setBounds(Rectangle rectangle) ->좌표와 크기

=>숫자 4개로 설정이 가능

위치의 기본값은 0 ,0 크기의 기본값도 0,0

안드로이도 크기 안주면 보이지 않는다.

 

void setEnabled(boolean isEnabled): 할성화 여부 설정

void setVisible(boolean isVisible): 화면 출력 여부 ->맨처음에 전체 윈도우를 불러야만 사용가능

 

3.Frame

=>애플리케이션의 가장 기본이 되는 윈도우

=>기본적으로 화면에 출력되지 않도록 설정되어 있기 때문에 setVisible을 호출해서 화면에 보여지도록 설정해야 합니ㅏㄷ.

=>setTitle을 이용하면 제목을 설정할 수 있습니다.

=>종료버튼이 제공이 되지만 기능은 없습니다.

나중에 이번트 처치를 해야만 창을 종료할 수 있습니다.

 

4.COmponent를 다른 component에 추가할 때는 add(Component component) 를 호출하면 추가됩니다.

 

 

5.윈도우 생성

=>제공되는 클래스를 사용할 때 제공되는 클래스의 인스턴스를 바로 만들어서 사용하는 경우인데 기능이 충분해서 인스턴스 생성만으로 옵션들을 설정해서 사용합니다.

=>상속받아서 사용하는 경우는 기능이 부족해서 기능을 추가해서 (Overriding)사용하기 위해서 입니다.

초기화 작업을 하거나 메소드 overriding을 해서 사용

상속시 생성자도 안하고 overriding하지 않으면 이다. 그냥 메소드 추가하는 방법은 없다고 보셔도 됩니다.

 

1)Frame인스턴스를 만들어서 출력

public class FrameMain1 {

       public static void main(String[] args) {

               //이렇게 하게 되면 너무 지전분하다.

               //윈도우 생성

               Frame f = new Frame();

               //좌표를 설정

               f.setLocation(100, 100);

               //윈도우 크기 설정 - 기본 크기가 0,0이므로 크기 설정하지 않으면 출력 안됨

               f.setSize(300, 500);

               f.setTitle("처음 만들어보는 윈도우");

               //f.setBackground(Color.GREEN);

               f.setBackground(new Color(128,0, 255));

               //윈도우를 화면에 출력 - 기본적으로 보이지 않도록 설정되어 있어서 메소드를 호출해야 보여짐

               f.setVisible(true);

       }

}

 

 

2)Frame으로 부터 상속받는 클래스를 만들고 클래스의 인스턴스를 만들어서 출력

=> 이 방법이 권장

=> 생성자를 만들어서 필요한 옵션을 설정

public class MyFrame extends Frame{

       //생성자

       public MyFrame() {

               setTitle("프레임 상속");

               setLocation(20,20);

               setSize(400,400);

               setVisible(true);

       }

}

 

public class FrameMain2 {

       public static void main(String[] args) {

               new MyFrame();

       }

}

 

6.Pannel

=>단독으로 출력될 없는 컨테이너로 여러 컴포넌트들을 묶어서 출력하기 위한 객체

1)생성자

Panel();

Panel(LayoutManager layoutManager):배치 방법을 설정해서 생성

 

2)주요메소드

add(Component component):패널위에 컴포넌트를 추가

 

7.Dialog(대화상자)

1)ModalModeless

Modal: 대화상자가 화면에 출력되어 있으면 다른 곳으로 제어권을 뺏기지 않는 대화상자, 열기와 저자 대화상자

파일에서 열기 누르면 다른데 누를수 가 없다.

적용, 저장이 있다.

 

Modeless:화면에 출력된 상태에서 다른 곳으로 제어권을 옮길 수 있는 대화상자,  찾기와 바꾸기

옵션을 대화상자에서 변경하고 바로 적용하고자 할 때 사용

modeless는 지역변수로 만들면 나중에 대화상자를 닫지 못하는 경우가 발생할 수 있습니다.

항상 메소드 바같쪽에 나둬야 한다.

 

2)생성자

Dialog(Frame이나 Dialog owner):대화상자가 닫히고 난 후 포커스를 받을 윈도우를 설정해서 생성

대화상자 기반의 프로그램은 계산기 =>dialog(null)

Dialog(Frame이나 Dialog owner,String title)

Dialog(Frame이나 Dialog owner,boolean modal) //truemodal

Dialog(Frame이나 Dialog owner,String title,boolean modal)

순서를 잘 확인해야 한다.

 

modalless상태

       //생성자

       public MyFrame() {

               setTitle("프레임 상속");

               setLocation(20,20);

               setSize(400,400);

              

               //대화상자를 만들어서 출력

               //대화상자가 모달로 출력이 되면 출력이후 문장은 대기 상태

               Dialog dialog = new Dialog(this,"대화상자");

               //Dialog dialog = new Dialog(this,"대화상자",true);//대화상자 밖에 안만들어진다. modal 절대로 다른데로 옮긴다.

               dialog.setLocation(10 ,10);

               dialog.setSize(100,100);//modaless 만들어져 있다.

              

               //setVisible(true);//먼저 윈도우 보여주기

               dialog.setVisible(true);

              

               setVisible(true);

       }

 

 

       public MyFrame() {

               setTitle("프레임 상속");

               setLocation(20,20);

               setSize(400,400);

              

               //대화상자를 만들어서 출력

               //대화상자가 모달로 출력이 되면 출력이후 문장은 대기 상태

               //Dialog dialog = new Dialog(this,"대화상자");

               Dialog dialog = new Dialog(this,"대화상자",true);//대화상자 밖에 안만들어진다. modal 절대로 다른데로 옮긴다.

               dialog.setLocation(10 ,10);

               dialog.setSize(100,100);//modaless 만들어져 있다.

              

               //setVisible(true);//먼저 윈도우 보여주기

               dialog.setVisible(true);

              

               setVisible(true);

       }

       public MyFrame() {

               setTitle("프레임 상속");

               setLocation(20,20);

               setSize(400,400);

              

               //대화상자를 만들어서 출력

               //대화상자가 모달로 출력이 되면 출력이후 문장은 대기 상태

               //Dialog dialog = new Dialog(this,"대화상자");

               Dialog dialog = new Dialog(this,"대화상자",true);//대화상자 밖에 안만들어진다. modal 절대로 다른데로 옮긴다.

               dialog.setLocation(10 ,10);

               dialog.setSize(100,100);//modaless 만들어져 있다.

              

               setVisible(true);//먼저 윈도우 보여주기

               dialog.setVisible(true);

              

               //setVisible(true);

       }

8.Button

1) 생성자

Button();

Button(String ,title)

 

2)메소드

String getLable();

void setLable(String lable);

setBackground()......

 

9.Checkbox도 버튼으로 본다.

1)생성자

Checkbox();

Checkbox(String ,title)

Checkbox(String ,title , boolean state)

Checkbox(String ,title ,CheckboxGruop group, boolean state)

=>CheckboxGroup 인스턴스를 생서애서 대입하면 라디오 버튼

 

public class ButtonWindow extends Frame {

      

       private Button btn;//이러야 메소드에서 버튼을 여러개 사용 가능핟.

       //성별을 체크하는 라디오 버튼

       private Checkbox man, woman;

      

       public ButtonWindow() {

               setTitle("button window");

               setLocation(100,100);

               setSize(300,300);

              

               Panel  p = new Panel();

              

               btn = new Button("button");

               //버튼을 패널에 추가

               p.add(btn);

              

               man = new Checkbox("man");

               woman = new Checkbox("woman");

               p.add(man);

               p.add(woman);

              

               //패널을 윈도우에 추가

               add(p);

              

               setVisible(true);

       }

}

 

 

 

public class ButtonWindow extends Frame {

      

       private Button btn;//이러야 메소드에서 버튼을 여러개 사용 가능핟.

       //성별을 체크하는 라디오 버튼

       private Checkbox man, woman;

      

       public ButtonWindow() {

               setTitle("button window");

               setLocation(100,100);

               setSize(300,300);

              

               Panel  p = new Panel();

              

               btn = new Button("button");

               //버튼을 패널에 추가

               p.add(btn);

                            

               CheckboxGroup group = new CheckboxGroup();

               man = new Checkbox("man", group,true);

               woman = new Checkbox("woman", group,false);

               p.add(man);

               p.add(woman);

              

               //패널을 윈도우에 추가

               add(p);

              

               setVisible(true);

       }

}

 

 

 

public class ButtonWindow extends Frame {

      

       private Button btn;//이러야 메소드에서 버튼을 여러개 사용 가능핟.

       //성별을 체크하는 라디오 버튼

       private Checkbox man, woman;

      

       public ButtonWindow() {

               setTitle("button window");

               setLocation(100,100);

               setSize(300,300);

              

               Panel  p = new Panel();

              

               btn = new Button("button");

               //버튼을 패널에 추가

               //btn.setLabel("button1");

               p.add(btn);

              

               //man = new Checkbox("man");

               //woman = new Checkbox("woman");

              

               CheckboxGroup group = new CheckboxGroup();

               man = new Checkbox("man",group, true);

               woman = new Checkbox("woman",group, false);

               p.add(man);

               p.add(woman);

              

               //패널을 윈도우에 추가

               add(p);

              

               setVisible(true);

              

               //5초후에 버튼의 레이블 변경

               /*try {

                      Thread.sleep(5000);

                      btn.setLabel("update");

               }catch(Exception e) {}*/

              

               /*for(int i = 0 ; i < 20 ;  i++) {

               try {

                      Thread.sleep(1000);

                      btn.setLabel("button "+ i);

               } catch (InterruptedException e) {}

              

               }*/

              

               //색상 바꾸기

               Color [] colors = {Color.RED , Color.BLUE, Color.GREEN};

               int i =0;

               while(true) {

                      try {

                             Thread.sleep(1000);

                             btn.setBackground(colors[i%colors.length]);

                             i++;

                      } catch (InterruptedException e) {}

                     

               }

       }

}

          

public class FrameMain2 {

       public static void main(String[] args) {

               //new MyFrame();

               new ButtonWindow();

               //한글이 안되면 바꿔야 ms949

       }

}

 

 

10.choice

=> 여러 개의 항목을 출력하고 그 중에 하나를 선택할 수 있도록 해주는 컴포넌트

1)생성자

Choice()

 

2)메소드

void add(String item)

String getItem(int index)

int getSelectedIndex():선택된 인덱스를 리턴

String getSelectedItem():선택된 문자열을 리턴

void remove(int index또는 String item)

 

 

11.Label

=>텍스트 출력 컴포넌트

1) 생성자

Label ()

Label(String text) 문자열 출력

Lable(String text, int alignment):맞춤을 지정해서 출력

alignment는 정수지만 옵션이기 때문에 직접 숫자를 설정하지 않고 클래스의 상수 이용

 

2)메소드

String getText()

void setText(String text)

void setAlignment(int alignment)

 

 

 

12.List

=>여러개의 항목을 출력하고 선택할 수 있도록 해주는 컴포넌트

=>Multiple Mode설정을 이용해서 여러 개 선택이 가능

1)생성자

List()

List(int rows):보여 줄 행의 개수

List(int rows, boolean multipleMode): 행의 개수를 설정하고 다중 선택 모드를 설정

 

2)choice의 메소드에 추가

int [] getSelectedIndexes():여러 개 선택한 경우 선택된 인덱스를 배열로 리턴

String[] getSelectedItems()

 

13.TextField

=>한 줄의 문자열을 입력받는 컴포넌트

1)생성자

TextField()

TextField(int columns):크기(글자 개수) 설정

TextField(String text):초기 문자열

TextField(String text,int columns):초기 문자열

 

2)메소드

void setEchoChar(char ch):화면에 보여질 문자 (동그라미나 별등을 보여준다.)

 

 

14.TextArea()

=>여러 줄 입력받는 컴포넌트

=>TextArea(String text, int rows, int columns, int scrollbars);

 

15.Scrollplane

=>GUI프로그래밍에서는 자신의 부모보다 더 큰 콘텐츠는 화면에 출력할 수 없습니다.

부모보다 큰 경우에는 Scroll이 가능한 컴포넌트에 배치를 해서 스크롤 바를 이용해서 보여주도록 해야 합니다.

=>생성자

ScrollPane(int 스크롤바정책): 항상 보여줄 것인지 아니면 필요할 때만 보여줄 것인지 등

 

16.메뉴

=>MenuBar, Menu,MenuItem(CheckboxMenuItem)

=>MenuBar인스턴스를 만들고 Frameadd

=>Menu를 만들고 Menu MenuBaradd,Menu를 만들 때는 문자열과 함께 생성

=>MenuItem이나 Menu를 만들어서 Menu에 부착

순세대로 add하면 menu에 만들어진다.

               MenuBar menuBar = new MenuBar();

               Menu menu = new Menu("file");

               //메뮤 아이템 생성

               MenuItem item = new MenuItem("open");

              

               menu.add(item);

               //메뉴 바에 메뉴 부착

               menuBar.add(menu);

               //프레임에 메뉴바 부착

               setMenuBar(menuBar);

 

 

 

17.Common Dialog

=>자주 사용하는 기능의 대화상자를 미리 만들어서 제공

=>awt에서는 FileDialog를 제공

많이 사용하는 것은 만들 필요 없다.

 

1)FileDialog의 생성자 - modal

FileDialog(Frame owner, Sring title, int mode): mode는 열기 대화상자인지 저장 대화상자로 만들것인지 결정 -FileDialog.LOAD, FileDialog.SAVE

save저장 load 열기 - 어떤 파일을 선택했는지 알아야 한다. 그래서 getFile()

 

2) FileDialog의 메소드

String getFile();//선택한 파일명 리턴

String getDirectory();//선택한 디렉토리명 리턴

 

String setFile(String file);//파일을 선택

String setDirectory(String directory);//디렉토리를 선택

 

               //파일 대화상자 밖에 안준다.

               FileDialog open = new FileDialog(this,"open",FileDialog.LOAD);

               //기본 디렉토리 설정

               open.setDirectory("c:\\");

               open.setVisible(true);//현재 디렉터리

               //선택한 파일 경로 출력하기

              System.out.println(open.getDirectory()+open.getFile());

               try {

                      BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(open.getDirectory()+open.getFile())));

                      String line = br.readLine();

                      System.out.println(line);

               } catch (Exception e1) {

               }

 

 

18.Layout

=>컨테이너에 컴포넌트를 배치하는 방법

=>Panel은 생성할 때 설정이 가능하고 Frame panel모두 setLayout메소드를 이용해서 변경도 가능

1)FlowLayout

=>Panel의 기본 배치 방법으로 가로 방향으로 컴포넌트를 배치하고 더 이상 공간이 없으면 아래쪽으로 배치

=>new FlowLayout()으로 생생

 

2)BorderLayout

=>Frame의 기본 배치 방법으로 동서남북 그리고 중앙에 하나의 컴포넌트만 배치하는 방법

add를 다른 옵션없이 사용하면 중앙에 1개만 배치됩니다.

=>각 방향에 배치를 할 때는 add(String 방향, Component component)로 배치

=>방향은 대소문자 구분을 함 (East, West, North,South, Center)

=>동서남북에 배치가 안되면 그 영역은 전부 Center의 영역

=>하나의 영역에 하나의 컴포넌트만 배치가 가능한데 컴포넌트를 Panel로 만들어서 배치하면 여러 개도 배치 가능

 

제목 : 제목입력란 (TextField)

내용 : 내용입력란 (TextArea)

 

public MainWindow() {

              

               //여러개의 컴포넌트들을 올려 놓을 있는 패널을 생성

               Panel northPanel = new Panel();

               //레이블과 텍스트 필드를 만들어서 패널에 배치

               //패털은 flowLayout이라서 순선대로 배치

               Label lblTitle = new Label("title");

               TextField txtTitle = new TextField(30);

               //화면에 보여지는 문자 설정

               txtTitle.setEchoChar('*');//작은 따옴표이다

               northPanel.add(lblTitle);

               northPanel.add(txtTitle);

              

               //프레임은 BorderLayout이라서 방향과 함께 배치

               //패널을 블록에 배치

               add("North" ,northPanel);

              

               Panel centerPanel = new Panel();

               Label lblContent = new Label("content");

               TextArea taContent = new TextArea(20,30);

               centerPanel.add(lblContent);

               centerPanel.add(taContent);

               add("Center",centerPanel);

              

               Panel southPanel = new Panel();

               //패널의 레이아웃을 변경

               //셀의 개수가 부족하면 행이나 열의 개수를 늘려서 배치

               southPanel.setLayout(new GridLayout(2,2));

               for(int i = 0; i < 9 ; i ++) {//4->9 할때 알아서 배치한다.

                      Button button = new Button("button"+i);

                      southPanel.add(button);

               }

               add("South" , southPanel);

              

               setTitle("게시물 입력");

               setLocation(100, 100);

               setSize(300, 400);

              

               //크기 변경을 못하게 설정

               setResizable(false);

               setVisible(true);

       }

 

 

3)GridLayout

=>격자()모양의 레이아웃

=>하나의 셀에 하나의 컴포넌트를 배치

=>add를 호출하면 순서래도 배치

=>셀이 부족하면 자동으로 늘어남

=>new GridLaout(int 행의 수 ,int 열의 수)로 만들어서 setLayout메소드에 대입

 

 

4)CardLayout

=>화면에 하나씩 겹쳐서 배치

 

5)null

=>지금까지의 레이아웃은 크기 조절이나 위치 조정을 못합니다.

=>레이아웃에  null을 설정하면 컴포턴트들의 위치나 크기를 조절할 수 있습니다.

=>위치나 크기를 조정 할 때 해상도나 전체 화면 크기를 고려해서 절대값보다는 상대적인 값으로 설정하는 것을 권장합니다.

=>화면에 배치되는 모든 컴포넌트들의 좌표와 크기를 설정해야 합니다.

 

반응형

'Study > Java' 카테고리의 다른 글

java-14  (0) 2020.10.04
java-13  (0) 2020.10.03
java-11  (0) 2020.10.01
java-10  (0) 2020.09.30
java-9  (0) 2020.09.29

+ Recent posts