Java ペイントソフト

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.util.Stack;
import javax.imageio.ImageIO;
import java.io.File;

public class AdvancedPaintAppWithUndoRedo extends JFrame {

    private DrawPanel drawPanel;
    private Color currentColor = Color.BLACK;
    private int brushSize = 4;
    private String currentTool = "Brush";
    private Stack<BufferedImage> undoStack = new Stack<>();
    private Stack<BufferedImage> redoStack = new Stack<>();

    public AdvancedPaintAppWithUndoRedo() {
        setTitle("Advanced Paint Application with Undo/Redo");
        setSize(800, 600);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        drawPanel = new DrawPanel();
        add(drawPanel, BorderLayout.CENTER);

        // メニューバーの作成
        JMenuBar menuBar = new JMenuBar();
        JMenu fileMenu = new JMenu("File");
        JMenuItem saveItem = new JMenuItem("Save");
        JMenuItem openItem = new JMenuItem("Open");
        JMenuItem clearItem = new JMenuItem("Clear");
        saveItem.addActionListener(e -> saveImage());
        openItem.addActionListener(e -> openImage());
        clearItem.addActionListener(e -> drawPanel.clearCanvas());
        fileMenu.add(saveItem);
        fileMenu.add(openItem);
        fileMenu.add(clearItem);
        menuBar.add(fileMenu);

        JMenu toolMenu = new JMenu("Tools");
        JMenuItem colorItem = new JMenuItem("Choose Color");
        JMenuItem brushItem = new JMenuItem("Brush Size");
        JMenuItem toolBrush = new JMenuItem("Brush");
        JMenuItem toolLine = new JMenuItem("Line");
        JMenuItem toolRect = new JMenuItem("Rectangle");
        JMenuItem toolOval = new JMenuItem("Oval");
        JMenuItem toolText = new JMenuItem("Text");

        colorItem.addActionListener(e -> chooseColor());
        brushItem.addActionListener(e -> chooseBrushSize());
        toolBrush.addActionListener(e -> currentTool = "Brush");
        toolLine.addActionListener(e -> currentTool = "Line");
        toolRect.addActionListener(e -> currentTool = "Rectangle");
        toolOval.addActionListener(e -> currentTool = "Oval");
        toolText.addActionListener(e -> currentTool = "Text");

        toolMenu.add(colorItem);
        toolMenu.add(brushItem);
        toolMenu.add(toolBrush);
        toolMenu.add(toolLine);
        toolMenu.add(toolRect);
        toolMenu.add(toolOval);
        toolMenu.add(toolText);
        menuBar.add(toolMenu);

        JMenu editMenu = new JMenu("Edit");
        JMenuItem undoItem = new JMenuItem("Undo");
        JMenuItem redoItem = new JMenuItem("Redo");
        undoItem.addActionListener(e -> drawPanel.undo());
        redoItem.addActionListener(e -> drawPanel.redo());
        editMenu.add(undoItem);
        editMenu.add(redoItem);
        menuBar.add(editMenu);

        setJMenuBar(menuBar);
    }

    // メインメソッド
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            AdvancedPaintAppWithUndoRedo app = new AdvancedPaintAppWithUndoRedo();
            app.setVisible(true);
        });
    }

    // 色を選択する
    private void chooseColor() {
        Color color = JColorChooser.showDialog(null, "Choose a Color", currentColor);
        if (color != null) {
            currentColor = color;
            drawPanel.setColor(color);
        }
    }

    // ブラシサイズを選択する
    private void chooseBrushSize() {
        String sizeStr = JOptionPane.showInputDialog(this, "Enter brush size:", brushSize);
        if (sizeStr != null) {
            try {
                int size = Integer.parseInt(sizeStr);
                if (size > 0) {
                    brushSize = size;
                    drawPanel.setBrushSize(size);
                }
            } catch (NumberFormatException e) {
                JOptionPane.showMessageDialog(this, "Invalid size entered.");
            }
        }
    }

    // 画像を保存する
    private void saveImage() {
        JFileChooser fileChooser = new JFileChooser();
        if (fileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
            File file = fileChooser.getSelectedFile();
            try {
                ImageIO.write(drawPanel.getImage(), "png", file);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }

    // 画像を開く
    private void openImage() {
        JFileChooser fileChooser = new JFileChooser();
        if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
            File file = fileChooser.getSelectedFile();
            try {
                BufferedImage image = ImageIO.read(file);
                drawPanel.setImage(image);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }

    // 描画用のパネル
    class DrawPanel extends JPanel {

        private BufferedImage image;
        private Graphics2D g2;
        private int startX, startY, endX, endY;

        public DrawPanel() {
            setPreferredSize(new Dimension(800, 600));
            setDoubleBuffered(false);
            addMouseListener(new MouseAdapter() {
                @Override
                public void mousePressed(MouseEvent e) {
                    startX = e.getX();
                    startY = e.getY();
                    if (g2 != null) {
                        if (currentTool.equals("Brush")) {
                            g2.fillOval(startX, startY, brushSize, brushSize);
                        }
                        saveToUndoStack();
                    }
                    repaint();
                }

                @Override
                public void mouseReleased(MouseEvent e) {
                    endX = e.getX();
                    endY = e.getY();
                    if (g2 != null) {
                        switch (currentTool) {
                            case "Line":
                                g2.drawLine(startX, startY, endX, endY);
                                break;
                            case "Rectangle":
                                g2.drawRect(Math.min(startX, endX), Math.min(startY, endY),
                                        Math.abs(startX - endX), Math.abs(startY - endY));
                                break;
                            case "Oval":
                                g2.drawOval(Math.min(startX, endX), Math.min(startY, endY),
                                        Math.abs(startX - endX), Math.abs(startY - endY));
                                break;
                            case "Text":
                                String text = JOptionPane.showInputDialog("Enter text:");
                                if (text != null) {
                                    g2.drawString(text, startX, startY);
                                }
                                break;
                        }
                    }
                    saveToUndoStack();
                    repaint();
                }
            });

            addMouseMotionListener(new MouseMotionAdapter() {
                @Override
                public void mouseDragged(MouseEvent e) {
                    if (currentTool.equals("Brush")) {
                        g2.fillOval(e.getX(), e.getY(), brushSize, brushSize);
                    }
                    repaint();
                }
            });

            clearCanvas();
        }

        // Undoスタックに現在の状態を保存
        private void saveToUndoStack() {
            BufferedImage undoImage = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
            Graphics2D g = undoImage.createGraphics();
            g.drawImage(image, 0, 0, null);
            g.dispose();
            undoStack.push(undoImage);
            redoStack.clear();  // 新しいアクションの後、Redoをクリア
        }

        // Undo機能
        public void undo() {
            if (!undoStack.isEmpty()) {
                redoStack.push(image);
                image = undoStack.pop();
                g2 = image.createGraphics();
                repaint();
            }
        }

        // Redo機能
        public void redo() {
            if (!redoStack.isEmpty()) {
                undoStack.push(image);
                image = redoStack.pop();
                g2 = image.createGraphics();
                repaint();
            }
        }

        // 色を設定
        public void setColor(Color color) {
            if (g2 != null) {
                g2.setColor(color);
            }
        }

        // ブラシサイズを設定
        public void setBrushSize(int size) {
            brushSize = size;
        }

        // キャンバスをクリア
        public void clearCanvas() {
            image = new BufferedImage(800, 600, BufferedImage.TYPE_INT_ARGB);
            g2 = image.createGraphics();
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2.setPaint(Color.WHITE);
            g2.fillRect(0, 0, image.getWidth(), image.getHeight());
            g2.setPaint(Color.BLACK);
            repaint();
        }

        // 描画イメージを取得
        public BufferedImage getImage() {
            return image;
        }

        // 描画イメージをセット
        public void setImage(BufferedImage img) {
            image = img;
            g2 = image.createGraphics();
            repaint();
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (image != null) {
                g.drawImage(image, 0, 0, null);
            }
        }
    }
}

投稿者: chosuke

趣味はゲームやアニメや漫画などです

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です