Last active
February 12, 2017 11:15
-
-
Save skht777/7d4d879a2396101664a82566ba0c6b09 to your computer and use it in GitHub Desktop.
雑なペイント
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package paint; | |
| import javax.swing.*; | |
| import java.awt.*; | |
| import java.awt.event.WindowAdapter; | |
| import java.awt.event.WindowEvent; | |
| import java.util.ArrayList; | |
| import java.util.Arrays; | |
| import java.util.List; | |
| /** | |
| * @author skht777 | |
| */ | |
| public class MainFrame extends JFrame { | |
| private MainFrame() { | |
| super(); | |
| setSize(700, 600); | |
| addWindowListener(new WindowAdapter() { | |
| public void windowClosing(WindowEvent windowEvent) { | |
| System.exit(0); | |
| } | |
| }); | |
| PaintCanvas canvas = new PaintCanvas(); | |
| PaintTool tool = new PaintTool(canvas); | |
| getContentPane().setLayout(new BorderLayout(10, 10)); | |
| getContentPane().add(tool, BorderLayout.WEST); | |
| getContentPane().add(canvas, BorderLayout.CENTER); | |
| // 全てのコンポーネントにキーイベントぶん投げる | |
| List<Component> list = new ArrayList<>(Arrays.asList(getComponents())); | |
| while (!list.isEmpty()) { | |
| Container c = (Container) list.remove(0); | |
| list.addAll(Arrays.asList(c.getComponents())); | |
| c.addKeyListener(canvas.getKeyListener()); | |
| } | |
| repaint(); // PaintToolを正しい形にする | |
| } | |
| public static void main(String[] args) { | |
| SwingUtilities.invokeLater(() -> new MainFrame().setVisible(true)); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package paint; | |
| import javax.swing.*; | |
| import java.awt.*; | |
| import java.awt.event.*; | |
| import java.awt.geom.AffineTransform; | |
| import java.awt.geom.Rectangle2D; | |
| import java.awt.image.BufferedImage; | |
| import java.util.ArrayList; | |
| import java.util.List; | |
| /** | |
| * @author skht777 | |
| */ | |
| public class PaintCanvas extends JPanel implements ShapeObserver { | |
| private final List<BufferedImage> histrory; | |
| private final AffineTransform at; | |
| private Shape shape; | |
| private Color color; | |
| private final MouseAdapter adpter = new MouseAdapter() { | |
| @Override | |
| public void mouseDragged(MouseEvent e) { | |
| draw(e.getX(), e.getY()); | |
| repaint(); | |
| } | |
| @Override | |
| public void mousePressed(MouseEvent e) { | |
| histrory.add(createAlphaImage()); | |
| draw(e.getX(), e.getY()); | |
| repaint(); | |
| } | |
| }; | |
| public PaintCanvas() { | |
| super(); | |
| histrory = new ArrayList<>(); | |
| at = new AffineTransform(); | |
| setBackground(Color.white); | |
| addMouseListener(adpter); | |
| addMouseMotionListener(adpter); | |
| } | |
| // ctr(⌘) + zでundo | |
| public KeyListener getKeyListener() { | |
| return new KeyAdapter() { | |
| @Override | |
| public void keyPressed(KeyEvent e) { | |
| int mask = System.getProperty("os.name").equals("Mac OS X") ? | |
| InputEvent.META_DOWN_MASK : InputEvent.CTRL_DOWN_MASK; | |
| if (e.getKeyCode() == KeyEvent.VK_Z && e.getModifiersEx() == mask | |
| && !histrory.isEmpty()) { | |
| histrory.remove(histrory.size() - 1); | |
| repaint(); | |
| } | |
| } | |
| }; | |
| } | |
| @Override | |
| protected void paintComponent(Graphics g) { | |
| super.paintComponent(g); | |
| final Graphics2D g2 = (Graphics2D) g; | |
| histrory.forEach(im -> g2.drawImage(im, 0, 0, null)); | |
| } | |
| // Imageを重ねるために透明なレイヤーを用意する | |
| private BufferedImage createAlphaImage() { | |
| final int width = getWidth(), height = getHeight(); | |
| BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); | |
| final Graphics2D g = (Graphics2D) image.getGraphics(); | |
| g.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.0f)); | |
| g.fill(new Rectangle2D.Double(0, 0, width, height)); | |
| g.setPaintMode(); | |
| g.dispose(); | |
| return image; | |
| } | |
| private void draw(int x, int y) { | |
| final Graphics2D g = (Graphics2D) histrory.get(histrory.size() - 1).getGraphics(); | |
| // Shapeの現在位置と描画位置の相対位置を求めて平行移動する変換式を設定 | |
| at.setToTranslation(x - shape.getBounds2D().getX(), y - shape.getBounds2D().getY()); | |
| g.setColor(color); | |
| g.fill(at.createTransformedShape(shape)); | |
| g.dispose(); | |
| } | |
| @Override | |
| public void updateShape(Shape s) { | |
| shape = s; | |
| } | |
| @Override | |
| public void updateColor(Color c) { | |
| color = c; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package paint; | |
| import javax.swing.*; | |
| import javax.swing.border.EmptyBorder; | |
| import javax.swing.border.LineBorder; | |
| import java.awt.*; | |
| import java.awt.event.MouseAdapter; | |
| import java.awt.event.MouseEvent; | |
| import java.awt.event.MouseListener; | |
| import java.awt.geom.Ellipse2D; | |
| import java.awt.geom.Rectangle2D; | |
| import java.util.function.Consumer; | |
| import java.util.stream.IntStream; | |
| /** | |
| * @author skht777 | |
| */ | |
| public class PaintTool extends JPanel { | |
| private final ShapeObserver observer; | |
| private static final int BASE_BOLD = 3; | |
| private Shape2D shape; | |
| private int size; | |
| // 描画する図形の識別用 | |
| private enum Shape2D { | |
| RECT(new Palette(Color.white)) { | |
| @Override | |
| Shape createShape(int size) { | |
| return new Rectangle2D.Double(0, 0, size, size); | |
| } | |
| }, | |
| ELLIPSE(new Palette(Color.black)) { | |
| @Override | |
| Shape createShape(int size) { | |
| return new Ellipse2D.Double(0, 0, size, size); | |
| } | |
| }; | |
| private final Palette palette; | |
| private Shape2D(Palette palette) { | |
| this.palette = palette; | |
| } | |
| Palette getPalette() { | |
| return palette; | |
| } | |
| abstract Shape createShape(int size); | |
| } | |
| // カラーパレット | |
| private static class Palette { | |
| private Color color; | |
| Palette(Color initialColor) { | |
| color = initialColor; | |
| } | |
| public void colorChoose() { | |
| Color c = JColorChooser.showDialog(null, "色選択", color); | |
| if (c != null) color = c; | |
| } | |
| public Color getColor() { | |
| return color; | |
| } | |
| } | |
| // カラーパレット用のパネル | |
| private class PalettePanel extends JPanel { | |
| private Palette palette; | |
| PalettePanel(Palette palette) { | |
| this.palette = palette; | |
| addMouseListener(PaintTool.this.implMouseClicked(e -> { | |
| palette.colorChoose(); | |
| repaint(); | |
| PaintTool.this.update(); | |
| })); | |
| } | |
| @Override | |
| protected void paintComponent(Graphics g) { | |
| super.paintComponent(g); | |
| final int size = 30; | |
| final Graphics2D g2 = (Graphics2D) g; | |
| // 現在の色を選択して描画 | |
| g2.setColor(palette.getColor()); | |
| g2.fill(new Rectangle2D.Double((getWidth() - size) / 2, 10, size, size)); | |
| } | |
| } | |
| public PaintTool(ShapeObserver observer) { | |
| shape = Shape2D.ELLIPSE; | |
| size = BASE_BOLD; | |
| this.observer = observer; | |
| setLayout(new GridLayout(2, 1, 5, 5)); | |
| add(getToolBox()); | |
| add(getOptionBox()); | |
| update(); | |
| } | |
| private JPanel getLayoutedPanel(int row, int col) { | |
| JPanel panel = new JPanel(); | |
| panel.setBorder(new EmptyBorder(0, 5, 0, 0)); | |
| panel.setLayout(new GridLayout(row, col, 0, 5)); | |
| return panel; | |
| } | |
| private JPanel getPanelWithBorder(int row, int col) { | |
| JPanel panel = getLayoutedPanel(row, col); | |
| panel.setBorder(new LineBorder(Color.black)); | |
| return panel; | |
| } | |
| // 描画モードの設定ボックス | |
| private JPanel getToolBox() { | |
| JPanel tool = getLayoutedPanel(5, 2); | |
| JButton pen = new JButton("書く"); | |
| pen.addMouseListener(implMouseClicked(e -> { | |
| shape = Shape2D.ELLIPSE; | |
| update(); | |
| })); | |
| JButton eraser = new JButton("消す"); | |
| eraser.addMouseListener(implMouseClicked(e -> { | |
| shape = Shape2D.RECT; | |
| update(); | |
| })); | |
| tool.add(pen); | |
| tool.add(eraser); | |
| return tool; | |
| } | |
| // 描画オプションの設定ボックス | |
| private JPanel getOptionBox() { | |
| JPanel option = getLayoutedPanel(2, 1); | |
| // 描画の太さの設定(MSペイントのパクリ) | |
| JPanel bold = getPanelWithBorder(4, 1); | |
| IntStream.rangeClosed(1, 4).map(i -> i * BASE_BOLD) | |
| .mapToObj(i -> { | |
| // TODO クラス化を検討 | |
| JPanel panel = new JPanel() { | |
| @Override | |
| protected void paintComponent(Graphics g) { | |
| super.paintComponent(g); | |
| final Graphics2D g2 = (Graphics2D) g; | |
| g2.fill(new Rectangle2D.Double(5, (getHeight() - i) / 2.0, getWidth() - 10, i)); | |
| } | |
| }; | |
| panel.addMouseListener(implMouseClicked(e -> { | |
| // 選んだやつの色を変える | |
| bold.getComponent(size / BASE_BOLD - 1).setBackground(bold.getBackground()); | |
| panel.setBackground(Color.cyan); | |
| size = i; | |
| update(); | |
| })); | |
| return panel; | |
| }).forEach(bold::add); | |
| bold.getComponent(0).setBackground(Color.cyan); | |
| // カラーパレットの設定 | |
| JPanel palette = getPanelWithBorder(2, 1); | |
| palette.add(new PalettePanel(Shape2D.ELLIPSE.getPalette())); | |
| palette.add(new PalettePanel(Shape2D.RECT.getPalette())); | |
| option.add(bold); | |
| option.add(palette); | |
| return option; | |
| } | |
| // オブザーバに現在の設定をぶん投げる | |
| private void update() { | |
| observer.upadate(shape.createShape(size), shape.getPalette().getColor()); | |
| } | |
| private MouseListener implMouseClicked(Consumer<MouseEvent> impl) { | |
| return new MouseAdapter() { | |
| @Override | |
| public void mouseClicked(MouseEvent e) { | |
| impl.accept(e); | |
| } | |
| }; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package paint; | |
| import java.awt.*; | |
| /** | |
| * @author skht777 | |
| */ | |
| interface ShapeObserver { | |
| void updateShape(Shape s); | |
| void updateColor(Color c); | |
| default void upadate(Shape s, Color c) { | |
| updateShape(s); | |
| updateColor(c); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment