기록
day 0603 메모장 본문
package com.kosta.exam01;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileReader;
import java.io.FileWriter;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class NotePad extends JFrame {
JTextArea jta;
public NotePad() {
// setTitle("메모장");
super("메모장");
jta = new JTextArea();
JScrollPane jsp = new JScrollPane(jta);
add(jsp);
JMenuBar jmb = new JMenuBar();
JMenu mn_file = new JMenu("파일");
JMenuItem file_new = new JMenuItem("새파일");
JMenuItem file_open = new JMenuItem("열기");
JMenuItem file_save = new JMenuItem("저장");
mn_file.add(file_new);
mn_file.add(file_open);
mn_file.add(file_save);
jmb.add(mn_file);
setJMenuBar(jmb);
setSize(400,300);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
file_new.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
System.out.println("새파일");
}
});
file_open.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
System.out.println("열기");
try {
FileReader fr = new FileReader("c:/data/memo.txt");
int ch;
String data = "";
while( (ch = fr.read()) != -1 ) {
data += (char)ch;
}
jta.setText(data);
}catch (Exception ex) {
System.out.println("예외발생:"+ex.getMessage());
}
}
});
file_save.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
System.out.println("저장");
String data = jta.getText();
System.out.println(data);
try {
FileWriter fw = new FileWriter("c:/data/memo.txt");
fw.write(data);
fw.close();
System.out.println("파일을 생성하였습니다.");
}catch (Exception ex) {
System.out.println("예외발생:"+ex.getMessage());
}
}
});
}
public static void main(String[] args) {
new NotePad();
}
}
/while문에 append 사용하기/
int ch;
while( (ch = fr.read()) != -1 ) {
jta.append( (char)ch + "" );
}
/while문에 StringBuffer 사용하기/
int ch;
StringBuffer data = new StringBuffer();
while( (ch = fr.read()) != -1 ) {
data.append((char)ch);
}
jta.setText( data.toString() );
- JFile Chooser : 메모장 파일 저장/열기 할 때 파일선택 하기
- 저장하기 : showDialog
- 열기 : showOpenDialog
file_save.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
System.out.println("저장");
String data = jta.getText();
System.out.println(data);
int re =jfc.showSaveDialog(null);
if(re == 0){
try{
FileWriter fw = new FileWriter(jfc.getSelectedFile());
fw.write(data);
fw.close();
System.out.println("파일을 생성하였습니다.");
}catch(Exception ex){
System.out.println("예외 발생 : " + ex.getMessage());
}
}
}
});
file_open.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
System.out.println("열기");
int re = jfc.showOpenDialog(null);
if(re == 0) {
try {
FileReader fr = new FileReader("c:/data/memo.txt");
int ch;
String data = "";
while( (ch = fr.read()) != -1 ) {
data += (char)ch;
}
jta.setText(data);
}catch (Exception ex) {
System.out.println("예외발생:"+ex.getMessage());
}
}
}
});
/JOptionPane.showConfirmDialog : 사용자에게 메세지 알려주기/
if(re == 0){
try{
FileWriter fw = new FileWriter(jfc.getSelectedFile());
fw.write(data);
fw.close();
JOptionPane.showConfirmDialog(null, "파일을 생성하였습니다.");
}catch(Exception ex){
System.out.println("예외 발생 : " + ex.getMessage());
}
}
/새파일 누르면 지워주기/
새파일 케이스가 다양하다
저장 안하고 새파일 - 저장할건지 묻는다(파일명이 있는가, 없는가)
저장 하고 새파일 - 텍스트가 지워진다
메모 열기 후 새파일 - 텍스트가 지워진다 등..
file_new.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
System.out.println("새파일");
// 텍스트 지워주기
jta.setText(" ");
}
});
/새파일 기능 추가하기/
저장하기 기능은 새피일, 열기에 필요하기때문에 메소드로 만든다
import java.io.File;
public class NotePad5 extends JFrame {
File file; // getSelectedFile()를 위한 멤버변수 생성
}
public void saveFile() {
System.out.println("저장");
String data = jta.getText();
System.out.println(data);
int re =jfc.showSaveDialog(null);
if(re == 0){
try{
FileWriter fw = new FileWriter(jfc.getSelectedFile());
fw.write(data);
fw.close();
JOptionPane.showConfirmDialog(null, "파일을 생성하였습니다.");
}catch(Exception ex){
System.out.println("예외 발생 : " + ex.getMessage());
}
}
}
file_save.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// 저장하기를 메소드로 옮긴 후 호출하기
saveFile();
}
});
}
예: 0 아니오: 1 취소: 2
예 : 변경된 내용 저장 -> 새파일
아니오 : 변경된 내용 저장안함 -> 새파일
취소 : 새파일을 취소
file_new.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// 변경된 내용이 있으면 "저장 하시겠습니까?" 라고 물어 보도록 한다
if(isNew) {
// 예: 0 아니오: 1 취소: 2
int re = JOptionPane.showConfirmDialog(null, "변경된 내용을 저장 하시겠습니까?");
// 새파일을 취소
if(re == 2) {return;}
// 저장하고 새파일
if(re == 0) {saveFile();}
}
// 텍스트 지워주기
jta.setText(" ");
// 새파일 했으므로 file에 null을 설정
file = null;
// 새파일 했으므로 작업표시줄에 "제목 없음" 설정
setTitle("제목 없음");
}
});
/스크롤 만들기/
package com.kosta.exam02;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class NotePad extends JFrame {
JTextArea jta;
public NotePad(){
jta = new JTextArea();
// 스크롤 만들기 (jta)를 감싸서 만든다
JScrollPane jsp = new JScrollPane(jta);
add(jsp);
setSize(400,300);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new NotePad();
}
}
/화면 구성하기/
package com.kosta.exam02;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class NotePad extends JFrame {
JTextArea jta;
public NotePad(){
jta = new JTextArea();
// 스크롤 만들기 (jta)를 감싸서 만든다
JScrollPane jsp = new JScrollPane(jta);
add(jsp);
// 메뉴바
JMenuBar jmb = new JMenuBar();
// 주메뉴
JMenu mn_file = new JMenu("파일");
// 부메뉴
JMenuItem file_new = new JMenuItem("새파일");
JMenuItem file_open = new JMenuItem("열기");
JMenuItem file_save = new JMenuItem("저장");
// 주메뉴에 담기
mn_file.add(file_new);
mn_file.add(file_open);
mn_file.add(file_save);
// 주메뉴를 메뉴바에 담기
jmb.add(mn_file);
// 프레임 설정
setJMenuBar(jmb);
setSize(400,300);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new NotePad();
}
}
** 전체 코드 **
package com.kosta.exam02;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class NotePad extends JFrame {
JTextArea jta;
// 파일열기,저장 할 때 파일을 선택하기위한 대화상자의 변수를 멤버변수로 선언
JFileChooser jfc;
// 현재 작업하고 있는 파일을 참조 할 변수 선언
File file;
// 파일에 변경된 내용이 있는지 판별하기위한 변수를 선언
// 파일을 저장하거나 열어온 즉시 그때는 변경된 내용이 없는 상태니까
// isNew에 false 저장
// 텍스트 에리어에 글씨를 한글자라도 써지면 isNew에 true를 저장
boolean isNew;
// 파일을 저장하기위한 메소드
public void saveFile() {
// 파일로 저장 할 문자열을 갖고온다
String data = jta.getText();
// 이미 파일이 열려있으면 파일선택 대화상자를 열지 않고
// 무조건 저장해야하기 때문에 0으로 기본값을 줍니다
int re = 0;
if(file == null) {
// 어떤 이름으로 저장할지 대화상자를 띄운다 Chooser
// 저장: 0 취소: 1
re = jfc.showSaveDialog(null);
// 대화상자에서 "저장"을 눌렀으면 저장을 시킨다
if(re == 0) {
// 대화상자에 입력한 파일 정보를 갖고와서 file 변수에 저장
file = jfc.getSelectedFile();
}
}
// 이미 파일이 오픈되어있거나 파일저장 대화상자에서
// "저장"을 눌렀다면 파일에 저장합니다
if(re == 0) {
try {
// 문자단위의 파일 출력을위한 객체를 생성
// 대화상자에서 입력한 파일의 정보를 매개변수로 전달한다
FileWriter fr = new FileWriter(file);
// 파일로 내용을 출력한다
fr.write(data);
//파일 출력 작업이 끝나면 파일을 닫아준다
fr.close();
// 파일이 성공적으로 저장되었다는 메세지를 출력
JOptionPane.showMessageDialog(null , "파일에 저장하였습니다.");
// 저장할 파일명을 타이틀바에 설정
setTitle(file.getName());
// 방금 저장했으므로 변경된 내용이 없다는 표시로 isNew에 false를 설정
isNew = false;
}catch (Exception e) {
System.out.println("예외발생 : " + e.getMessage());
}
}
}
public NotePad(){
setTitle("제목 없음");
// JFileChooser 객체 생성
// 매개변수로 작업 디렉토리를 전달한다 c:/data
jfc = new JFileChooser("c:/data");
jta = new JTextArea();
// 스크롤 만들기 (jta)를 감싸서 만든다
JScrollPane jsp = new JScrollPane(jta);
add(jsp);
// 메뉴바
JMenuBar jmb = new JMenuBar();
// 주메뉴
JMenu mn_file = new JMenu("파일");
// 부메뉴
JMenuItem file_new = new JMenuItem("새파일");
JMenuItem file_open = new JMenuItem("열기");
JMenuItem file_save = new JMenuItem("저장");
// 주메뉴에 담기
mn_file.add(file_new);
mn_file.add(file_open);
mn_file.add(file_save);
// 주메뉴를 메뉴바에 담기
jmb.add(mn_file);
// 프레임 설정
setJMenuBar(jmb);
setSize(400,300);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 텍스트에리어에 키이벤트로 등록
jta.addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
// 글씨가 한글자라도 써지면 isNew를 설정하여
// 변경된 내용이 있다 라고 표시
isNew = true;
}
@Override
public void keyPressed(KeyEvent e) {
}
});
file_new.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//텍스트에리어에 저장되지 않는 변경된 내용이 있으면
//"저장하시겠습니까?"라고 물어본다
if(isNew) {
int re= JOptionPane.showConfirmDialog(null, "변경된 내용을 저장하시겠습니까?");
//0:예, 1:아니오, 2:취소
if(re == 2) {return;}
if(re == 0) {saveFile();}
}
// 새파일을 누르면 텍스트에리어를 깨끗이 해요
jta.setText("");
// 새파일을 했으므로 file에 null을 설정
file = null;
// 새파일을 했으므로 제목표시줄에 "제목없음"으로 설정
setTitle("제목없음");
}
});
file_open.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//열어올 파일을 선택하기 위한 대화상자
// 열기: 0 취소: 1
int re = jfc.showOpenDialog(null);
// 열기를 눌렀으면 열어오는 동작을 하도록 한다
if(re == 0) {
// 파일열기 대화상자에서 선택한 파일의 정보를 file변수에 저장
file = jfc.getSelectedFile();
try{
// 문자단위 파일의 내용을 컴퓨터 메모리로 읽어들이기 위한 객체를 생성
// 파일열기 대화상자에서 선택한 파일을 매개변수로 전달
FileReader fr = new FileReader(file);
// 파일로부터 한글자씩 읽어들이기 위한 변술를 선언
int ch;
// 파일의 전체내용을 저장하기위한 변수를 선언
String data = " ";
// 파일이 끝이 아닐때까지 읽어들여 data에 저장
while((ch = fr.read()) != -1) {
data +=(char)ch + " ";
}
// 파일로부터 읽어들인 전체 문자열 data를 텍스트에리어에 설정
jta.setText(data);
// 파일을 닫아줍니다
fr.close();
// 열어온 파일명을 타이틀바에 설정
setTitle(file.getName());
// 방금 파일을 읽어 왔으므로 변경된 내용이
// 없다는 표시로 isNew에 false설정
isNew = false;
}catch (Exception ex) {
System.out.println("예외 발생 : " + ex.getMessage());
}
}
}
});
file_save.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
saveFile();
}
});
}
public static void main(String[] args) {
new NotePad();
}
}
14:00 ~
/가장 최근에 수정된 날짜/
/파일의 길이를 반환/
/파일 반환, 파일의 배열 반환/
package com.kosta.exam02;
import java.io.File;
public class FileTest {
public static void main(String[] args) {
// c:/data/.. 파일을 삭제하는 프로그램을 만들어 봅시다
File file = new File("c:/data/menu.txt");
System.out.println("3초뒤에 파일이 삭제됩니다.");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
file.delete();
}
}
/파일 목록 보기/
package com.kosta.exam02;
import java.io.File;
public class FileTest02 {
public static void main(String[] args) {
File file = new File("c:/data");
String[] list = file.list();
for(String fname : list) {
System.out.println(fname);
}
}
}
/화면 구성하기/
package com.kosta.exam02;
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class FileTest03 extends JFrame {
JList<String> list;
JTextArea jta;
public FileTest03() {
String[] arr = {"사과", "포도", "수박"};
list = new JList<String>(arr);
JScrollPane jsp_list = new JScrollPane(list);
jta = new JTextArea();
JScrollPane jsp_jta= new JScrollPane(jta);
add(jsp_list, BorderLayout.WEST);
add(jsp_jta, BorderLayout.CENTER);
setSize(200,300);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new FileTest03();
}
}
public FileTest03() {
String[] arr;
// c드라이브 data를 읽어와서
File dir = new File("c:/data");
// arr에 넣는다
arr = dir.list();
list = new JList<String>(arr);
JScrollPane jsp_list = new JScrollPane(list);
..
/두번 나와서 mouseReleased 에../
list.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
String fname = list.getSelectedValue();
System.out.println(fname);
}
});
list.addMouseListener(new MouseListener() {
@Override
public void mouseReleased(MouseEvent e) {
String fname = list.getSelectedValue();
System.out.println(fname);
}
});
package com.kosta.exam02;
import java.awt.BorderLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class FileTest03 extends JFrame {
JList<String> list;
JTextArea jta;
Vector<String > v;
public FileTest03() {
v = new Vector<String>();
String[] arr;
// c드라이브 data를 읽어와서
File dir = new File("c:/data");
// arr에 넣는다
arr = dir.list();
for(String fname : arr) {
// 배열에서 txt, java파일만 담는다 (확장자가 ".txt"로 끝난다)
if(fname.endsWith(".txt") || fname.endsWith(".java")) {
v.add(fname);
}
}
// Vector에 담아 list로 만든다
list = new JList<String>(v);
JScrollPane jsp_list = new JScrollPane(list);
jta = new JTextArea();
JScrollPane jsp_jta= new JScrollPane(jta);
add(jsp_list, BorderLayout.WEST);
add(jsp_jta, BorderLayout.CENTER);
setSize(300,300);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
list.addMouseListener(new MouseListener() {
@Override
public void mouseReleased(MouseEvent e) {
String fname = list.getSelectedValue();
FileReader fr = null;
try {
fr = new FileReader("c:/data/" + fname);
int ch;
String data = " ";
while((ch = fr.read()) != -1) {
data += (char)ch + " ";
}
jta.setText(data);
fr.close();
}catch (Exception ex) {
System.out.println("예외발생 : " + ex.getMessage());
}finally {
if(fr != null) {
try {
fr.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseClicked(MouseEvent e) {
int cnt = e.getClickCount();
if(cnt == 2){
File file = new File("c:/data/" + list.getSelectedValue());
file.delete();
jta.setText("");
File dir = new File("c:/data");
String []arr= dir.list();
//벡터를 깨끗이 비워준다
v.clear();
for(String fname :arr) {
if(fname.endsWith(".txt") || fname.endsWith(".java")) {
v.add(fname);
}
}
//벡터의 내용이 바뀌었으니 리스트를 다시 그려줄 것을 요청
list.updateUI();
}
}
});
}
public static void main(String[] args) {
new FileTest03();
}
}
/더블클릭하면 삭제/
/JComboBox/
package com.kosta.exam02;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class JComboBoxTest extends JFrame {
JComboBox<String> jcb;
JLabel jlb;
public JComboBoxTest() {
jcb = new JComboBox<String>();
jcb.addItem("사과");
jcb.addItem("포도");
jcb.addItem("수박");
jcb.addItem("딸기");
jcb.addItem("오렌지");
jlb = new JLabel();
add(jcb, BorderLayout.NORTH);
add(jlb, BorderLayout.CENTER);
setSize(400,300);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jcb.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String item = (String) jcb.getSelectedItem();
jlb.setText(item + "을(를) 선택하였습니다." );
}
});
}
public static void main(String[] args) {
new JComboBoxTest();
}
}
/JButton image 넣기/
package com.kosta.exam02;
import java.awt.FlowLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
public class ImageButton extends JFrame {
ImageIcon icon;
ImageIcon icon2;
ImageIcon icon3;
JButton btn;
public ImageButton() {
icon = new ImageIcon("apple.png");
icon2 = new ImageIcon("kiwi.png");
icon3 = new ImageIcon("watermelon.png");
btn = new JButton(icon);
// 마우스가 올라가면
btn.setRolloverIcon(icon2);
// 마우스 클릭하면
btn.setPressedIcon(icon3);
setLayout(new FlowLayout());
add(btn);
setSize(200,200);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new ImageButton();
}
}
/콤보박스에서 선택한 이미지를 라벨에 출력하기/
package com.kosta.exam02;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class JComboBoxImageLabelTest extends JFrame {
// 콤보박스에 선택한 이미지를 라벨에 출력 해 봅니다
JComboBox<String> jcb;
JLabel jlb;
JButton btn;
ImageIcon icon;
ImageIcon icon2;
ImageIcon icon3;
ImageIcon icon4;
ImageIcon icon5;
public JComboBoxImageLabelTest() {
jcb = new JComboBox<String>();
icon = new ImageIcon("apple.png");
icon2 = new ImageIcon("kiwi.png");
icon3 = new ImageIcon("lemon.png");
icon4 = new ImageIcon("watermelon.png");
icon5 = new ImageIcon("melon.png");
jcb.addItem("사과");
jcb.addItem("키위");
jcb.addItem("레몬");
jcb.addItem("수박");
jcb.addItem("메론");
jlb = new JLabel();
// 기본 이미지 설정
jlb.setIcon(icon);
jcb.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String fruit = (String) jcb.getSelectedItem();
switch (fruit) {
case "사과": jlb.setIcon(icon); break;
case "키위": jlb.setIcon(icon2); break;
case "레몬": jlb.setIcon(icon3); break;
case "수박": jlb.setIcon(icon4); break;
case "메론": jlb.setIcon(icon5); break;
default: break;
}
}
});
add(jcb, BorderLayout.NORTH);
add(jlb, BorderLayout.CENTER);
setSize(200,200);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new JComboBoxImageLabelTest();
}
}
** 6월 7일 평가시험 **
- 오늘 학습한 내용에 대하여 요약/정리하고 궁금한 점 질문합니다
- 요약 및 정리가 끝난 사람들은 5월 24일 실습의 그림판 프로그램에 "새파일" 기능을 구현 해 봅니다
// JFrame 기능 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Frame에서 구현하기
java.awt.event.WindowEvent
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
dispose();
}
});
'📖' 카테고리의 다른 글
day 0605 데이터베이스 연결 프로그래밍 (0) | 2024.06.05 |
---|---|
day 0604 네트워크 프로그래밍 (2) | 2024.06.04 |
day 0531 GUI 연습 (0) | 2024.05.31 |
day 0530 멀티쓰레드_임계영역_쓰레드사이의 통신 (0) | 2024.05.30 |
day 0529 멀티쓰레드 (1) | 2024.05.29 |