본문 바로가기
Java

[JAVA] Swing 라이브러리를 사용하여 디지털 시계를 만들기

by teamnova 2023. 11. 14.

안녕하세요. 이번 게시글은 Java에서 다중 Thread와 Swing을 이용해 현재 날짜, 요일, 시간을 띄우는 예제입니다.

 

아래는 시연영상입니다.

다음은 코드 설명입니다.

  1. ClockFrame:
    • 이 클래스는 프로그램의 메인 GUI를 표시하는 창입니다.
    • 여기서 우리는 현재의 시간과 날짜를 가져와서 그것을 기반으로 레이블을 설정합니다. 이렇게하면 프로그램이 시작될 때 현재 시간부터 시계가 시작됩니다.
    • 각 시, 분, 초는 자신의 스레드에서 동작하여 정해진 간격마다 해당 값을 업데이트합니다.
  2. TimeRunnable:
    • 이 클래스는 각 시, 분, 초를 업데이트하는 작업을 수행합니다.
    • 스레드가 시작되면 run 메소드가 호출되며, 이 메소드는 무한히 실행되면서 정해진 간격마다 시간 값을 업데이트합니다.
    • 주어진 timeUnitGetter 함수를 사용하여 현재 시간의 시, 분, 초 중 필요한 값을 가져옵니다.
// Java Swing (GUI 라이브러리)와 날짜/시간 관리 라이브러리를 가져옵니다.
import javax.swing.*;
import java.awt.*;
import java.time.LocalDateTime;
import java.time.format.TextStyle;
import java.util.Locale;

// ClockFrame JFrame을 확장하여 GUI 창을 표시합니다.
public class ClockFrame extends JFrame{
// 생성자에서 GUI 요소들을 초기화하고 배치합니다.
public ClockFrame(){
// 창이 닫힐 때 프로그램이 종료되도록 설정합니다.
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// GUI 컴포넌트들이 가로로 배치되게 FlowLayout을 사용합니다.
setLayout(new FlowLayout());

// 현재 시간을 가져옵니다.
LocalDateTime now = LocalDateTime.now();

// 현재 날짜와 요일을 표시하는 레이블을 생성하고 추가합니다.
JLabel dateLabel = new JLabel(now.getYear() + " " + now.getMonthValue() + " " + now.getDayOfMonth() + " " + now.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.getDefault()));
dateLabel.setFont(new Font("Helvetica", Font.BOLD, 20));
dateLabel.setHorizontalAlignment(JLabel.CENTER);
add(dateLabel);

// 현재 시간을 표시하는 레이블들을 생성하고 추가합니다.
JLabel hoursLabel = new JLabel(String.format("%02d", now.getHour()));
hoursLabel.setFont(new Font("Helvetica", Font.BOLD, 80));
hoursLabel.setHorizontalAlignment(JLabel.CENTER);
add(hoursLabel);

JLabel minutesLabel = new JLabel(String.format("%02d", now.getMinute()));
minutesLabel.setFont(new Font("Helvetica", Font.BOLD, 80));
minutesLabel.setHorizontalAlignment(JLabel.CENTER);
add(minutesLabel);

JLabel secondsLabel = new JLabel(String.format("%02d", now.getSecond()));
secondsLabel.setFont(new Font("Helvetica", Font.BOLD, 80));
secondsLabel.setHorizontalAlignment(JLabel.CENTER);
add(secondsLabel);

// 창의 크기를 설정하고 보이게 만듭니다.
setSize(750, 200);
setVisible(true);

// 각 시, , 초에 대한 스레드를 시작합니다.
Thread hourThread = new Thread(new TimeRunnable(hoursLabel, 3600000, LocalDateTime::getHour));
Thread minuteThread = new Thread(new TimeRunnable(minutesLabel, 60000, LocalDateTime::getMinute));
Thread secondThread = new Thread(new TimeRunnable(secondsLabel, 1000, LocalDateTime::getSecond));

hourThread.start();
minuteThread.start();
secondThread.start();
}

public static void main(String[] args) {
// 프로그램을 시작하면 ClockFrame 객체를 생성하여 실행합니다.
new ClockFrame();
}
}

// TimeRunnable Runnable 인터페이스를 구현하여 스레드로 실행될 수 있게 합니다.
class TimeRunnable implements Runnable{
JLabel label; // 시간을 표시할 레이블
int interval; // 얼마나 자주 시간을 업데이트할지 결정하는 간격 (밀리초 단위)
java.util.function.Function<LocalDateTime, Integer> timeUnitGetter; // , , 초 중 어느 것을 가져올지 결정하는 함수

// 생성자에서 필요한 정보를 초기화합니다.
public TimeRunnable(JLabel label, int interval, java.util.function.Function<LocalDateTime, Integer> timeUnitGetter){
this.label = label;
this.interval = interval;
this.timeUnitGetter = timeUnitGetter;
}

@Override
public void run(){
// run 메소드는 스레드가 시작되면 호출됩니다.
while(true){
try{
// 지정된 간격만큼 스레드를 잠재웁니다.
Thread.sleep(interval);
}catch(InterruptedException e){
// 만약 스레드가 중단되면, 메소드를 종료합니다.
return;
}

// 현재 시간에서 필요한 시, , 초 값을 가져와 레이블에 설정합니다.
int value = timeUnitGetter.apply(LocalDateTime.now());
label.setText(String.format("%02d", value));
}
}
}