Clean & Blue 자세히보기

전공/전공 마스터리

자바 Swing 파일 복사 프로그램 진행바 / 스레드(Thread), JProgressBar

_청렴 2022. 9. 18. 22:13
반응형

이미지 파일을 복사하는 중

GUI 화면을 구성할 Main 클래스와

파일 복사 및 jProgressbar 진행바를 구현하기 위한 FileTransfer 클래스로 구성하였다.

진행바를 만들기 위해서는 jProgressBar를 이용해야 하고 GUI 화면에 보여주기 위해선 스레드를 이용해야 한다.

스레드를 이용하지 않으면 작업이 끝날때까지 아무런 변화가 없다가 작업이 끝날때만 한번에 변화된다.

때문에 스레드를 이용해 중간중간 sleep을 시켜줌으로써 화면에 뿌릴수 있게 텀을 주어야 한다.

 

 

- FileTransfer 클래스

public class FileTransfer
{

	String path = "";
	String save = "";
	JProgressBar bar;
	
	FileInputStream fin;
	FileOutputStream fout;
	
	void setBar(JProgressBar jbar)
	{
		this.bar = jbar;
	}
	
	void setPath(String path1)
	{
		path = path1;
	}
	
	void setSave(String save)
	{
		this.save = save;
	}

불러올 파일경로와 저장할 경로를 담을 path와 save를 String으로 준비한다.

Main에서 쓰일 JProgressBar의 레퍼런스를 담을 bar도 준비

그리고 파일 input/output 스트림도 준비한다.

그리고 각 멤버들을 초기화 해줄수 있는 메소드들도 준비해준다.

 

void fileTransfer()
{		
	path.replace("/", "\\"); // '/'를 인식할수 있게 '\\'로 치환해준다.
	save.replace("/", "\\");
	File file = new File(path);
	File to = new File(save);
		
	double fileSize = file.length(); // 복사할 파일의 사이즈를 불러옴
		
	new Thread(new Runnable() / 익명 클래스로 스레드를 생성한다.
	{	
		public void run()
		{
			try
			{
				fin = new FileInputStream(file); // 파일스트림 생성
				fout  = new FileOutputStream(to);
					
				int c = 0; 
				double size = 0;
				byte[] bytes = new byte[1024];
					
				while((c=fin.read(bytes)) != -1) 
				{
					fout.write(bytes, 0, c); // 파일 복사 진행
					
					size += c; //복사된 크기만큼 size에 더한다.
						
					bar.setValue((int)(size*100/fileSize)); //진행바 값 설정
					Thread.sleep(10); //잠시 sleep하여 화면에 진행바를 갱신한다.
				}
							
				fout.flush(); //미쳐 복사되지 못한 데이터 flush
				fin.close();
				fout.close();
					
			} catch(IOException e)
			{
				System.out.println("파일 입출력 오류");
			} catch (InterruptedException e) //이중 catch문
			{
				e.printStackTrace();
			}
		}
	}).start(); //익명 클래스이므로 바로 start()메소드로 실행해준다.
			
}

FileTransfer 클래스 내의 fileTransfer 메소드이다. 실제 파일을 복사할 기능을 할 메소드이다.

jvm은 '/'로 이루어진 경로명을 인식하지 못하니 5번 6번 라인에서 path와 save는 replace 메소드를 이용해 전부 '\\'로 치환해준다.

10번 라인에서 스레드를 익명클래스로 정의해주고 run() 메소드를 오버라이딩 해준다.

23번 라인에서는 while문을 이용해 파일을 bytes 단위로 읽어와 변수 c에 담아둔다.

그 이후 변수 c를 이용해 bytes 단위로 파일을 쓴다.

파일 쓰기가 된 만큼 변수 size에 누적하여 더한다. 이는 진행바를 표현할 때 이용된다.

29번 라인에서는 진행바 bar의 값을 세팅해준다. size(현재 복사된 파일 사이즈)를 fileSize(총 복사할 파일 사이즈)로 나눈뒤 100을 곱하여 백분율로 표기한다.

그 이후 약간의 sleep()을 이용해 화면에 여태까지 작업된 bar의 상태를 갱신하여 뿌려준다.

fileTransfer 해당 메소드가 실행될때 위 작업이 진행되야 하기 때문에 익명 클래스로 스레드를 선언했기 때문에 45번라인에서 start() 메소드를 실행해준다.

 

 

- Main 클래스

public class Main extends JFrame
{
	Container contentPane;
	JFileChooser fileChooser;
	String pathName;
	String savePath;
	
	FileTransfer tf = new FileTransfer(); //파일 복사를 진행할 인스턴스
	
	JTextField beforeTf = new JTextField(15);
	JTextField afterTf = new JTextField(15);
	
	JProgressBar bar = new JProgressBar(0, 100); // 진행바
	
	public Main()
	{
		setTitle("스레드를 이용한 파일 복사 프로그램");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		contentPane = getContentPane();
		contentPane.setLayout(new FlowLayout());
		

		beforeTf.setFont(new Font("고딕체", Font.ITALIC, 25));
		beforeTf.setEditable(false);
		
		JButton fileBtn = new JButton("File");
		fileBtn.addMouseListener(new FileListener());
		
		
		
		afterTf.setFont(new Font("고딕체", Font.ITALIC, 25));
		afterTf.setEditable(false);
		
		JButton saveBtn = new JButton("save");
		saveBtn.addMouseListener(new SaveListener());
		
		bar.setValue(0); // 진행바 초기값 설정
		bar.setForeground(Color.green); // 진행바 전경색 설정
		bar.setStringPainted(true); // 진행바에 진행 숫자 표기
		
		contentPane.add(beforeTf);
		contentPane.add(fileBtn);
		contentPane.add(afterTf);
		contentPane.add(saveBtn);
		contentPane.add(bar);
		
		setLocationByPlatform(true);
		setVisible(true);
		setSize(500, 350);
	}
	
	class FileListener extends MouseAdapter //복사할 파일을 찾기 위한 액션리스너
	{
		public void mouseClicked(MouseEvent e)
		{
			fileChooser = new JFileChooser();
			fileChooser.setCurrentDirectory(new File("C:\\Users\\aapsl\\Desktop"));
			FileNameExtensionFilter filter = new FileNameExtensionFilter("images", "jpg", "gif", "png");
			// 파일 필터를 이미지로 제한한다.
            
			fileChooser.setFileFilter(filter);
			
			int ret = fileChooser.showOpenDialog(null);
			
			if(ret == JFileChooser.APPROVE_OPTION)
			{
				pathName = fileChooser.getSelectedFile().getPath();
				beforeTf.setText(pathName);
				
				tf.setPath(pathName);
			}	
		}
	}
	
	class SaveListener extends MouseAdapter // 복사될 파일을 저장할 경로를 설정할 액션리스너
	{
		public void mouseClicked(MouseEvent e)
		{
			fileChooser = new JFileChooser();
			fileChooser.setCurrentDirectory(new File("C:\\Users\\aapsl\\Desktop"));
			FileNameExtensionFilter filter = new FileNameExtensionFilter("images", "jpg", "gif", "png");
			fileChooser.setFileFilter(filter);
			
			int ret = fileChooser.showSaveDialog(null);
			
			if(ret == JFileChooser.APPROVE_OPTION)
			{
				savePath = fileChooser.getSelectedFile().getPath();
				afterTf.setText(savePath);
				
				tf.setSave(savePath);
				tf.setBar(bar);
				tf.fileTransfer(); // 파일 복사 진행
			}	
			
		}
	}
	
	public static void main(String[] args)
	{
		new Main();
	}
}

GUI 화면과 각 버튼의 액션리스너 등을 구현한 Main 클래스이다.

FileTransfer 클래스의 인스턴스 tf 를 이용해 마우스리스너에서 해당 동작들이 진행되게끔 했다.

 

- JProgressBar

setValue(int init) : 진행바 초기값 설정

setForeground(Color.green) : 진행바 전경색 설정
setStringPainted(true) : 진행바에 진행 숫자 표기