###前提・実現したいこと
Javaでペイントツールを製作しています。
ドラッグ中は破線で四角形を描画し、ドラッグから離れたら実線で四角形を描画する機能と、
1回だけundoできる機能の実装を考えているのですが、
undo機能の方がうまく動きません。
###発生している問題・エラーメッセージ
要素数2の配列に対して実線が描画された画面の画像を交互に保存し、
undoが呼び出されたら配列から直前の画像を呼び出してrepaintを行う。という方法をとりたいのですが、
repaintメソッドの処理の順番をよく理解できておらず、実線が描画された状態の画像を保存するつもりが
破線の状態の画像を保存してしまいundoに失敗しています。
なにか方法がありましたら教えていただけると助かります。
よろしくお願いいたします。
###ソースコード
Java
1public class DrawTest extends JPanel implements MouseListener, MouseMotionListener, KeyListener{ 2 /*** フィールド ***/ 3 //ウィンドウ 4 JFrame frame; 5 //線 6 BasicStroke graphicStroke; //範囲確定後描画用の実線 7 BasicStroke dashStroke; //範囲確定前描画用の点線 8 9 //画像 10 BufferedImage buf; //キャプチャ画像 11 Graphics2D b2; //キャプチャ画像の描画情報 12 BufferedImage[] imgList; //undo用配列 13 Boolean confirm; //範囲確定判断 14 int imageCount; //描画した回数 15 16 //座標 17 int x1,y1; //始点座標 18 int x2,y2; //終点座標 19 20 /*** コンストラクタ ***/ 21 public DrawTest() { 22 // ウィンドウ 23 java.awt.GraphicsEnvironment env = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(); 24 java.awt.DisplayMode displayMode = env.getDefaultScreenDevice().getDisplayMode(); 25 int frameWidth = displayMode.getWidth(); 26 int frameHeight = displayMode.getHeight(); 27 frame = new JFrame(); 28 frame.setUndecorated(true); 29 frame.setSize(frameWidth, frameHeight); 30 31 // 画像 32 buf = captureDisplay(); 33 imgList = new BufferedImage[2]; 34 imgList[0] = deepCopy(buf); 35 imgList[1] = deepCopy(buf); 36 Graphics b = buf.createGraphics(); 37 b2 = (Graphics2D) b; 38 39 // 線 40 float[] dash = { 10.0f, 5.0f, 20.0f, 5.0f }; 41 graphicStroke = new BasicStroke(15, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER); 42 dashStroke = new BasicStroke(5.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f, dash, 0.0f); 43 b2.setStroke(graphicStroke); 44 b2.setColor(Color.BLACK); 45 46 // 初期化 47 confirm = false; 48 imageCount = 0; 49 50 // リスナー 51 frame.addMouseListener(this); 52 frame.addMouseMotionListener(this); 53 frame.addKeyListener(this); 54 55 // 可視化 56 frame.getContentPane().add(this); 57 frame.setVisible(true); 58 frame.isFocusable(); 59 } 60 61 /*** 描画 ***/ 62 public void paintComponent(Graphics g){ 63 Graphics2D g2 = (Graphics2D) g; 64 g2.setStroke(dashStroke); 65 g2.setColor(Color.BLACK); 66 67 // 左上の座標と幅と高さ 68 int rectX = x1; 69 int rectY = y1; 70 int rectW = x2 - x1; 71 int rectH = y2 - y1; 72 73 // 座標調整 74 if (rectW < 0 && rectH >= 0) { 75 rectX = x2; 76 rectW = x1 - x2; 77 } else if (rectH < 0 && rectW >= 0) { 78 rectY = y2; 79 rectH = y1 - y2; 80 } else if (rectH < 0 && rectW < 0) { 81 rectX = x2; 82 rectY = y2; 83 rectW = x1 - x2; 84 rectH = y1 - y2; 85 } 86 87 // mouseReleasedから呼び出されていればtrue 88 if(confirm){ 89 // 画像に実線で描画 90 b2.drawRect(rectX, rectY, rectW, rectH); 91 int rem = imageCount % 2; 92 imgList[rem] = captureDisplay(); 93 94 imageCount++; 95 confirm = false; 96 } 97 98 // キャプチャ画像をパネルに反映 99 g2.drawImage(buf, 0, 0, this); 100 101 // パネルに破線で描画 102 g2.drawRect(rectX, rectY, rectW, rectH); 103 104 } 105 106 /*** 画面をキャプチャ ***/ 107 public BufferedImage captureDisplay() { 108 BufferedImage image = null; 109 try { 110 image = new Robot().createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize())); 111 } catch (HeadlessException | AWTException e) { 112 e.printStackTrace(); 113 } 114 return image; 115 } 116 117 /*** BufferedImage型のclone作成 ***/ 118 public static BufferedImage deepCopy(BufferedImage original) { 119 ColorModel cm = original.getColorModel(); 120 boolean isAlphaPremultiplied = cm.isAlphaPremultiplied(); 121 WritableRaster raster = original.copyData(original.getRaster().createCompatibleWritableRaster()); 122 return new BufferedImage(cm, raster, isAlphaPremultiplied, null); 123 } 124 125 /*** undo ***/ 126 public void undo(){ 127 int rem = imageCount % 2; 128 if(rem == 0){ 129 buf = deepCopy(imgList[0]); 130 imgList[1] = deepCopy(imgList[0]); 131 }else{ 132 buf = deepCopy(imgList[1]); 133 imgList[0] = deepCopy(imgList[1]); 134 } 135 } 136 137 /*** 以下リスナーで呼び出されるメソッド ***/ 138 public void mousePressed(MouseEvent e) { 139 // 始点更新 140 x1 = e.getX(); 141 y1 = e.getY(); 142 } 143 144 public void mouseDragged(MouseEvent e) { 145 // 終点更新 146 x2 = e.getX(); 147 y2 = e.getY(); 148 149 repaint(); 150 } 151 152 public void mouseClicked(MouseEvent e) { 153 // 右クリックが押されたらundo実行 154 if(e.getButton() == MouseEvent.BUTTON3){ 155 undo(); 156 } 157 } 158 159 public void mouseReleased(MouseEvent e) { 160 // 終点更新後、範囲確定フラグにtrueを入れて再描画 161 x2 = e.getX(); 162 y2 = e.getY(); 163 164 confirm = true; 165 repaint(); 166 } 167 168 public void keyPressed(KeyEvent e) { 169 // ESCが押されたら終了 170 if(e.getKeyCode() == KeyEvent.VK_ESCAPE){ 171 System.exit(0); 172 } 173 } 174 175 /*** main ***/ 176 public static void main(String[] args) { 177 DrawTest dtest = new DrawTest(); 178 }
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/02/26 13:08