본문 바로가기

Java

불편해서 직접만든 CapsLock 표시

기존에 사용하던 키보드에 command 키가 망가져 새로운 키보드가 필요했다. 키보드를 가방에 넣고 집, 학교, 카페 등으로 이동한게 문제인거 같았다.. 친구의 추천으로 쿠팡에서 3만원대 가성비 좋은 블루투스 키보드를 구입했다. 작고 디자인도 마음에 들었지만 capslock 표시가 없는게 나에게 큰 단점이었다. 그게 뭐가 불편하냐고 할 수 있겠지만 난 사이트 로그인시에 capslock 표시가 안되면 비밀번호를 정말 많이 틀린다.. 그러던중 대학교 수업시간에 배운 AWT 강의가 떠올랐다. 강의를 듣던 당시에는 이걸 대체 어디에 써먹을 수 있을지 의문이었는데 잘만 활용하면 capslock을 화면에 표시할 수 있을거 같았다.

 

곧바로 난 자바 프로젝트를 하나 만들었고 강의 내용을 떠올리며 개발을 시작했고 결과물은 다음과 같다.

public class Main {
    private TrayIcon trayIcon;
    private SystemTray systemTray;
    int size = 16;
    private BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> new Main().createAndShowGUI());
    }

    private void createAndShowGUI() {
        if (!SystemTray.isSupported()) {
            System.out.println("SystemTray is not supported");
            return;
        }

        PopupMenu popup = new PopupMenu();
        MenuItem exitItem = new MenuItem("Exit");
        exitItem.addActionListener(e -> System.exit(0));
        popup.add(exitItem);


        trayIcon = new TrayIcon(createImage("capslock-off.png", Color.BLUE, image));
        trayIcon.setPopupMenu(popup);

        try {
            systemTray = SystemTray.getSystemTray();
            systemTray.add(trayIcon);
        } catch (AWTException e) {
            e.printStackTrace();
            return;
        }

        Timer timer = new Timer(300, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                updateCapsLockIcon();
            }
        });

        timer.start();
    }

    private void updateCapsLockIcon() {
        boolean isCapsLockOn = Toolkit.getDefaultToolkit().getLockingKeyState(KeyEvent.VK_CAPS_LOCK);

        if (isCapsLockOn) {
            trayIcon.setImage(createImage("CapsLock Indicator", Color.RED, image));
        } else {
            trayIcon.setImage(createImage("CapsLock Indicator", Color.GREEN, image));
        }
    }

    private Image createImage(String text, Color color, BufferedImage image) {

        int size = 16; // 이미지 크기
        Graphics2D g2d = image.createGraphics();

        // 동그라미를 그립니다.
        g2d.setColor(color);
        g2d.fillOval(0, 0, size, size);

        // 텍스트를 중앙에 그립니다.
        g2d.setColor(Color.WHITE);
        Font font = new Font("Arial", Font.PLAIN, 10);
        FontMetrics fm = g2d.getFontMetrics(font);
        int x = (size - fm.stringWidth(text)) / 2;
        int y = (size - fm.getHeight()) / 2 + fm.getAscent();
        g2d.setFont(font);
        g2d.drawString(text, x, y);

        g2d.dispose();
        return image;
    }
}

현재 난 맥을 사용하고 있으며 화면 상단에 capslock 표시를 띄우기 위해 System Tray를 사용했다. 난 단지 capslock 표시만 보면됐고 디자인은 전혀 신경쓰지 않았다. createImage 함수에서 간단한 문자열, 색과 함께 작은 사이즈의 원 이미지를 생성한다. 해당 프로젝트를 실행하면 기존의 capslock 버튼과 무관하게 파란색 원이 출력되게 했으며 이후 Timer 객체에 ActionListner를 구현해 0.3초 마다 casplock 버튼을 확인한 뒤 on / off 여부에 따라 초록, 빨강 원이 표시되도록 구현했다. exit 버튼역시 구현해보았지만 크게 쓸데는 없었다

 

프로젝트를 실행하니

화면 상단에 capslock이 켜지지 않았다는 뜻의 초록색 원이 표시됐다. text는 원이 너무 작아 별로 도움이 되지 않았다..ㅎㅎ

capslock을 누르니 빨간색으로 변경됐다. 처음에는 Timer의 값을 1000으로 했었는데 이렇게 하니 반영되는 속도가 너무 늦어 300으로 낮췄다. 하지만 이 프로젝트의 단점은 백그라운드로 실행되지 않는다는 점이다. 백그라운드로 실행하기 위해 구글링을 더 해보았지만 AWT가 아닌 다른 라이브러리를 사용해야 했다. 난 어짜피 나만 사용할거고 이 프로젝트 하나 실행해놓는건 별로 어렵지 않았기에 굳이 다른 라이브러리를 다운받아 구현하지 않았다.

 

Intellij에서 계속 실행하기엔 Intellij 자체가 너무 무거워 터미널을 이용해 컴파일하고 실행했다.

터미널에서 해당 프로젝트가 존재하는 파일로 들어간 뒤 javac Main.java 를 통해 쉽게 컴파일 했고 이후 java Main 을 이용해 실행했다.

터미널에 한번 실행했던 기록을 남겨놓으니 다시 실행하는건 전혀 귀찮지 않았다

 

0.3초에 한번 capslock의 변경을 감지해 이미지를 띄워야해 CPU나 메모리를 많이 먹지 않을까 고민했지만 프로젝트를 실행하기 전과 후의 CPU와 메모리 사용량의 변화가 거의 없어 매우 만족하며 현재까지도 사용하고 있다. 역시 배움과 지식에 쓸데없고 의미없는 건 없나보다.

'Java' 카테고리의 다른 글

쓰레드  (0) 2022.12.06
Java기초 예외처리  (0) 2022.12.04
제네릭스  (0) 2022.11.25