본문 바로가기

언어/Java

[JAVA] 간단한 캐비닛 Swing프로그램

1. 구상

하나의 java 파일에 모든 코드를 넣었다.

원래는 여러 개의 class파일을 나눠서 값을 전달하고 전달받고 이런식으로 만들어보려고 했다.

하지만 값을 받는 도중에 오류가 발생해서 하나의 java파일에 코드를 작성했다.(제한된 기한 문제) 

다음에는 여러 개의 class로 나누고 값을 받는 방법을 찾아서 다시 게시할 예정이다.

또한, (private, public, protected, 디폴트)class들의 설명도 따로 게시할 예정이다.

 

2. 코드 설명

1) 라이브러리, 변수 설명

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.* 

javax.swing 패키지에 있는 모든 클래스를 현재 파일에서 사용할 수 있도록 가져온다. 그래픽 사용자 인터페이스(GUI)를 개발하기 위한 java라이브러리를 가져온다.


import java.awt.* 

java.awt 패키지에 있는 모든 클래스를 현재 파일에서 사용할 수 있도록 가져온다. 이 패키지는 이벤트 처리, 그래픽 등을 다루는 클래스를 제공한다.


import java.awt.event.ActionEvent;

ActionEvent는 버튼 클릭이나 메뉴 선택 등을 나타내는 이벤트 객체이다.


import java.awt.event.ActionListener;

ActionListener는 ActionEvent를 처리하기 위한 인터페이스이다.

예) 버튼을 눌렀을 때, 다음 페이지로 넘어가도록 만들거나 값을 저장, 변경 등을 할 수 있다.

class AI_Student_Info{ //학생의 id, pw, 선택한 캐비닛 자리 저장
    private String id, pw;
    private int seatRow, seatCol;
    public AI_Student_Info(String id, String pw){
        this.id = id;
        this.pw = pw;
    }
    public void setSeat(int row, int col) {
        this.seatRow = row;
        this.seatCol = col;
    }
    public int getSeat_ROW(){ return seatRow ;}
    public int getSeat_COL(){return seatCol;}
    public String getId(){ return id;}
    public String getPw(){ return pw;}
}

회원들의 값을 저장하는 클래스(AI_Student_Info)

앞에 게시한 console 프로그램처럼 회원들의 정보를 저장하도록 만들었다.

또한, 회원들의 정보를 볼 수 있도록 만들었다.

this를 쓰면 중복된 코드를 피하고 재사용을 할 수 있다.

int row, col;
int y = 45;
private int idx = 0;
public AI_Student_Info[] AI_Students = new AI_Student_Info[30];
private JTextField idText = new JTextField();
private JPasswordField pwText = new JPasswordField();
private JLabel id = new JLabel("아이디");
private JLabel pw = new JLabel("비밀번호");
private JButton LoginBtn = new JButton("로그인");
private JButton NewMemberBtn = new JButton("회원가입");
private JButton ReturnSeatBtn = new JButton("자리반납");
private JButton StudentBtn = new JButton("등록회원");
private JTextArea textArea = new JTextArea("등록학생 \n",100, 100);
private JButton ExitBtn = new JButton("종료");
private JLabel Cabinet = new JLabel("Cabinet");
private JLabel KnuCabinet = new JLabel("ooo C.S Program");

private  JButton [][] seatBtn = new JButton[4][4];
private String [][] seatBtn_text = {{"1","2","3","4"},{"5","6","7","8"},{"9","10","11","12"},{"13","14","15","16"}};

Cabinet_Swing에 필요한 버튼, 라벨 등을 선언했다.

setTitle("ooo Cabinet");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container c = getContentPane();
c.setLayout(null);

c.add(id);
id.setLocation(215,10);
id.setSize(60,30);

c.add(idText);
idText.setLocation(270,10);
idText.setSize(100,30);

c.add(pw);
pw.setLocation(215,45);
pw.setSize(60,30);

c.add(pwText);
pwText.setLocation(270,45);
pwText.setSize(100,30);

c.add(LoginBtn);
LoginBtn.setLocation(380,10);
LoginBtn.setSize(85,30);

c.add(NewMemberBtn);
NewMemberBtn.setLocation(380,45);
NewMemberBtn.setSize(85,30);

c.add(textArea);
JScrollPane scrollPane = new JScrollPane(textArea);
scrollPane.setBounds(10, 85, 360, 140);
c.add(scrollPane);

c.add(ReturnSeatBtn);
ReturnSeatBtn.setLocation(585,195);
ReturnSeatBtn.setSize(85,30);

c.add(StudentBtn);
StudentBtn.setLocation(380,85);
StudentBtn.setSize(85,70);

c.add(ExitBtn);
ExitBtn.setLocation(675,195);
ExitBtn.setSize(85,30);

c.add(Cabinet);
//Cabinet.setBackground(Color.magenta);
Cabinet.setLocation(580,10);
Cabinet.setSize(85,30);
Cabinet.setFont(new Font("Arial",Font.ITALIC,20));

c.add(KnuCabinet);
KnuCabinet.setLocation(10,30);
KnuCabinet.setSize(200,30);
KnuCabinet.setFont(new Font("Arial",Font.ITALIC,20));

//캐비닛 버튼 16개 생성
for (int i = 0; i < 4; i++) {
    int x = 480;
    for (int j = 0; j < 4; j++) {
        seatBtn[i][j] = new JButton();
        seatBtn[i][j].setText(seatBtn_text[i][j]);

        c.add(seatBtn[i][j]);
        seatBtn[i][j].setLocation(x, y);
        seatBtn[i][j].setSize(70, 30);
        x += 70;
    }
    y += 35;
}

setSize(780, 270);
setVisible(true);

앞에서 선언한 버튼, 라벨 등을 JFrame에 넣는다. 

배치관리자를 쓰면 편하지만 원하는 위치에 넣을 수가 없어서 일일히 배치를 했다.

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //창을 닫을 때, 프로그램도 종료
setSize(780, 270); //JFrame창 size
setVisible(true); // 보이도록 설정

이 코드를 까먹지 말자

위 코드로 실행하면 이 화면이 뜬다. 아직은 어떤 버튼을 누르던 아무런 이벤트가 발생하지 않는다.  

 

 

2) 로그인

//로그인 버튼
LoginBtn.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        String pw = pwText.getText();
        String id = idText.getText();

        boolean id_pw_equal = false;
        int log_in_overlap = -1;

        //로그인,비밀번호에 아무것도 입력하지 않았을 때
        if (id.length() == 0 && pw.length() == 0) {
            JOptionPane.showMessageDialog(null, "아이디와 비밀번호를 입력해주세요.", "Error", JOptionPane.ERROR_MESSAGE);
            return;
        }

        //저장된 id,pw가 입력한 값과 같은지 판단
        for (int i = 0; i < idx; i++) {
            if (AI_Students[i].getId().equals(id) && AI_Students[i].getPw().equals(pw)) {
                id_pw_equal = true;
                log_in_overlap = i;
                break;
            }
        }

        //바로 로그인할 때 오류메세지
        if (log_in_overlap == -1) {
            JOptionPane.showMessageDialog(null, "일치하는 아이디가 없습니다.", "Error", JOptionPane.ERROR_MESSAGE);
            return;
        }

        //한 개 아이디 당 한 개 캐비닛 배정
        if (AI_Students[log_in_overlap].getSeat_ROW() != 0 || AI_Students[log_in_overlap].getSeat_COL() != 0) {
            JOptionPane.showMessageDialog(null, "이미 사용 중인 캐비닛이 있습니다.", "Error", JOptionPane.ERROR_MESSAGE);
            return;

        } else {
            JOptionPane.showMessageDialog(null, "로그인 되었습니다. 자리를 선택해주세요.", "Message", JOptionPane.INFORMATION_MESSAGE);
        }

        //seatBtn버튼이 눌릴 때마다 눌린 횟수만큼 메세지가 뜸 -> 버튼 기능 초기화
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                for (ActionListener listener : seatBtn[i][j].getActionListeners()) {
                    seatBtn[i][j].removeActionListener(listener);
                }
            }
        }

        //자리 배정 코드
        if (id_pw_equal) {
            for (int i = 0; i < 4; i++) {
                for (int j = 0; j < 4; j++) {
                    int finalI = i;
                    int finalJ = j;
                    int finalLog_in_overlap = log_in_overlap;

                    seatBtn[i][j].addActionListener(new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                            JButton b = (JButton) e.getSource();

                            if (b == seatBtn[finalI][finalJ]) {
                                //다시 재배정 받을 떄, 로그인을 해주세요 문구가 뜸
                                if (AI_Students[finalLog_in_overlap].getSeat_ROW() != 0 || AI_Students[finalLog_in_overlap].getSeat_COL() != 0) {
                                }else {
                                    int seatNumber = finalI * 4 + finalJ + 1;
                                    int result = JOptionPane.showConfirmDialog(null, seatNumber + "번 캐비닛를 선택하시겠습니까?.", "Message", JOptionPane.YES_NO_OPTION);

                                    if (result == JOptionPane.YES_OPTION) {
                                        AI_Students[finalLog_in_overlap].setSeat(finalI, finalJ);
                                        seatBtn[finalI][finalJ].setEnabled(false);
                                        JOptionPane.showMessageDialog(null, seatNumber + "번 캐비닛에 배정되었습니다", "Message", JOptionPane.INFORMATION_MESSAGE);
                                    }
                                }
                            }
                        }
                    });
                }
            }
        }
        idText.setText("");
        pwText.setText("");
    }
});

2.1)

초기화면에서 로그인 버튼을 눌렀을 때, "아이디와 비밀번호를 입력해주세요."라는 문구를 뜨게 했다. 이 코드가 없으면 초기화면에서 로그인 버튼을 눌렀을 때, 오류가 발생할 것이다. 크기는 100으로 설정했지만 그 안에 아무런 정보가 없기 때문이다. 다른 버튼을 눌렀을 때에도 이 코드를 넣었다. 

//저장된 id,pw가 입력한 값과 같은지 판단
for (int i = 0; i < idx; i++) {
    if (AI_Students[i].getId().equals(id) && AI_Students[i].getPw().equals(pw)) {
        id_pw_equal = true;
        log_in_overlap = i;
        break;
    }
}

//바로 로그인할 때 오류메세지
if (log_in_overlap == -1) {
    JOptionPane.showMessageDialog(null, "일치하는 아이디가 없습니다.", "Error", JOptionPane.ERROR_MESSAGE);
    return;
}

2.2)

idtext, pwtext에 정보를 입력하지 않았을 때, 경고 메세지를 뜨게 했다.

//로그인,비밀번호에 아무것도 입력하지 않았을 때
if (id.length() == 0 && pw.length() == 0) {
    JOptionPane.showMessageDialog(null, "아이디와 비밀번호를 입력해주세요.", "Error", JOptionPane.ERROR_MESSAGE);
    return;
}

2.3)

중복로그인을 방지하기 위해서 배정된 캐비닛이 있으면 경고메세지를 뜨게 만들었다.

//한 개 아이디 당 한 개 캐비닛 배정
if (AI_Students[log_in_overlap].getSeat_ROW() != 0 || AI_Students[log_in_overlap].getSeat_COL() != 0) {
    JOptionPane.showMessageDialog(null, "이미 사용 중인 캐비닛이 있습니다.", "Error", JOptionPane.ERROR_MESSAGE);
    return;

} else {
    JOptionPane.showMessageDialog(null, "로그인 되었습니다. 자리를 선택해주세요.", "Message", JOptionPane.INFORMATION_MESSAGE);
}

2.4)

swing 프로그램을 만들고 나서 문제점이 발견했다. 예를 들어 2명이 회원가입과 로그인을 하면 첫 번째 회원이 로그인 할 때는 문제가 없었는데 두 번째 회원이 로그인 할 때, 배정메세지가 2번이 떴다. 이 부분을 해결하기 위해 눌린 버튼 횟수가 로그인 할 때 항상 초기화 될 수 있도록 했다.

배정 메세지가 2번 뜨는 이유는 앞에서 버튼을 만들 때, 버튼 하나당 코드를 만들지 않고 묶어서 만들었기 때문에 카운트가 되는 것 같다. 버튼 하나씩 코드를 만들 수 있지만 코드가 길어질 것 같아서 하나로 묶었다.

//seatBtn버튼이 눌릴 때마다 눌린 횟수만큼 메세지가 뜸 -> 버튼 기능 초기화
for (int i = 0; i < 4; i++) {
    for (int j = 0; j < 4; j++) {
        for (ActionListener listener : seatBtn[i][j].getActionListeners()) {
            seatBtn[i][j].removeActionListener(listener);
        }
    }
}

2.5)

위에 있는 코드가 잘 실행되었을 때, 캐비닛 선택을 할 수 있다.

-1번부터 16번 중에서 하나를 선택했을 때, 그때의 행과 열을 받아서 해당 자리를 다시 선택 못하게 했다. 

 

처음에는 자리반납을 하고 로그인을 하지 않아도 다시 자리를 선택할 수 있었다. 이 문제점을 해결하기 위해 자리반납을 하고 회원 id,pw를 입력을 해야지만 캐비닛을 선택할 수 있도록 만들었다. 

 

//자리 배정 코드
if (id_pw_equal) {
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            int finalI = i;
            int finalJ = j;
            int finalLog_in_overlap = log_in_overlap;

            seatBtn[i][j].addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    JButton b = (JButton) e.getSource();

                    if (b == seatBtn[finalI][finalJ]) {
                        //다시 재배정 받을 떄, 로그인을 해주세요 문구가 뜸
                        if (AI_Students[finalLog_in_overlap].getSeat_ROW() != 0 || AI_Students[finalLog_in_overlap].getSeat_COL() != 0) {
                        }else {
                            int seatNumber = finalI * 4 + finalJ + 1;
                            int result = JOptionPane.showConfirmDialog(null, seatNumber + "번 캐비닛를 선택하시겠습니까?.", "Message", JOptionPane.YES_NO_OPTION);

                            if (result == JOptionPane.YES_OPTION) {
                                AI_Students[finalLog_in_overlap].setSeat(finalI, finalJ);
                                seatBtn[finalI][finalJ].setEnabled(false);
                                JOptionPane.showMessageDialog(null, seatNumber + "번 캐비닛에 배정되었습니다", "Message", JOptionPane.INFORMATION_MESSAGE);
                            }
                        }
                    }
                }
            });
        }
    }
}

2.6)

캐비닛을 배정받은 후에 idtext, pwtext에 있는 회원 정보를 없애도록 했다.

idText.setText("");
pwText.setText("");

 

 

3) 로그아웃

 //자리반납 버튼
ReturnSeatBtn.addActionListener(new ActionListener() {
     @Override
     public void actionPerformed(ActionEvent e) {
         int log_out_index = -1;
         boolean sure_log_out = false;

         JButton b = (JButton) e.getSource();
         if (idText.getText().equals(0) || pwText.getText().equals(0)){
             JOptionPane.showMessageDialog(null, "아이디와 비밀번호를 입력해주세요.", "Message", JOptionPane.INFORMATION_MESSAGE);
             return;
         }else {
             String back_pw = pwText.getText();
             String back_id = idText.getText();

             for (int i = 0; i < idx; i++) {
                 if (AI_Students[i].getId().equals(back_id) &&AI_Students[i].getPw().equals(back_pw)){
                     log_out_index = i;
                     sure_log_out = true;
                     break;
                 }
             }
         }

         if (sure_log_out) {
             int result = JOptionPane.showConfirmDialog(null, " 현재 사용 중인 캐비닛을 반납하시겠습니까?.", "Message", JOptionPane.YES_NO_OPTION);
             if (result == JOptionPane.YES_OPTION) {
                 row = AI_Students[log_out_index].getSeat_ROW();
                 col = AI_Students[log_out_index].getSeat_COL();
                 seatBtn[row][col].setEnabled(true);
                 int seatNumber = row* 4 + col + 1;
                 JOptionPane.showMessageDialog(null, seatNumber +"번 캐비닛이 반납되었습니다.", "Message", JOptionPane.INFORMATION_MESSAGE);

                 for (int i = 0; i < 4; i++) {
                     for (int j = 0; j < 4; j++) {
                         for (ActionListener listener : seatBtn[i][j].getActionListeners()) {
                             seatBtn[i][j].removeActionListener(listener);
                         }
                     }
                 }
                 row=0; col=0;
                 AI_Students[log_out_index].setSeat(row,col);
                 idText.setText("");
                 pwText.setText("");
             }
         }else JOptionPane.showMessageDialog(null, "일치하는 정보가 없습니다.", "Message", JOptionPane.ERROR_MESSAGE);
     }
 });

3.1)

id, pw에 아무런 글자가 없는 경우에 id,pw를 입력하라는 메세지창을 뜨게 했다.

만약 회원정보를 입력하고 일치하는 회원 정보가 있을 때, sure_log_out이 true로 바뀐다.

또한 log_out_index에 그 회원의 정보가 몇 번째에 있는지 저장을 한다.(로그아웃하기 위해서 저장한다.)

if (idText.getText().equals(0) || pwText.getText().equals(0)){
    JOptionPane.showMessageDialog(null, "아이디와 비밀번호를 입력해주세요.", "Message", JOptionPane.INFORMATION_MESSAGE);
    return;
}else {
    String back_pw = pwText.getText();
    String back_id = idText.getText();

    for (int i = 0; i < idx; i++) {
        if (AI_Students[i].getId().equals(back_id) &&AI_Students[i].getPw().equals(back_pw)){
            log_out_index = i;
            sure_log_out = true;
            break;
        }
    }
}

3.2)

id, pw에 정보를 입력했을 때, AI_Student_Info에 저장된 회원의 정보를 찾아서 일치하면 로그아웃을 하고 만약 회원의 정보와 일치하지 않는 경우에는 "일치하는 정보가 없습니다"라는 에러메세지를 뜨게 만들었다.

else JOptionPane.showMessageDialog(null, "일치하는 정보가 없습니다.", "Message", JOptionPane.ERROR_MESSAGE);

3.3)

회원가입은 했지만 캐비닛 배정을 받지 않는 경우에 자리반납을 하면 "1번 캐비닛이 반납되었습니다"라는 문구가 뜰 것이다. 이 부분을 아직 만들지 못했다. 하지만 if문을 써서 로그인을 하지않는 회원이 자리반납을 했을 경우에 "배정된 캐비닛이 없습니다"라는 문구를 뜨게끔 코드를 만들면 해결될 것이다.

if (sure_log_out) {
    int result = JOptionPane.showConfirmDialog(null, " 현재 사용 중인 캐비닛을 반납하시겠습니까?.", "Message", JOptionPane.YES_NO_OPTION);
    if (result == JOptionPane.YES_OPTION) {
        row = AI_Students[log_out_index].getSeat_ROW();
        col = AI_Students[log_out_index].getSeat_COL();
        seatBtn[row][col].setEnabled(true);
        int seatNumber = row* 4 + col + 1;
        JOptionPane.showMessageDialog(null, seatNumber +"번 캐비닛이 반납되었습니다.", "Message", JOptionPane.INFORMATION_MESSAGE);

        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                for (ActionListener listener : seatBtn[i][j].getActionListeners()) {
                    seatBtn[i][j].removeActionListener(listener);
                }
            }
        }
        row=0; col=0;
        AI_Students[log_out_index].setSeat(row,col);
        idText.setText("");
        pwText.setText("");
    }
}else JOptionPane.showMessageDialog(null, "일치하는 정보가 없습니다.", "Message", JOptionPane.ERROR_MESSAGE);

 

 

4) 등록회원 보기

//등록학생 보기 버튼
StudentBtn.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        textArea.setText("");
        for (int i = 0; i < idx; i++) {
            textArea.append(Integer.toString(i+1)+"번 회원\n");
            textArea.append("아이디-> " + AI_Students[i].getId() + ", 비밀번호 -> " + AI_Students[i].getPw() + "\n");
            row= AI_Students[i].getSeat_ROW();
            col=AI_Students[i].getSeat_COL();
            int seatNum =row*4+col+1;
            if (col==0 && row ==0){
                textArea.append("배정된 캐비넷이 없습니다."+"\n");
            }else  textArea.append("현재 사용 중인 캐비닛은 " + seatNum + "번 입니다."+"\n");
        }
    }
});

4.1)

이 버튼을 누르면 textarea에 모든 회원정보가 뜬다. 이 부분을 다른 창에 띄워서 보도록 하려고 했지만 정보를 전달하고 받는 과정에서 오류가 있어서 한 창에 띄웠다.

4.2)

console프로그램에서는 행과 열로 캐비닛 자리를 출력하게 했지만 swing 프로그램에서는 행과 열을 계산해서 값을 1번부터 16번까지 값을 차례대로 배정했다.

예) 1행 1열 - >1번 캐비닛 

4.3)

회원가입은 했지만 캐비닛 배정을 받지 않는 회원이라면 "배정된 캐비닛이 없습니다"라는 문구를 뜨게했다.

 

 

5) 회원가입

//회원가입 버튼
NewMemberBtn.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        String id = idText.getText();
        String pw =  pwText.getText();
        if (id.length() == 0 || pw.length() == 0) {
            JOptionPane.showMessageDialog(null, "새로운 아이디와 비밀번호를 입력해주세요.", "Message", JOptionPane.ERROR_MESSAGE);
        } else {
            boolean isDuplicate = false;
            for (int i = 0; i < idx; i++) {
                if (AI_Students[i].getId().equals(id)) {
                    isDuplicate = true;
                    break;
                }
            }
            if (isDuplicate) {
                JOptionPane.showMessageDialog(null, "중복된 아이디입니다.", "Message", JOptionPane.ERROR_MESSAGE);
            } else {
                JOptionPane.showMessageDialog(null, "가입되었습니다.", "Message", JOptionPane.INFORMATION_MESSAGE);
                AI_Students[idx] = new AI_Student_Info(id, pw);
                idx++;
            }
        }
        idText.setText("");
        pwText.setText("");
    }
});

5.1)

console프로그램을 만들 때, 이미 가입되어 있던 아이디가 있으면 중복을 방지하기 위한 코드를 만들었다.

그 부분을 가져와 GUI스윙에 맞게 바꿨다. 

5.2)

id, pw에 아무런 글자가 없는 경우에 id,pw를 입력하라는 메세지창을 뜨게 했다. 

5.3)

회원가입 부분에서 idx를 쓴다. -> 회원을 저장할 수 있는 크기는 100명이고 idx가 0명부터 회원 정보를 저장한다.

 

6) 종료

//종료버튼
ExitBtn.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {

    int result = JOptionPane.showConfirmDialog(null, "종료하시겠습니까?","Message",JOptionPane.YES_NO_OPTION);

    if (result== JOptionPane.CLOSED_OPTION) {//메인 화면으로 돌아가는 코드
        } else if (result == JOptionPane.YES_OPTION) {System.exit(0);}
    }
});

6.1)

종료버튼을 누르면 "종료하시겠습니까?"라는 '예,아니오' 메세지 창이 뜬다. 이때 '예'를 누르면 프로그램이 종료된다.

 

 

전체코드

package src;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

class AI_Student_Info{ //학생의 id, pw, 선택한 캐비닛 자리 저장
    private String id, pw;
    private int seatRow, seatCol;
    public AI_Student_Info(String id, String pw){
        this.id = id;
        this.pw = pw;
    }
    public void setSeat(int row, int col) {
        this.seatRow = row;
        this.seatCol = col;
    }
    public int getSeat_ROW(){ return seatRow ;}
    public int getSeat_COL(){return seatCol;}
    public String getId(){ return id;}
    public String getPw(){ return pw;}
}
public class Cabinet_Swing extends JFrame {
    int row, col;
    int y = 45;
    private int idx = 0;
    public AI_Student_Info[] AI_Students = new AI_Student_Info[30];
    private JTextField idText = new JTextField();
    private JPasswordField pwText = new JPasswordField();
    private JLabel id = new JLabel("아이디");
    private JLabel pw = new JLabel("비밀번호");
    private JButton LoginBtn = new JButton("로그인");
    private JButton NewMemberBtn = new JButton("회원가입");
    private JButton ReturnSeatBtn = new JButton("자리반납");
    private JButton StudentBtn = new JButton("등록회원");
    private JTextArea textArea = new JTextArea("등록학생 \n",100, 100);
    private JButton ExitBtn = new JButton("종료");
    private JLabel Cabinet = new JLabel("Cabinet");
    private JLabel KnuCabinet = new JLabel("ooo C.S Program");

    private  JButton [][] seatBtn = new JButton[4][4];
    private String [][] seatBtn_text = {{"1","2","3","4"},{"5","6","7","8"},{"9","10","11","12"},{"13","14","15","16"}};

    public Cabinet_Swing() {// 메인 화면
        setTitle("KNU Cabinet");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Container c = getContentPane();
        c.setLayout(null);

        c.add(id);
        id.setLocation(215,10);
        id.setSize(60,30);

        c.add(idText);
        idText.setLocation(270,10);
        idText.setSize(100,30);

        c.add(pw);
        pw.setLocation(215,45);
        pw.setSize(60,30);

        c.add(pwText);
        pwText.setLocation(270,45);
        pwText.setSize(100,30);

        c.add(LoginBtn);
        LoginBtn.setLocation(380,10);
        LoginBtn.setSize(85,30);

        c.add(NewMemberBtn);
        NewMemberBtn.setLocation(380,45);
        NewMemberBtn.setSize(85,30);

        c.add(textArea);
        JScrollPane scrollPane = new JScrollPane(textArea);
        scrollPane.setBounds(10, 85, 360, 140);
        c.add(scrollPane);

        c.add(ReturnSeatBtn);
        ReturnSeatBtn.setLocation(585,195);
        ReturnSeatBtn.setSize(85,30);

        c.add(StudentBtn);
        StudentBtn.setLocation(380,85);
        StudentBtn.setSize(85,70);

        c.add(ExitBtn);
        ExitBtn.setLocation(675,195);
        ExitBtn.setSize(85,30);

        c.add(Cabinet);
        //Cabinet.setBackground(Color.magenta);
        Cabinet.setLocation(580,10);
        Cabinet.setSize(85,30);
        Cabinet.setFont(new Font("Arial",Font.ITALIC,20));

        c.add(KnuCabinet);
        KnuCabinet.setLocation(10,30);
        KnuCabinet.setSize(200,30);
        KnuCabinet.setFont(new Font("Arial",Font.ITALIC,20));

        //캐비닛 버튼 16개 생성
        for (int i = 0; i < 4; i++) {
            int x = 480;
            for (int j = 0; j < 4; j++) {
                seatBtn[i][j] = new JButton();
                seatBtn[i][j].setText(seatBtn_text[i][j]);

                c.add(seatBtn[i][j]);
                seatBtn[i][j].setLocation(x, y);
                seatBtn[i][j].setSize(70, 30);
                x += 70;
            }
            y += 35;
        }

        setSize(780, 270);
        setVisible(true);

        //로그인 버튼
        LoginBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String pw = pwText.getText();
                String id = idText.getText();

                boolean id_pw_equal = false;
                int log_in_overlap = -1;

                //로그인,비밀번호에 아무것도 입력하지 않았을 때
                if (id.length() == 0 && pw.length() == 0) {
                    JOptionPane.showMessageDialog(null, "아이디와 비밀번호를 입력해주세요.", "Error", JOptionPane.ERROR_MESSAGE);
                    return;
                }

                //저장된 id,pw가 입력한 값과 같은지 판단
                for (int i = 0; i < idx; i++) {
                    if (AI_Students[i].getId().equals(id) && AI_Students[i].getPw().equals(pw)) {
                        id_pw_equal = true;
                        log_in_overlap = i;
                        break;
                    }
                }

                //바로 로그인할 때 오류메세지
                if (log_in_overlap == -1) {
                    JOptionPane.showMessageDialog(null, "일치하는 아이디가 없습니다.", "Error", JOptionPane.ERROR_MESSAGE);
                    return;
                }

                //한 개 아이디 당 한 개 캐비닛 배정
                if (AI_Students[log_in_overlap].getSeat_ROW() != 0 || AI_Students[log_in_overlap].getSeat_COL() != 0) {
                    JOptionPane.showMessageDialog(null, "이미 사용 중인 캐비닛이 있습니다.", "Error", JOptionPane.ERROR_MESSAGE);
                    return;

                } else {
                    JOptionPane.showMessageDialog(null, "로그인 되었습니다. 자리를 선택해주세요.", "Message", JOptionPane.INFORMATION_MESSAGE);
                }

                //seatBtn버튼이 눌릴 때마다 눌린 횟수만큼 메세지가 뜸 -> 버튼 기능 초기화
                for (int i = 0; i < 4; i++) {
                    for (int j = 0; j < 4; j++) {
                        for (ActionListener listener : seatBtn[i][j].getActionListeners()) {
                            seatBtn[i][j].removeActionListener(listener);
                        }
                    }
                }

                //자리 배정 코드
                if (id_pw_equal) {
                    for (int i = 0; i < 4; i++) {
                        for (int j = 0; j < 4; j++) {
                            int finalI = i;
                            int finalJ = j;
                            int finalLog_in_overlap = log_in_overlap;

                            seatBtn[i][j].addActionListener(new ActionListener() {
                                @Override
                                public void actionPerformed(ActionEvent e) {
                                    JButton b = (JButton) e.getSource();

                                    if (b == seatBtn[finalI][finalJ]) {
                                        //다시 재배정 받을 떄, 로그인을 해주세요 문구가 뜸
                                        if (AI_Students[finalLog_in_overlap].getSeat_ROW() != 0 || AI_Students[finalLog_in_overlap].getSeat_COL() != 0) {
                                        }else {
                                            int seatNumber = finalI * 4 + finalJ + 1;
                                            int result = JOptionPane.showConfirmDialog(null, seatNumber + "번 캐비닛를 선택하시겠습니까?.", "Message", JOptionPane.YES_NO_OPTION);

                                            if (result == JOptionPane.YES_OPTION) {
                                                AI_Students[finalLog_in_overlap].setSeat(finalI, finalJ);
                                                seatBtn[finalI][finalJ].setEnabled(false);
                                                JOptionPane.showMessageDialog(null, seatNumber + "번 캐비닛에 배정되었습니다", "Message", JOptionPane.INFORMATION_MESSAGE);
                                            }
                                        }
                                    }
                                }
                            });
                        }
                    }
                }
                idText.setText("");
                pwText.setText("");
            }
        });
        //자리반납 버튼
       ReturnSeatBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                int log_out_index = -1;
                boolean sure_log_out = false;

                JButton b = (JButton) e.getSource();
                if (idText.getText().equals(0) || pwText.getText().equals(0)){
                    JOptionPane.showMessageDialog(null, "아이디와 비밀번호를 입력해주세요.", "Message", JOptionPane.INFORMATION_MESSAGE);
                    return;
                }else {
                    String back_pw = pwText.getText();
                    String back_id = idText.getText();

                    for (int i = 0; i < idx; i++) {
                        if (AI_Students[i].getId().equals(back_id) &&AI_Students[i].getPw().equals(back_pw)){
                            log_out_index = i;
                            sure_log_out = true;
                            break;
                        }
                    }
                }

                if (sure_log_out) {
                    int result = JOptionPane.showConfirmDialog(null, " 현재 사용 중인 캐비닛을 반납하시겠습니까?.", "Message", JOptionPane.YES_NO_OPTION);
                    if (result == JOptionPane.YES_OPTION) {
                        row = AI_Students[log_out_index].getSeat_ROW();
                        col = AI_Students[log_out_index].getSeat_COL();
                        seatBtn[row][col].setEnabled(true);
                        int seatNumber = row* 4 + col + 1;
                        JOptionPane.showMessageDialog(null, seatNumber +"번 캐비닛이 반납되었습니다.", "Message", JOptionPane.INFORMATION_MESSAGE);

                        for (int i = 0; i < 4; i++) {
                            for (int j = 0; j < 4; j++) {
                                for (ActionListener listener : seatBtn[i][j].getActionListeners()) {
                                    seatBtn[i][j].removeActionListener(listener);
                                }
                            }
                        }
                        row=0; col=0;
                        AI_Students[log_out_index].setSeat(row,col);
                        idText.setText("");
                        pwText.setText("");
                    }
                }else JOptionPane.showMessageDialog(null, "일치하는 정보가 없습니다.", "Message", JOptionPane.ERROR_MESSAGE);
            }
        });
        //등록학생 보기 버튼
        StudentBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                textArea.setText("");
                for (int i = 0; i < idx; i++) {
                    textArea.append(Integer.toString(i+1)+"번 회원\n");
                    textArea.append("아이디-> " + AI_Students[i].getId() + ", 비밀번호 -> " + AI_Students[i].getPw() + "\n");
                    row= AI_Students[i].getSeat_ROW();
                    col=AI_Students[i].getSeat_COL();
                    int seatNum =row*4+col+1;
                    if (col==0 && row ==0){
                        textArea.append("배정된 캐비넷이 없습니다."+"\n");
                    }else  textArea.append("현재 사용 중인 캐비닛은 " + seatNum + "번 입니다."+"\n");
                }
            }
        });
        //회원가입 버튼
        NewMemberBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String id = idText.getText();
                String pw =  pwText.getText();
                if (id.length() == 0 || pw.length() == 0) {
                    JOptionPane.showMessageDialog(null, "새로운 아이디와 비밀번호를 입력해주세요.", "Message", JOptionPane.ERROR_MESSAGE);
                } else {
                    boolean isDuplicate = false;
                    for (int i = 0; i < idx; i++) {
                        if (AI_Students[i].getId().equals(id)) {
                            isDuplicate = true;
                            break;
                        }
                    }
                    if (isDuplicate) {
                        JOptionPane.showMessageDialog(null, "중복된 아이디입니다.", "Message", JOptionPane.ERROR_MESSAGE);
                    } else {
                        JOptionPane.showMessageDialog(null, "가입되었습니다.", "Message", JOptionPane.INFORMATION_MESSAGE);
                        AI_Students[idx] = new AI_Student_Info(id, pw);
                        idx++;
                    }
                }
                idText.setText("");
                pwText.setText("");
            }
        });
        //종료버튼
        ExitBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {

            int result = JOptionPane.showConfirmDialog(null, "종료하시겠습니까?","Message",JOptionPane.YES_NO_OPTION);

            if (result== JOptionPane.CLOSED_OPTION) {//메인 화면으로 돌아가는 코드
                } else if (result == JOptionPane.YES_OPTION) {System.exit(0);}
            }
        });
    }
    public static void main(String[] args) {
        new Cabinet_Swing();
    }
}

3. 후기

앞에 게시했던 console 프로그램 보다 기능이 적지만 코드 길이는 비슷했다. 

Swing 프로그램을 만들고 난 후에 어떻게 하면 코드를 줄일 수 있을지 고민을 했다.

반복되는 코드는 줄이고 다른 class를 불러와서 필요할 때만 사용하는 방식으로 바꾸면 코드길이가 줄어들지 않을까?라는 생각을 했다. 다음 게시물을 올릴 때, 여러 개의 class로 나눠서 작성을 해봐야겠다. 

 

 오류

1) 회원 정보를 저장할 때, 메모장에 저장하고 수정하는 방식으로 해봤지만 회원정보를 수정할 때, 오류가 발생했다.

     (값을 출력할 때, 아무런 정보가 뜨지 않았다.)

     (회원 저장은 되지만 수정은 할 수 없다는 글이 있었다. -> 더 찾아봐야겠다.)

2) 회원정보를 저장한 후에 값을 불러오는 과정에서도 오류가 발생했다.