🐕

[Java][Swing] Color Selectorの作成

に公開

背景

今更ながらJavaとSwingの手習いということで色の選択アプリであるColor Selectorを作成してみた。作成した動機は以下

  • 周辺にJava使いが多いので、Javaのリハビリ
  • SwingはJavaの開発環境を入れたらそのまま使えることにメリットを感じること
  • Swingは単一のソースコードでもそれなりのアプリが開発ができること
  • Swingの欠点であったダサいUIが改善可能であることを知ったこと
    Swingの手習いのついでにそれなりに実用性の高いアプリを作ってみるということで、Color Selectorを作ってみた。

Color Selectorとは何か?

Webページの作成の際に、背景色と文字色の組み合わせをどう選択すべきか迷うことがあるが、色をスライダーで選択しながら画面で確認して色を選べるツールとしてColor Selectorを開発した。画面のスクリーンショットは以下

提供する機能

  • R/G/Bのスライダーでの色の選択機能(文字色、背景色をラジオボタンで切り替え可能)
  • 右側のテキストフィールドに数字を直接入れることで決め打ちで色の確認が可能
  • 選択した色は10進数表記だけでなく、16進数表記でも確認が可能(上のスクショで"#86C650"と記載されているがそれ)

開発環境

  • JDK(Amazon Corretto 21)
  • テキストエディタで手書きで開発

開発後の所感

以下が期待通りの結果であることが確認できた
SwingはJavaの開発環境を入れたらそのまま動くこと(追加パッケージの導入不要は小さく、早く開発する観点でありがたい)
Swingは単一ファイルでも動作すること(ソースコードをスクリプト言語のように単一ファイルを編集しながら実行できるところも素晴らしい)
見た目が改善していること(Look and FeelをWindows風にすることで違和感のないUIになることを確認。ちなみに初期設定のUIは以下で過去のイメージ通り微妙にダサい)。

今後

「単一ファイルで小さく、早くつくる」というコンセプトが実現できることが確認できた。今後業務で必要になった時にすぐに小さく、早く作れるように、継続してサンプルを作ってみる予定

ソースコード

///////////////////////////////////////////////////////////////////////////////////////////////
//// Color Selector written by yanboumabou (2025/06/01)
/// [Usage]
///  Please run the following command. A Color Selector will appear after running it.
///  java ColorSelector.java

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

public class ColorSelector {
    static int frontColorR = 255;
    static int frontColorG = 255;
    static int frontColorB = 255;

    static int backColorR = 0;
    static int backColorG = 0;
    static int backColorB = 0;

    static boolean isForeground = false;

    static void setLookAndFeel() {
	try {
	    UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
	} catch(Exception e) {
	    e.printStackTrace();
	}
    }
    
    public static void main(String[] args){
	JFrame frame = new JFrame("Color Selector");
	frame.setSize(800, 500);
	
	setLookAndFeel();

	// https://stackoverflow.com/questions/27025230/aligning-components-in-box
	Box box0 = Box.createVerticalBox();
	JPanel panel1 = new JPanel(new FlowLayout());
	JPanel panel2 = new JPanel(new FlowLayout());
	JPanel panel3 = new JPanel(new FlowLayout());
	JPanel panel4 = new JPanel(new FlowLayout());
	box0.add(panel1);
	box0.add(panel2);
	box0.add(panel3);
	box0.add(panel4);
	frame.add(box0);
	
	//////////////////////////////////////////////////////////////////////////////////
	// Label
	JLabel label = new JLabel("Front Color");
	label.setForeground(new Color(frontColorR, frontColorG, frontColorB));
	label.setBackground(new Color(backColorR, backColorG, backColorB));
	label.setOpaque(true); //enable this for showing background
	label.setPreferredSize(new Dimension(200, 100));
	label.setHorizontalAlignment(JLabel.CENTER);
	label.setFont(new Font("Meiryo UI", Font.BOLD, 16));
	panel1.add(label);

	// Radio Button
	JRadioButton rb_fg = new JRadioButton(String.format("FG: #%02X%02X%02X", frontColorR, frontColorG, frontColorB), false);
	JRadioButton rb_bg = new JRadioButton(String.format("BG: #%02X%02X%02X", backColorR, backColorG, backColorB), true);
	rb_fg.setFont(new Font("Meiryo UI", Font.PLAIN, 14));
	rb_bg.setFont(new Font("Meiryo UI", Font.PLAIN, 14));
	Box box1 = Box.createVerticalBox();
	box1.add(rb_fg);
	box1.add(rb_bg);
	panel1.add(box1);
	ButtonGroup bg = new ButtonGroup();
	bg.add(rb_fg);
	bg.add(rb_bg);

	//////////////////////////////////////////////////////////////////////////////////
	// Label/Slider/TextField(R)
	JLabel label_title_r = new JLabel("R: ");
	label_title_r.setFont(new Font("Meiryo UI", Font.PLAIN, 14));
	panel2.add(label_title_r);
	JSlider slider_r = new JSlider(0, 255, 0);
	slider_r.setPreferredSize(new Dimension(280, 50));
	slider_r.setMajorTickSpacing(50);
	slider_r.setPaintTicks(true);
	panel2.add(slider_r);
	JTextField tf_r = new JTextField("0", 3);
	tf_r.setFont(new Font("Meiryo UI", Font.PLAIN, 14));
	tf_r.setHorizontalAlignment(JTextField.RIGHT);
	panel2.add(tf_r);

	//////////////////////////////////////////////////////////////////////////////////
	// Label/Slider/TextField(G)
	JLabel label_title_g = new JLabel("G: ");
	label_title_g.setFont(new Font("Meiryo UI", Font.PLAIN, 14));
	panel3.add(label_title_g);
	JSlider slider_g = new JSlider(0, 255, 0);
	slider_g.setPreferredSize(new Dimension(280, 50));
	slider_g.setMajorTickSpacing(50);
	slider_g.setPaintTicks(true);
	panel3.add(slider_g);
	JTextField tf_g = new JTextField("0", 3);
	tf_g.setFont(new Font("Meiryo UI", Font.PLAIN, 14));
	tf_g.setHorizontalAlignment(JTextField.RIGHT);
	panel3.add(tf_g);
	//////////////////////////////////////////////////////////////////////////////////
	// Label/Slider/TextField(B)
	JLabel label_title_b = new JLabel("B: ");
	label_title_b.setFont(new Font("Meiryo UI", Font.PLAIN, 14));
	panel4.add(label_title_b);
	JSlider slider_b = new JSlider(0, 255, 0);
	slider_b.setPreferredSize(new Dimension(280, 50));
	slider_b.setMajorTickSpacing(50);
	slider_b.setPaintTicks(true);
	panel4.add(slider_b);
	JTextField tf_b = new JTextField("0", 3);
	tf_b.setFont(new Font("Meiryo UI", Font.PLAIN, 14));
	tf_b.setHorizontalAlignment(JTextField.RIGHT);
	panel4.add(tf_b);

	//////////////////////////////////////////////////////////////////////////////////
	// Event Listeners (Radio Button)
	rb_fg.addActionListener(new ActionListener() {
		public void actionPerformed(ActionEvent e) {
		    isForeground = true;
		    slider_r.setValue(frontColorR);
		    slider_g.setValue(frontColorG);
		    slider_b.setValue(frontColorB);
		    tf_r.setText(String.format("%02d", frontColorR));
		    tf_g.setText(String.format("%02d", frontColorG));
		    tf_b.setText(String.format("%02d", frontColorB));
		}
	    });
	rb_bg.addActionListener(new ActionListener() {
		public void actionPerformed(ActionEvent e) {
		    isForeground = false;
		    slider_r.setValue(backColorR);
		    slider_g.setValue(backColorG);
		    slider_b.setValue(backColorB);
		    tf_r.setText(String.format("%02d", backColorR));
		    tf_g.setText(String.format("%02d", backColorG));
		    tf_b.setText(String.format("%02d", backColorB));
		}
	    });
	
	//////////////////////////////////////////////////////////////////////////////////
	// Event Listeners (Slider - R)
	slider_r.addChangeListener(new ChangeListener() {
		public void stateChanged(ChangeEvent e) {
		    if(isForeground) {
			frontColorR = ((JSlider)e.getSource()).getValue();
			label.setForeground(new Color(frontColorR, frontColorG, frontColorB));
			tf_r.setText(String.format("%02d", frontColorR));
			rb_fg.setText(String.format("FG: #%02X%02X%02X", frontColorR, frontColorG, frontColorB));
		    }else {
			backColorR = ((JSlider)e.getSource()).getValue();
			label.setBackground(new Color(backColorR, backColorG, backColorB));
			tf_r.setText(String.format("%02d", backColorR));
			rb_bg.setText(String.format("BG: #%02X%02X%02X", backColorR, backColorG, backColorB));
		    }		    
		}
	    });
	//////////////////////////////////////////////////////////////////////////////////
	// Event Listeners (Slider - G)
	slider_g.addChangeListener(new ChangeListener() {
		public void stateChanged(ChangeEvent e) {
		    if(isForeground) {
			frontColorG = ((JSlider)e.getSource()).getValue();
			label.setForeground(new Color(frontColorR, frontColorG, frontColorB));
			tf_g.setText(String.format("%02d", frontColorG));
			rb_fg.setText(String.format("FG: #%02X%02X%02X", frontColorR, frontColorG, frontColorB));
		    }else {
			backColorG = ((JSlider)e.getSource()).getValue();
			label.setBackground(new Color(backColorR, backColorG, backColorB));
			tf_g.setText(String.format("%02d", backColorG));
			rb_bg.setText(String.format("BG: #%02X%02X%02X", backColorR, backColorG, backColorB));
		    }		    
		}
	    });

	//////////////////////////////////////////////////////////////////////////////////
	// Event Listeners (Slider - B)
	slider_b.addChangeListener(new ChangeListener() {
		public void stateChanged(ChangeEvent e) {
		    if(isForeground) {
			frontColorB = ((JSlider)e.getSource()).getValue();
			label.setForeground(new Color(frontColorR, frontColorG, frontColorB));
			tf_b.setText(String.format("%02d", frontColorB));
			rb_fg.setText(String.format("FG: #%02X%02X%02X", frontColorR, frontColorG, frontColorB));
		    }else {
			backColorB = ((JSlider)e.getSource()).getValue();
			label.setBackground(new Color(backColorR, backColorG, backColorB));
			tf_b.setText(String.format("%02d", backColorB));
			rb_bg.setText(String.format("BG: #%02X%02X%02X", backColorR, backColorG, backColorB));
		    }		    
		}
	    });
	
	//////////////////////////////////////////////////////////////////////////////////
	// Event Listeners (TextField - R)
	tf_r.addActionListener(new ActionListener() {
		public void actionPerformed(ActionEvent e){
		    if(isForeground) {
			frontColorR = Integer.valueOf(tf_r.getText());
			label.setForeground(new Color(frontColorR, frontColorG, frontColorB));
			slider_r.setValue(frontColorR);
			rb_fg.setText(String.format("FG: #%02X%02X%02X", frontColorR, frontColorG, frontColorB));
		    }else {
			backColorR = Integer.valueOf(tf_r.getText());
			label.setBackground(new Color(backColorR, backColorG, backColorB));
			slider_r.setValue(backColorR);
			rb_bg.setText(String.format("BG: #%02X%02X%02X", backColorR, backColorG, backColorB));
		    }
		}
	    });

	//////////////////////////////////////////////////////////////////////////////////
	// Event Listeners (TextField - G)
	tf_g.addActionListener(new ActionListener() {
		public void actionPerformed(ActionEvent e){
		    if(isForeground) {
			frontColorG = Integer.valueOf(tf_g.getText());
			label.setForeground(new Color(frontColorR, frontColorG, frontColorB));
			slider_g.setValue(frontColorG);
			rb_fg.setText(String.format("FG: #%02X%02X%02X", frontColorR, frontColorG, frontColorB));
		    }else {
			backColorG = Integer.valueOf(tf_g.getText());
			label.setBackground(new Color(backColorR, backColorG, backColorB));
			slider_g.setValue(backColorG);
			rb_bg.setText(String.format("BG: #%02X%02X%02X", backColorR, backColorG, backColorB));
		    }
		}
	    });

	//////////////////////////////////////////////////////////////////////////////////
	// Event Listeners (TextField - B)
	tf_b.addActionListener(new ActionListener() {
		public void actionPerformed(ActionEvent e){
		    if(isForeground) {
			frontColorB = Integer.valueOf(tf_b.getText());
			label.setForeground(new Color(frontColorR, frontColorG, frontColorB));
			slider_b.setValue(frontColorB);
			rb_fg.setText(String.format("FG: #%02X%02X%02X", frontColorR, frontColorG, frontColorB));
		    }else {
			backColorB = Integer.valueOf(tf_b.getText());
			label.setBackground(new Color(backColorR, backColorG, backColorB));
			slider_b.setValue(backColorB);
			rb_bg.setText(String.format("BG: #%02X%02X%02X", backColorR, backColorG, backColorB));
		    }
		}
	    });
	
	//////////////////////////////////////////////////////////////////////////////////

	frame.pack();
	// https://stackoverflow.com/questions/9543320/how-to-position-the-form-in-the-center-screen
	frame.setLocationRelativeTo(null);
	frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	frame.setResizable(false);
	frame.setVisible(true);
    }
}

Discussion