chatGPTにJavaでのお絵描きツールの作り方を聞いてEclipseで作ってみたので、勉強のやる気を出すためにもメモ。
ArtCanvas.java
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ArtCanvas extends JFrame {
private DrawArea drawArea;
public ArtCanvas() {
setTitle("描いて遊べるアートキャンバス 🎨");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(800, 600);
drawArea = new DrawArea();
add(drawArea, BorderLayout.CENTER);
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(ArtCanvas::new);
}
}
class DrawArea extends JPanel {
private List<Line> lines = new ArrayList<>();
private int prevX, prevY;
private boolean drawing = false;
public DrawArea() {
setBackground(Color.WHITE);
// マウスの動きとクリックを検知
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
prevX = e.getX();
prevY = e.getY();
drawing = true;
}
@Override
public void mouseReleased(MouseEvent e) {
drawing = false;
}
});
addMouseMotionListener(new MouseAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
if (drawing) {
int x = e.getX();
int y = e.getY();
lines.add(new Line(prevX, prevY, x, y));
prevX = x;
prevY = y;
repaint(); // 再描画
}
}
});
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// 描いた線を全部描画
g.setColor(Color.BLACK);
for (Line line : lines) {
g.drawLine(line.x1, line.y1, line.x2, line.y2);
}
}
private static class Line {
int x1, y1, x2, y2;
Line(int x1, int y1, int x2, int y2) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
}
}
色を選べるようにした。
ArtCanvas.java
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ArtCanvas extends JFrame {
private DrawArea drawArea;
public ArtCanvas() {
setTitle("描いて遊べるアートキャンバス 🎨");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(800, 600);
drawArea = new DrawArea();
add(drawArea, BorderLayout.CENTER);
// 🎨 カラーパネルを作る
JPanel colorPanel = new JPanel();
colorPanel.setLayout(new FlowLayout());
// いくつかの色ボタンを追加
Color[] colors = {Color.BLACK, Color.RED, Color.BLUE, Color.GREEN, Color.ORANGE, Color.MAGENTA};
for (Color c : colors) {
JButton btn = new JButton();
btn.setBackground(c);
btn.setPreferredSize(new Dimension(20, 20));
btn.addActionListener(e -> drawArea.setCurrentColor(c));
colorPanel.add(btn);
}
// 「カラーピッカー」ボタン(自由に色を選ぶ)
JButton pickerBtn = new JButton("その他の色...");
pickerBtn.addActionListener(e -> {
Color newColor = JColorChooser.showDialog(this, "色を選択", drawArea.getCurrentColor());
if (newColor != null) {
drawArea.setCurrentColor(newColor);
}
});
colorPanel.add(pickerBtn);
add(colorPanel, BorderLayout.NORTH);
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(ArtCanvas::new);
}
}
class DrawArea extends JPanel {
private List<Line> lines = new ArrayList<>();
private int prevX, prevY;
private boolean drawing = false;
private Color currentColor = Color.BLACK;
public DrawArea() {
setBackground(Color.WHITE);
// マウスの動きとクリックを検知
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
prevX = e.getX();
prevY = e.getY();
drawing = true;
}
@Override
public void mouseReleased(MouseEvent e) {
drawing = false;
}
});
addMouseMotionListener(new MouseAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
if (drawing) {
int x = e.getX();
int y = e.getY();
lines.add(new Line(prevX, prevY, x, y, currentColor));
prevX = x;
prevY = y;
repaint(); // 再描画
}
}
});
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// 描いた線を全部描画
for (Line line : lines) {
g.setColor(line.color);
g.drawLine(line.x1, line.y1, line.x2, line.y2);
}
}
public void setCurrentColor(Color c) {
this.currentColor = c;
}
public Color getCurrentColor() {
return this.currentColor;
}
private static class Line {
int x1, y1, x2, y2;
Color color;
Line(int x1, int y1, int x2, int y2, Color color) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.color = color;
}
}
}
「その他の色」ボタンを押下すると、以下のようなカラーパレットがある。

次は、消しゴムを追加してみた。
ChatGPTによると「白い線は実質消しゴム!」とのこと。背景が白の場合はそれでいいのかも。
ArtCanvas.java
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ArtCanvas extends JFrame {
private DrawArea drawArea;
private Color lastSelectedColor = Color.BLACK; // ← 直前の色を覚えておく
public ArtCanvas() {
setTitle("描いて遊べるアートキャンバス 🎨");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(800, 600);
drawArea = new DrawArea();
add(drawArea, BorderLayout.CENTER);
// 🎨 カラーパネル
JPanel colorPanel = new JPanel();
colorPanel.setLayout(new FlowLayout());
// 色ボタン
Color[] colors = {Color.BLACK, Color.RED, Color.BLUE, Color.GREEN, Color.ORANGE, Color.MAGENTA};
for (Color c : colors) {
JButton btn = new JButton();
btn.setBackground(c);
btn.setPreferredSize(new Dimension(20, 20));
btn.addActionListener(e -> drawArea.setCurrentColor(c));
colorPanel.add(btn);
}
// 「カラーピッカー」ボタン(自由に色を選ぶ)
JButton pickerBtn = new JButton("その他の色...");
pickerBtn.addActionListener(e -> {
Color newColor = JColorChooser.showDialog(this, "色を選択", drawArea.getCurrentColor());
if (newColor != null) {
drawArea.setCurrentColor(newColor);
}
});
colorPanel.add(pickerBtn);
// 🧼 消しゴムボタン
JButton eraserBtn = new JButton("🧽 消しゴム");
eraserBtn.addActionListener(e -> drawArea.setCurrentColor(Color.WHITE));
colorPanel.add(eraserBtn);
// 🖌 ペンに戻るボタン
JButton penBtn = new JButton("✏️ ペンに戻る");
penBtn.addActionListener(e -> drawArea.setCurrentColor(lastSelectedColor));
colorPanel.add(penBtn);
add(colorPanel, BorderLayout.NORTH);
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(ArtCanvas::new);
}
}
class DrawArea extends JPanel {
private List<Line> lines = new ArrayList<>();
private int prevX, prevY;
private boolean drawing = false;
private Color currentColor = Color.BLACK;
public DrawArea() {
setBackground(Color.WHITE);
// マウスの動きとクリックを検知
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
prevX = e.getX();
prevY = e.getY();
drawing = true;
}
@Override
public void mouseReleased(MouseEvent e) {
drawing = false;
}
});
addMouseMotionListener(new MouseAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
if (drawing) {
int x = e.getX();
int y = e.getY();
lines.add(new Line(prevX, prevY, x, y, currentColor));
prevX = x;
prevY = y;
repaint(); // 再描画
}
}
});
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// 描いた線を全部描画
for (Line line : lines) {
g.setColor(line.color);
g.drawLine(line.x1, line.y1, line.x2, line.y2);
}
}
public void setCurrentColor(Color c) {
this.currentColor = c;
}
public Color getCurrentColor() {
return this.currentColor;
}
private static class Line {
int x1, y1, x2, y2;
Color color;
Line(int x1, int y1, int x2, int y2, Color color) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.color = color;
}
}
}
線の太さを変えられるようにしてみた。
ArtCanvas.java
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.SwingUtilities;
public class ArtCanvas extends JFrame {
private DrawArea drawArea;
private Color lastSelectedColor = Color.BLACK; // ← 直前の色を覚えておく
public ArtCanvas() {
setTitle("描いて遊べるアートキャンバス 🎨");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(800, 600);
drawArea = new DrawArea();
add(drawArea, BorderLayout.CENTER);
// 🎨 カラーパネル
JPanel colorPanel = new JPanel();
colorPanel.setLayout(new FlowLayout());
// 色ボタン
Color[] colors = {Color.BLACK, Color.RED, Color.BLUE, Color.GREEN, Color.ORANGE, Color.MAGENTA};
for (Color c : colors) {
JButton btn = new JButton();
btn.setBackground(c);
btn.setPreferredSize(new Dimension(20, 20));
btn.addActionListener(e -> {
lastSelectedColor = c;
drawArea.setCurrentColor(c);
});
colorPanel.add(btn);
}
// 「カラーピッカー」ボタン(自由に色を選ぶ)
JButton pickerBtn = new JButton("その他の色...");
pickerBtn.addActionListener(e -> {
Color newColor = JColorChooser.showDialog(this, "色を選択", drawArea.getCurrentColor());
if (newColor != null) {
drawArea.setCurrentColor(newColor);
}
});
colorPanel.add(pickerBtn);
// 🧼 消しゴムボタン
JButton eraserBtn = new JButton("🧽 消しゴム");
eraserBtn.addActionListener(e -> drawArea.setCurrentColor(Color.WHITE));
colorPanel.add(eraserBtn);
// 🖌 ペンに戻るボタン
JButton penBtn = new JButton("✏️ ペンに戻る");
penBtn.addActionListener(e -> drawArea.setCurrentColor(lastSelectedColor));
colorPanel.add(penBtn);
add(colorPanel, BorderLayout.NORTH);
// ✨ 線の太さスライダー
JPanel bottomPanel = new JPanel();
JLabel sliderLabel = new JLabel("線の太さ:");
JSlider thicknessSlider = new JSlider(1, 50, 5); // 最小1, 最大50, 初期値5
thicknessSlider.setMajorTickSpacing(5);
thicknessSlider.setPaintTicks(true);
thicknessSlider.setPaintLabels(true);
thicknessSlider.addChangeListener(e -> {
int value = thicknessSlider.getValue();
drawArea.setCurrentThickness(value);
});
bottomPanel.add(sliderLabel);
bottomPanel.add(thicknessSlider);
add(bottomPanel, BorderLayout.SOUTH);
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(ArtCanvas::new);
}
}
class DrawArea extends JPanel {
private List<Line> lines = new ArrayList<>();
private int prevX, prevY;
private boolean drawing = false;
private Color currentColor = Color.BLACK;
private float currentThickness = 3f;
public DrawArea() {
setBackground(Color.WHITE);
// マウスの動きとクリックを検知
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
prevX = e.getX();
prevY = e.getY();
drawing = true;
}
@Override
public void mouseReleased(MouseEvent e) {
drawing = false;
}
});
addMouseMotionListener(new MouseAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
if (drawing) {
int x = e.getX();
int y = e.getY();
lines.add(new Line(prevX, prevY, x, y, currentColor, currentThickness));
prevX = x;
prevY = y;
repaint(); // 再描画
}
}
});
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
// 描いた線を全部描画
for (Line line : lines) {
g.setColor(line.color);
g2.setStroke(new BasicStroke(line.thickness, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
g.drawLine(line.x1, line.y1, line.x2, line.y2);
}
}
public void setCurrentColor(Color c) {
this.currentColor = c;
}
public Color getCurrentColor() {
return this.currentColor;
}
public void setCurrentThickness(float thickness) {
this.currentThickness = thickness;
}
private static class Line {
int x1, y1, x2, y2;
Color color;
float thickness;
Line(int x1, int y1, int x2, int y2, Color color, float thickness) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.color = color;
this.thickness = thickness;
}
}
}
画像保存できるようにしてみた。
ArtCanvas.java
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.SwingUtilities;
public class ArtCanvas extends JFrame {
private DrawArea drawArea;
private Color lastSelectedColor = Color.BLACK; // ← 直前の色を覚えておく
public ArtCanvas() {
setTitle("描いて遊べるアートキャンバス 🎨");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(800, 600);
drawArea = new DrawArea();
add(drawArea, BorderLayout.CENTER);
// 🎨 カラーパネル
JPanel colorPanel = new JPanel();
colorPanel.setLayout(new FlowLayout());
// 色ボタン
Color[] colors = {Color.BLACK, Color.RED, Color.BLUE, Color.GREEN, Color.ORANGE, Color.MAGENTA};
for (Color c : colors) {
JButton btn = new JButton();
btn.setBackground(c);
btn.setPreferredSize(new Dimension(20, 20));
btn.addActionListener(e -> {
lastSelectedColor = c;
drawArea.setCurrentColor(c);
});
colorPanel.add(btn);
}
// 「カラーピッカー」ボタン(自由に色を選ぶ)
JButton pickerBtn = new JButton("その他の色...");
pickerBtn.addActionListener(e -> {
Color newColor = JColorChooser.showDialog(this, "色を選択", drawArea.getCurrentColor());
if (newColor != null) {
lastSelectedColor = newColor;
drawArea.setCurrentColor(newColor);
}
});
colorPanel.add(pickerBtn);
// 🧼 消しゴムボタン
JButton eraserBtn = new JButton("🧽 消しゴム");
eraserBtn.addActionListener(e -> drawArea.setCurrentColor(Color.WHITE));
colorPanel.add(eraserBtn);
// 🖌 ペンに戻るボタン
JButton penBtn = new JButton("✏️ ペンに戻る");
penBtn.addActionListener(e -> drawArea.setCurrentColor(lastSelectedColor));
colorPanel.add(penBtn);
// 💾 画像保存ボタン
JButton saveBtn = new JButton("💾 画像を保存");
saveBtn.addActionListener(e -> drawArea.saveImage());
colorPanel.add(saveBtn);
add(colorPanel, BorderLayout.NORTH);
// ✨ 線の太さスライダー
JPanel bottomPanel = new JPanel();
JLabel sliderLabel = new JLabel("線の太さ:");
JSlider thicknessSlider = new JSlider(1, 50, 5); // 最小1, 最大50, 初期値5
thicknessSlider.setMajorTickSpacing(5);
thicknessSlider.setPaintTicks(true);
thicknessSlider.setPaintLabels(true);
thicknessSlider.addChangeListener(e -> {
int value = thicknessSlider.getValue();
drawArea.setCurrentThickness(value);
});
bottomPanel.add(sliderLabel);
bottomPanel.add(thicknessSlider);
add(bottomPanel, BorderLayout.SOUTH);
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(ArtCanvas::new);
}
}
class DrawArea extends JPanel {
private List<Line> lines = new ArrayList<>();
private int prevX, prevY;
private boolean drawing = false;
private Color currentColor = Color.BLACK;
private float currentThickness = 3f;
public DrawArea() {
setBackground(Color.WHITE);
// マウスの動きとクリックを検知
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
prevX = e.getX();
prevY = e.getY();
drawing = true;
}
@Override
public void mouseReleased(MouseEvent e) {
drawing = false;
}
});
addMouseMotionListener(new MouseAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
if (drawing) {
int x = e.getX();
int y = e.getY();
lines.add(new Line(prevX, prevY, x, y, currentColor, currentThickness));
prevX = x;
prevY = y;
repaint(); // 再描画
}
}
});
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
// 描いた線を全部描画
for (Line line : lines) {
g.setColor(line.color);
g2.setStroke(new BasicStroke(line.thickness, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
g.drawLine(line.x1, line.y1, line.x2, line.y2);
}
}
public void setCurrentColor(Color c) {
this.currentColor = c;
}
public Color getCurrentColor() {
return this.currentColor;
}
public void setCurrentThickness(float thickness) {
this.currentThickness = thickness;
}
// 💾 画像保存
public void saveImage() {
// 描画内容を BufferedImage に書き出す
BufferedImage image = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = image.createGraphics();
paint(g2);
g2.dispose();
// 保存ダイアログ
JFileChooser fileChooser = new JFileChooser();
fileChooser.setDialogTitle("画像を保存");
fileChooser.setSelectedFile(new File("my_drawing.png"));
int userSelection = fileChooser.showSaveDialog(this);
if (userSelection == JFileChooser.APPROVE_OPTION) {
File fileToSave = fileChooser.getSelectedFile();
try {
// 拡張子がない場合、自動で .png をつける
String path = fileToSave.getAbsolutePath();
if (!path.toLowerCase().endsWith(".png")) {
fileToSave = new File(path + ".png");
}
ImageIO.write(image, "png", fileToSave);
JOptionPane.showMessageDialog(this, "画像を保存しました!\n" + fileToSave.getAbsolutePath());
} catch (Exception ex) {
JOptionPane.showMessageDialog(this, "保存に失敗しました: " + ex.getMessage());
}
}
}
private static class Line {
int x1, y1, x2, y2;
Color color;
float thickness;
Line(int x1, int y1, int x2, int y2, Color color, float thickness) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.color = color;
this.thickness = thickness;
}
}
}
塗りつぶしや画面の描画の全削除等も入れて、不要な部分を削除したりした。
ArtCanvas.java
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.LinkedList;
import java.util.Queue;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.SwingUtilities;
public class ArtCanvas extends JFrame {
private DrawArea drawArea;
public ArtCanvas() {
setTitle("描いて遊べるアートキャンバス 🎨");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(800, 600);
drawArea = new DrawArea();
add(drawArea, BorderLayout.CENTER);
// 🎨 カラーパネル
JPanel colorPanel = new JPanel();
colorPanel.setLayout(new FlowLayout());
// 色ボタン
Color[] colors = {Color.BLACK, Color.RED, Color.BLUE, Color.GREEN, Color.ORANGE, Color.MAGENTA};
for (Color c : colors) {
JButton btn = new JButton();
btn.setBackground(c);
btn.setPreferredSize(new Dimension(20, 20));
btn.addActionListener(e -> {
drawArea.setCurrentColor(c);
});
colorPanel.add(btn);
}
// 「カラーピッカー」ボタン(自由に色を選ぶ)
JButton pickerBtn = new JButton("その他の色...");
pickerBtn.addActionListener(e -> {
Color newColor = JColorChooser.showDialog(this, "色を選択", drawArea.getCurrentColor());
if (newColor != null) {
drawArea.setCurrentColor(newColor);
}
});
colorPanel.add(pickerBtn);
// 🖌 ペンボタン
JButton penBtn = new JButton("ペン");
penBtn.addActionListener(e -> drawArea.setTool("pen"));
colorPanel.add(penBtn);
// 塗りつぶし
JButton fillBtn = new JButton("塗りつぶし");
fillBtn.addActionListener(e -> drawArea.setTool("fill"));
colorPanel.add(fillBtn);
// 🧼 消しゴムボタン
JButton eraserBtn = new JButton("消しゴム");
eraserBtn.addActionListener(e -> drawArea.setCurrentColor(Color.WHITE));
colorPanel.add(eraserBtn);
// 🧭 全削除
JButton clearBtn = new JButton("全削除");
clearBtn.addActionListener(e -> drawArea.clearCanvas());
colorPanel.add(clearBtn);
// 💾 画像保存ボタン
JButton saveBtn = new JButton("💾 画像を保存");
saveBtn.addActionListener(e -> drawArea.saveImage());
colorPanel.add(saveBtn);
add(colorPanel, BorderLayout.NORTH);
// ✨ 線の太さスライダー
JPanel bottomPanel = new JPanel();
JLabel sliderLabel = new JLabel("線の太さ:");
JSlider thicknessSlider = new JSlider(1, 50, 5); // 最小1, 最大50, 初期値5
thicknessSlider.setMajorTickSpacing(5);
thicknessSlider.setPaintTicks(true);
thicknessSlider.setPaintLabels(true);
thicknessSlider.addChangeListener(e -> {
int value = thicknessSlider.getValue();
drawArea.setCurrentThickness(value);
});
bottomPanel.add(sliderLabel);
bottomPanel.add(thicknessSlider);
add(bottomPanel, BorderLayout.SOUTH);
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(ArtCanvas::new);
}
}
class DrawArea extends JPanel {
private int prevX, prevY;
private boolean drawing = false;
private Color currentColor = Color.BLACK;
private float currentThickness = 3f;
private BufferedImage canvas;
private String currentTool = "pen"; // pen or fill
public DrawArea() {
setBackground(Color.WHITE);
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
initCanvas();
}
});
// マウスの動きとクリックを検知
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
int x = e.getX();
int y = e.getY();
if (currentTool.equals("pen")) {
prevX = e.getX();
prevY = e.getY();
drawing = true;
} else if (currentTool.equals("fill")) {
floodFill(x, y, canvas.getRGB(x, y), currentColor.getRGB());
repaint();
}
}
@Override
public void mouseReleased(MouseEvent e) {
drawing = false;
}
});
addMouseMotionListener(new MouseAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
if (drawing) {
int x = e.getX();
int y = e.getY();
// これまでlinesに記録していたけど、canvasに直接描いてるので不要になる
// lines.add(new Line(prevX, prevY, x, y, currentColor, currentThickness));
Graphics2D g2m = canvas.createGraphics(); // canvasに直接描く
g2m.setColor(currentColor);
g2m.setStroke(new BasicStroke(currentThickness, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
g2m.drawLine(prevX, prevY, x, y);
g2m.dispose();
prevX = x;
prevY = y;
repaint(); // 再描画
}
}
});
}
private void initCanvas() {
int w = getWidth();
int h = getHeight();
if (w <= 0 || h <= 0) return;
BufferedImage newCanvas = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics2D g2i = newCanvas.createGraphics();
g2i.setColor(Color.WHITE);
g2i.fillRect(0, 0, w, h);
if (canvas != null) {
g2i.drawImage(canvas, 0, 0, null);
}
g2i.dispose();
canvas = newCanvas;
}
// 🪣 Flood Fill(非再帰版)
private void floodFill(int startX, int startY, int targetColor, int replacementColor) {
if (targetColor == replacementColor) return;
if (startX < 0 || startY < 0 || startX >= canvas.getWidth() || startY >= canvas.getHeight()) return;
if (canvas.getRGB(startX, startY) != targetColor) return;
Queue<Point> queue = new LinkedList<>();
queue.add(new Point(startX, startY));
while (!queue.isEmpty()) {
Point p = queue.poll();
int x = p.x;
int y = p.y;
if (x < 0 || y < 0 || x >= canvas.getWidth() || y >= canvas.getHeight()) continue;
if (canvas.getRGB(x, y) != targetColor) continue;
canvas.setRGB(x, y, replacementColor);
queue.add(new Point(x + 1, y));
queue.add(new Point(x - 1, y));
queue.add(new Point(x, y + 1));
queue.add(new Point(x, y - 1));
}
}
// 🧭 全削除
public void clearCanvas() {
Graphics2D g2c = canvas.createGraphics();
g2c.setColor(Color.WHITE);
g2c.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());
g2c.dispose();
repaint();
}
// 💾 画像保存
public void saveImage() {
// 描画内容を BufferedImage に書き出す
BufferedImage image = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g2s = image.createGraphics();
paint(g2s);
g2s.dispose();
// 保存ダイアログ
JFileChooser fileChooser = new JFileChooser();
fileChooser.setDialogTitle("画像を保存");
fileChooser.setSelectedFile(new File("my_drawing.png"));
int userSelection = fileChooser.showSaveDialog(this);
if (userSelection == JFileChooser.APPROVE_OPTION) {
File fileToSave = fileChooser.getSelectedFile();
try {
// 拡張子がない場合、自動で .png をつける
String path = fileToSave.getAbsolutePath();
if (!path.toLowerCase().endsWith(".png")) {
fileToSave = new File(path + ".png");
}
ImageIO.write(image, "png", fileToSave);
JOptionPane.showMessageDialog(this, "画像を保存しました!\n" + fileToSave.getAbsolutePath());
} catch (Exception ex) {
JOptionPane.showMessageDialog(this, "保存に失敗しました: " + ex.getMessage());
}
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(canvas, 0, 0, null);
}
public void setCurrentColor(Color c) {
this.currentColor = c;
}
public Color getCurrentColor() {
return this.currentColor;
}
public void setTool(String tool) {
this.currentTool = tool;
}
public void setCurrentThickness(float thickness) {
this.currentThickness = thickness;
}
}
ちょっとずつ改良したい。














