Source Code: Paint Program
The source code files can be viewed in a text editor like Notepad++. Or, the source code can be compiled and run in an IDE environment like Eclipse. Download Source Code
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 | /***************************************************************************** * Lab13: The Paint Program * Name: Samantha Yu * Submitted to AP Computer Science 12: January 27, 2015 * Last modified: April 4, 2015 * Teacher: Christopher Slowley ******************************************************************************/ import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.Frame; import java.awt.event.WindowListener; import java.awt.event.WindowEvent; import java.awt.event.MouseMotionListener; import java.awt.event.MouseListener; import java.awt.event.MouseEvent; public class PaintApp extends Frame implements WindowListener, MouseListener, MouseMotionListener { /** * */ private static final long serialVersionUID = 5650761267721782655L; // Used when creating the frame of the paint program private int appWidth, appHeight, canvasHeight; private Menu menuBar; private Tools toolbar; private int menuHeight; private Rectangle canvasRect; // Canvas is not visible and does not include menu bar private boolean firstPaint, menuChange, continuePaint; // Used as "switches" during program execution private int oldX, oldY, newX, newY; // Used on mouse events private Graphics2D g2Frame; // The Graphics2D class provides "more sophisticated control over geometry, coordinate transformations, color management, and text layout" // (see "http://docs.oracle.com/javase/7/docs/api/java/awt/Graphics2D.html") than its superclass, the Graphics class, // Such as being able to paint lines that have different edges private Layers layersArray; public static void main(String args[]) { // The main method handles the application's framework (such as event listeners) and makes the window visible PaintApp paintProgram = new PaintApp(); paintProgram.addWindowListener(paintProgram); paintProgram.addMouseListener(paintProgram); paintProgram.addMouseMotionListener(paintProgram); paintProgram.appWidth = 761 ; paintProgram.appHeight = 380 ; paintProgram.setSize(paintProgram.appWidth, paintProgram.appHeight); paintProgram.setVisible( true ); paintProgram.createApp(); } public void createApp() { // Menu bar, canvas, layers array, and toolbar are created menuHeight = 75 ; createCanvas(); layersArray = new Layers( this ); // The menu bar's selection boxes are created but not the buttons that you can see; i.e. buttons are invisible menuBar = new Menu( this , layersArray); toolbar = new Tools( this , menuBar, layersArray); firstPaint = true ; } public void paint(Graphics g) { // Called after paintProgram became visible and whenever the graphical output needs to be updated or repainted g2Frame = (Graphics2D) g; // The abstract Graphics2D class extends the abstract Graphics class if (firstPaint) { menuBar.createMenu(); // Menu items are drawn onto the menu off-screen image g2Frame.drawImage(menuBar.menuImage, 0 , 0 , this ); // Off-screen image is drawn onto the application; menu becomes visible firstPaint = false ; continuePaint = true ; } else { if (continuePaint) { // If a user's mouse did not click inside the menu, the mouse paints with the user's selected tool, size, and color toolbar.useTool(menuBar.getNumTool(), oldX, oldY, newX, newY); } else { // If a menu item is selected, then the area underneath the menu is not painted continuePaint = true ; // When the user selects a large size for their tool, then the canvas will not be accidentally painted. } paintLayers(g2Frame); if (menuChange) { // If the user has selected a menu item, the menu bar is updated and redrawn menuBar.changeToolMenu(); menuChange = false ; } g2Frame.drawImage(menuBar.menuImage, 0 , 0 , this ); // Prevents the menu bar from disappearing when the application has gone inactive or been resized } } public void paintLayers(Graphics2D g2Frame) { // When a layer is created or deleted, or the user decides to switch to a different layer if (layersArray.deleteLayer) { // A layer is deleted (can be any layer, not just the last layer in imageArray, that is not the only layer left) g2Frame.drawImage(layersArray.getImageArray().get(layersArray.getcLayerNum()), 0 , getMenuHeight(), this ); // Draws the blank deleted layer // Otherwise, the deleted layer will remain and is not erased on screen for ( int k = 0 ; k < layersArray.getImageArray().size(); k++) { // Then draws the rest of the layers in ascending order if (k!=layersArray.getcLayerNum()) { g2Frame.drawImage(layersArray.getImageArray().get(k), 0 , getMenuHeight(), this ); } } layersArray.deleteLayer = false ; layersArray.getImageArray().remove(layersArray.getcLayerNum()); // Removes the blank deleted layer from imageArray if (layersArray.getcLayerNum() == layersArray.getImageArray().size()) // If the deleted layer was the last layer, then decrease cLayerNum layersArray.setcLayerNum(layersArray.getcLayerNum() - 1 ); // If not, then cLayerNum is not decreased // eg If the third layer is deleted, then the next layer which used to be the fourth layer is now the third layer g2Frame.drawImage(layersArray.getImageArray().get(layersArray.getcLayerNum()), 0 , getMenuHeight(), this ); // The current layer is drawn last for visibility } else { // If you are not deleting a layer, update only the current layer's graphics. // If you constantly redrawing the other layers, then those other layers will flicker in the background g2Frame.drawImage(layersArray.getImageArray().get(layersArray.getcLayerNum()), 0 , getMenuHeight(), this ); } if (layersArray.changeLayer) { // If a layer is created or deleted, or the user switches to the previous or next layer menuBar.changeLayerMenu(); // Layer status is updated layersArray.changeLayer = false ; } } public void windowClosing(WindowEvent e) { dispose(); System.exit( 0 ); // Normal exit of program } // These window events are required to be implemented, because this class implements the WindowListener // However, this paint program does not need these window events so these methods are left blank public void windowOpened(WindowEvent e){} public void windowIconified(WindowEvent e){} public void windowClosed(WindowEvent e){} public void windowDeiconified(WindowEvent e){} public void windowActivated(WindowEvent e){} public void windowDeactivated(WindowEvent e){} private void createCanvas() { // Creates the canvas that the user can draw on; user cannot draw on menu canvasHeight = appHeight - getMenuHeight(); canvasRect = new Rectangle( 0 ,getMenuHeight(),appWidth, canvasHeight); } public int getAppWidth() { // Returns the private appWidth attribute return appWidth; } public int getCanvasHeight() { // Returns the private canvasHeight attribute return canvasHeight; } public int getMenuHeight() { // Returns the private menuHeight attribute return menuHeight; } // These mouse events are required to be implemented, because this class implements the MouseListener and MouseMotionListener // However, this paint program does not need these mouse events so these methods are left blank public void mouseClicked(MouseEvent e) {} // When the mouse button is pressed down then released public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mouseMoved(MouseEvent e) {} // When the mouse is moving but none of the buttons are held down public void mousePressed(MouseEvent e) { // When any of the mouse buttons are pressed down menuBar.select(e.getX(), e.getY()); newX = e.getX(); newY = e.getY(); oldX = e.getX(); oldY = e.getY(); if (menuBar.menuRect.contains(e.getX(),e.getY())) { continuePaint = false ; // After the user selects a menu item, continuePaint will prevent the area under the menu from getting painted. menuChange = true ; repaint(); } if (canvasRect.contains(e.getX(), e.getY())) { // The application repaints if the user clicks inside the canvas repaint(); } } public void mouseDragged(MouseEvent e) { // When any of the mouse buttons are held down while the mouse is dragged oldX = newX; oldY = newY; newX = e.getX(); newY = e.getY(); if (canvasRect.contains(e.getX(), e.getY())) { // The application repaints only if the user drags the mouse inside the canvas repaint(); } } public void mouseReleased(MouseEvent e) { // When any of the mouse buttons are lifted up newX = e.getX(); newY = e.getY(); if (canvasRect.contains(e.getX(), e.getY())) { // The application repaints only if the user lifts the mouse inside the canvas repaint(); } } public void update(Graphics g) { // When repaint() is called, the update() then calls paint() // Since "default implementation of update() clears the Component's background before calling paint()", // I removed the background layers from flickering by drawing the layers here for ( int k = 0 ; k < layersArray.getImageArray().size(); k++) { g2Frame.drawImage(layersArray.getImageArray().get(k), 0 , getMenuHeight(), this ); } paint(g); } } |
/***************************************************************************** * Lab13: The Paint Program * Name: Samantha Yu * Submitted to AP Computer Science 12: January 27, 2015 * Last modified: April 4, 2015 * Teacher: Christopher Slowley ******************************************************************************/ import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.Frame; import java.awt.event.WindowListener; import java.awt.event.WindowEvent; import java.awt.event.MouseMotionListener; import java.awt.event.MouseListener; import java.awt.event.MouseEvent; public class PaintApp extends Frame implements WindowListener, MouseListener, MouseMotionListener { /** * */ private static final long serialVersionUID = 5650761267721782655L; // Used when creating the frame of the paint program private int appWidth, appHeight, canvasHeight; private Menu menuBar; private Tools toolbar; private int menuHeight; private Rectangle canvasRect; // Canvas is not visible and does not include menu bar private boolean firstPaint, menuChange, continuePaint; // Used as "switches" during program execution private int oldX, oldY, newX, newY; // Used on mouse events private Graphics2D g2Frame; // The Graphics2D class provides "more sophisticated control over geometry, coordinate transformations, color management, and text layout" // (see "http://docs.oracle.com/javase/7/docs/api/java/awt/Graphics2D.html") than its superclass, the Graphics class, // Such as being able to paint lines that have different edges private Layers layersArray; public static void main(String args[]) { // The main method handles the application's framework (such as event listeners) and makes the window visible PaintApp paintProgram = new PaintApp(); paintProgram.addWindowListener(paintProgram); paintProgram.addMouseListener(paintProgram); paintProgram.addMouseMotionListener(paintProgram); paintProgram.appWidth = 761; paintProgram.appHeight = 380; paintProgram.setSize(paintProgram.appWidth, paintProgram.appHeight); paintProgram.setVisible(true); paintProgram.createApp(); } public void createApp() { // Menu bar, canvas, layers array, and toolbar are created menuHeight = 75; createCanvas(); layersArray = new Layers(this); // The menu bar's selection boxes are created but not the buttons that you can see; i.e. buttons are invisible menuBar = new Menu(this, layersArray); toolbar = new Tools(this, menuBar, layersArray); firstPaint = true; } public void paint(Graphics g) { // Called after paintProgram became visible and whenever the graphical output needs to be updated or repainted g2Frame = (Graphics2D) g; // The abstract Graphics2D class extends the abstract Graphics class if (firstPaint) { menuBar.createMenu(); // Menu items are drawn onto the menu off-screen image g2Frame.drawImage(menuBar.menuImage, 0, 0, this); // Off-screen image is drawn onto the application; menu becomes visible firstPaint = false; continuePaint = true; } else { if (continuePaint) { // If a user's mouse did not click inside the menu, the mouse paints with the user's selected tool, size, and color toolbar.useTool(menuBar.getNumTool(), oldX, oldY, newX, newY); } else { // If a menu item is selected, then the area underneath the menu is not painted continuePaint = true; // When the user selects a large size for their tool, then the canvas will not be accidentally painted. } paintLayers(g2Frame); if (menuChange) { // If the user has selected a menu item, the menu bar is updated and redrawn menuBar.changeToolMenu(); menuChange = false; } g2Frame.drawImage(menuBar.menuImage, 0, 0, this); // Prevents the menu bar from disappearing when the application has gone inactive or been resized } } public void paintLayers(Graphics2D g2Frame) { // When a layer is created or deleted, or the user decides to switch to a different layer if (layersArray.deleteLayer) { // A layer is deleted (can be any layer, not just the last layer in imageArray, that is not the only layer left) g2Frame.drawImage(layersArray.getImageArray().get(layersArray.getcLayerNum()), 0, getMenuHeight(), this); // Draws the blank deleted layer // Otherwise, the deleted layer will remain and is not erased on screen for (int k = 0; k < layersArray.getImageArray().size(); k++) { // Then draws the rest of the layers in ascending order if (k!=layersArray.getcLayerNum()) { g2Frame.drawImage(layersArray.getImageArray().get(k), 0, getMenuHeight(), this); } } layersArray.deleteLayer = false; layersArray.getImageArray().remove(layersArray.getcLayerNum()); // Removes the blank deleted layer from imageArray if (layersArray.getcLayerNum() == layersArray.getImageArray().size()) // If the deleted layer was the last layer, then decrease cLayerNum layersArray.setcLayerNum(layersArray.getcLayerNum() - 1); // If not, then cLayerNum is not decreased // eg If the third layer is deleted, then the next layer which used to be the fourth layer is now the third layer g2Frame.drawImage(layersArray.getImageArray().get(layersArray.getcLayerNum()), 0, getMenuHeight(), this); // The current layer is drawn last for visibility } else { // If you are not deleting a layer, update only the current layer's graphics. // If you constantly redrawing the other layers, then those other layers will flicker in the background g2Frame.drawImage(layersArray.getImageArray().get(layersArray.getcLayerNum()), 0, getMenuHeight(), this); } if (layersArray.changeLayer) { // If a layer is created or deleted, or the user switches to the previous or next layer menuBar.changeLayerMenu(); // Layer status is updated layersArray.changeLayer = false; } } public void windowClosing(WindowEvent e) { dispose(); System.exit(0); // Normal exit of program } // These window events are required to be implemented, because this class implements the WindowListener // However, this paint program does not need these window events so these methods are left blank public void windowOpened(WindowEvent e){} public void windowIconified(WindowEvent e){} public void windowClosed(WindowEvent e){} public void windowDeiconified(WindowEvent e){} public void windowActivated(WindowEvent e){} public void windowDeactivated(WindowEvent e){} private void createCanvas() { // Creates the canvas that the user can draw on; user cannot draw on menu canvasHeight = appHeight - getMenuHeight(); canvasRect = new Rectangle(0,getMenuHeight(),appWidth, canvasHeight); } public int getAppWidth() { // Returns the private appWidth attribute return appWidth; } public int getCanvasHeight() { // Returns the private canvasHeight attribute return canvasHeight; } public int getMenuHeight() { // Returns the private menuHeight attribute return menuHeight; } // These mouse events are required to be implemented, because this class implements the MouseListener and MouseMotionListener // However, this paint program does not need these mouse events so these methods are left blank public void mouseClicked(MouseEvent e) {} // When the mouse button is pressed down then released public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mouseMoved(MouseEvent e) {} // When the mouse is moving but none of the buttons are held down public void mousePressed(MouseEvent e) { // When any of the mouse buttons are pressed down menuBar.select(e.getX(), e.getY()); newX = e.getX(); newY = e.getY(); oldX = e.getX(); oldY = e.getY(); if (menuBar.menuRect.contains(e.getX(),e.getY())) { continuePaint = false; // After the user selects a menu item, continuePaint will prevent the area under the menu from getting painted. menuChange = true; repaint(); } if (canvasRect.contains(e.getX(), e.getY())) { // The application repaints if the user clicks inside the canvas repaint(); } } public void mouseDragged(MouseEvent e) { // When any of the mouse buttons are held down while the mouse is dragged oldX = newX; oldY = newY; newX = e.getX(); newY = e.getY(); if (canvasRect.contains(e.getX(), e.getY())) { // The application repaints only if the user drags the mouse inside the canvas repaint(); } } public void mouseReleased(MouseEvent e) { // When any of the mouse buttons are lifted up newX = e.getX(); newY = e.getY(); if (canvasRect.contains(e.getX(), e.getY())) { // The application repaints only if the user lifts the mouse inside the canvas repaint(); } } public void update(Graphics g) { // When repaint() is called, the update() then calls paint() // Since "default implementation of update() clears the Component's background before calling paint()", // (see http://journals.ecs.soton.ac.uk/java/tutorial/ui/drawing/update.html) // I removed the background layers from flickering by drawing the layers here for (int k = 0; k < layersArray.getImageArray().size(); k++) { g2Frame.drawImage(layersArray.getImageArray().get(k), 0, getMenuHeight(), this); } paint(g); } }
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | /***************************************************************************** * Lab13: The Paint Program: Layers class * Name: Samantha Yu * Submitted to AP Computer Science 12: January 27, 2015 * Last modified: April 4, 2015 * Teacher: Christopher Slowley ******************************************************************************/ import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.util.ArrayList; import javax.swing.JOptionPane; public class Layers { PaintApp paintLab; // A PaintApp object has only one instance and allows this class to access its non-static methods and attributes // I did not make PaintApp's attributes static, because those attributes refer to the one and same object, the paint program // I did not want to place the Menu's methods into PaintApp, because those methods belong in its own separate category // So, this Layers class must be able to access and change the graphical output of PaintApp such as repaint() private ArrayList<BufferedImage> imageArray; // Stores buffered images of each layer // I decided to use the BufferedImage class instead of its superclass, the Image class, due to its ability to include transparency private int cLayerNum; // The index, cLayerNum, of imageArray allows access to the current layer and makes a graphical context for that layer public boolean deleteLayer, changeLayer; public Layers(PaintApp pLab) { // Creates an ArrayList of BufferedImages to contain the layers and creates an initial layer paintLab = pLab; imageArray = new ArrayList<BufferedImage>(); BufferedImage bImage = new BufferedImage(paintLab.getAppWidth(), paintLab.getCanvasHeight(), BufferedImage.TYPE_INT_ARGB); imageArray.add(bImage); // Adds the first layer cLayerNum = 0 ; } public void newLayer() { // Creates a new layer after the current layer BufferedImage bImage = new BufferedImage(paintLab.getAppWidth(), paintLab.getCanvasHeight(), BufferedImage.TYPE_INT_ARGB); cLayerNum++; imageArray.add(cLayerNum,bImage); // Adds that layer after the current layer deleteLayer = false ; changeLayer = true ; paintLab.repaint(); } public void previousLayer() { // User switches to the previous layer if (cLayerNum > 0 ) { // If the previous layer's index exists in imageArray cLayerNum--; changeLayer = true ; } else { // Prevents the user from accessing a layer that does not exist and getting an index out of bounds error JOptionPane.showMessageDialog( null , "Sorry, but you cannot go to a layer that does not exist yet." ); } paintLab.repaint(); // The graphical output is repainted, because when the notification pops up it erases some of the graphics // Also, this allows for the previous layer's graphics to now be at the top and fully visible } public void nextLayer() { // User switches to the next layer if (cLayerNum < imageArray.size() - 1 ) { // If the next layer's index exists in imageArray cLayerNum++; changeLayer = true ; } else { JOptionPane.showMessageDialog( null , "Sorry, but you cannot go to a layer that does not exist yet." ); } paintLab.repaint(); // The graphical output is repainted, because when the notification pops up it erases some of the graphics // Also, this allows for the previous layer's graphics to now be at the top and fully visible } public void deleteLayer() { // User deletes the current layer if ((cLayerNum != imageArray.size() - 1 ) || (cLayerNum > 0 )) { // If the current layer is not the only layer left BufferedImage bImage = new BufferedImage(paintLab.getAppWidth(), paintLab.getCanvasHeight(), BufferedImage.TYPE_INT_ARGB); Graphics2D buffg = (Graphics2D) bImage.getGraphics(); buffg.fillRect( 0 , 0 , paintLab.getAppWidth(), paintLab.getCanvasHeight()); // Creates a blank image the size of the canvas imageArray.set(cLayerNum, bImage); // Sets the current layer to this blank image deleteLayer = true ; changeLayer = true ; paintLab.repaint(); // The blank image (user-requested deleted layer) clears the canvas and the other layers are redrawn on top } else { // User cannot delete the only layer JOptionPane.showMessageDialog( null , "Sorry, but you cannot delete your only layer." ); paintLab.repaint(); } } public ArrayList<BufferedImage> getImageArray() { // Returns the private imageArray return imageArray; } public int getcLayerNum() { // Returns the private cLayerNum attribute, the current index of imageArray, so that other classes can properly access cLayerNum return cLayerNum; } public void setcLayerNum( int cNum) { // Sets the cLayerNum to the new current layer's index cLayerNum = cNum; } } |
/***************************************************************************** * Lab13: The Paint Program: Layers class * Name: Samantha Yu * Submitted to AP Computer Science 12: January 27, 2015 * Last modified: April 4, 2015 * Teacher: Christopher Slowley ******************************************************************************/ import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.util.ArrayList; import javax.swing.JOptionPane; public class Layers { PaintApp paintLab; // A PaintApp object has only one instance and allows this class to access its non-static methods and attributes // I did not make PaintApp's attributes static, because those attributes refer to the one and same object, the paint program // I did not want to place the Menu's methods into PaintApp, because those methods belong in its own separate category // So, this Layers class must be able to access and change the graphical output of PaintApp such as repaint() private ArrayList<BufferedImage> imageArray; // Stores buffered images of each layer // I decided to use the BufferedImage class instead of its superclass, the Image class, due to its ability to include transparency private int cLayerNum; // The index, cLayerNum, of imageArray allows access to the current layer and makes a graphical context for that layer public boolean deleteLayer, changeLayer; public Layers(PaintApp pLab) { // Creates an ArrayList of BufferedImages to contain the layers and creates an initial layer paintLab = pLab; imageArray = new ArrayList<BufferedImage>(); BufferedImage bImage = new BufferedImage(paintLab.getAppWidth(), paintLab.getCanvasHeight(), BufferedImage.TYPE_INT_ARGB); imageArray.add(bImage); // Adds the first layer cLayerNum = 0; } public void newLayer() { // Creates a new layer after the current layer BufferedImage bImage = new BufferedImage(paintLab.getAppWidth(), paintLab.getCanvasHeight(), BufferedImage.TYPE_INT_ARGB); cLayerNum++; imageArray.add(cLayerNum,bImage); // Adds that layer after the current layer deleteLayer = false; changeLayer = true; paintLab.repaint(); } public void previousLayer() { // User switches to the previous layer if (cLayerNum > 0) { // If the previous layer's index exists in imageArray cLayerNum--; changeLayer = true; } else { // Prevents the user from accessing a layer that does not exist and getting an index out of bounds error JOptionPane.showMessageDialog(null, "Sorry, but you cannot go to a layer that does not exist yet."); } paintLab.repaint(); // The graphical output is repainted, because when the notification pops up it erases some of the graphics // Also, this allows for the previous layer's graphics to now be at the top and fully visible } public void nextLayer() { // User switches to the next layer if (cLayerNum < imageArray.size() - 1) { // If the next layer's index exists in imageArray cLayerNum++; changeLayer = true; } else { JOptionPane.showMessageDialog(null, "Sorry, but you cannot go to a layer that does not exist yet."); } paintLab.repaint(); // The graphical output is repainted, because when the notification pops up it erases some of the graphics // Also, this allows for the previous layer's graphics to now be at the top and fully visible } public void deleteLayer() { // User deletes the current layer if ((cLayerNum != imageArray.size() - 1) || (cLayerNum > 0)) { // If the current layer is not the only layer left BufferedImage bImage = new BufferedImage(paintLab.getAppWidth(), paintLab.getCanvasHeight(), BufferedImage.TYPE_INT_ARGB); Graphics2D buffg = (Graphics2D) bImage.getGraphics(); buffg.fillRect(0, 0, paintLab.getAppWidth(), paintLab.getCanvasHeight()); // Creates a blank image the size of the canvas imageArray.set(cLayerNum, bImage); // Sets the current layer to this blank image deleteLayer = true; changeLayer = true; paintLab.repaint(); // The blank image (user-requested deleted layer) clears the canvas and the other layers are redrawn on top } else { // User cannot delete the only layer JOptionPane.showMessageDialog(null, "Sorry, but you cannot delete your only layer."); paintLab.repaint(); } } public ArrayList<BufferedImage> getImageArray() { // Returns the private imageArray return imageArray; } public int getcLayerNum() { // Returns the private cLayerNum attribute, the current index of imageArray, so that other classes can properly access cLayerNum return cLayerNum; } public void setcLayerNum(int cNum) { // Sets the cLayerNum to the new current layer's index cLayerNum = cNum; } }
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 | /***************************************************************************** * Lab13: The Paint Program: Menu class * Name: Samantha Yu * Submitted to AP Computer Science 12: January 27, 2015 * Last modified: April 4, 2015 * Teacher: Christopher Slowley ******************************************************************************/ import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.image.BufferedImage; import javax.swing.JColorChooser; import javax.swing.JOptionPane; import javax.swing.colorchooser.AbstractColorChooserPanel; public class Menu { // Menu buttons are not physically seen, but are the "click-able" items Rectangle menuRect, colorRect, sizeRect; Rectangle pencilRect, brushRect, sprayRect; Rectangle newRect, prevRect, nextRect, delRect; // Menu appearance Color menuColor, paintColor, toolColor, sizeColor, fontColor, layerBtnColor, selectColor; Font btnFont; private int numTool, strokeSize; String stringStroke; // Used when getting the color from dialog boxes BufferedImage menuImage; // To prevent the menu bar being erased when the window is no longer active, menuImage will store the current image Graphics2D g2Menu; // g2Menu will paint graphics onto that image when necessary PaintApp paintLab; // A PaintApp object has only one instance and allows this class to access its non-static methods and attributes // I did not make PaintApp's attributes static, because those attributes refer to the one and same object, the paint program // I did not want to place the Menu's methods into PaintApp, because those methods belong in its own separate category // So, this Menu class must be able to access the dimensions of PaintApp such as the get methods like getAppWidth() Layers layersArray; public Menu(PaintApp pLab, Layers lArray) { // When the menu object is constructed, the invisible but "click-able" buttons are also constructed paintLab = pLab; // Initializes paintLab to the actual PaintApp, and layersArray to the actual layers array layersArray = lArray; // So that Menu class' methods can access the non-static fields and methods, such as imageArray selectColor = new Color( 0 , 0 , 0 ); fontColor = new Color( 0 , 0 , 0 ); btnFont = new Font( "Georgia" ,Font.BOLD, 17 ); numTool = 1 ; strokeSize = 15 ; colorRect = new Rectangle( 13 , 35 , 35 , 35 ); // Color button (invisible but "click-able") pencilRect = new Rectangle( 53 , 35 , 80 , 35 ); // Tool buttons (invisible but "click-able") brushRect = new Rectangle( 138 , 35 , 80 , 35 ); sprayRect = new Rectangle( 223 , 35 , 80 , 35 ); sizeRect = new Rectangle( 308 , 35 , 60 , 35 ); // Size buttons (invisible but "click-able") newRect = new Rectangle( 373 , 35 , 70 , 35 ); // Layer buttons (invisible but "click-able") prevRect = new Rectangle( 448 , 35 , 70 , 35 ); nextRect = new Rectangle( 523 , 35 , 70 , 35 ); delRect = new Rectangle( 598 , 35 , 70 , 35 ); menuRect = new Rectangle( 8 , 30 ,paintLab.getAppWidth(), paintLab.getMenuHeight()); } public void createMenu() { // Creates the physical appearance of the menu menuImage = new BufferedImage(paintLab.getAppWidth(),paintLab.getMenuHeight(),BufferedImage.TYPE_INT_ARGB); g2Menu = (Graphics2D) menuImage.getGraphics(); makeBackgroundMenu(); makeColorButton(); makeSizeButton(); makeToolButtons(); makeLayerButtons(); } private void makeBackgroundMenu() { // Makes background menu menuColor = new Color( 71 , 119 , 166 ); g2Menu.setColor(menuColor); g2Menu.fillRect( 0 , 0 ,paintLab.getAppWidth(), paintLab.getMenuHeight()); } private void makeColorButton() { // Makes visible color buttons paintColor = new Color( 121 , 219 , 209 ); g2Menu.setColor(paintColor); g2Menu.fillRect( 13 , 35 , 35 , 35 ); g2Menu.setStroke( new BasicStroke( 2 , BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND)); g2Menu.setColor(selectColor); g2Menu.drawRect( 13 , 35 , 35 , 35 ); // Draws border } private void makeToolButtons() { // Makes visible tool buttons toolColor = new Color( 240 , 236 , 189 ); g2Menu.setColor(toolColor); g2Menu.fillRoundRect( 53 , 35 , 80 , 35 , 20 , 20 ); // 1st Tool Button: Pencil g2Menu.fillRoundRect( 138 , 35 , 80 , 35 , 20 , 20 ); // 2nd Tool Button: Elastic g2Menu.fillRoundRect( 223 , 35 , 80 , 35 , 20 , 20 ); // 3rd Tool Button: Paint Bucket g2Menu.setColor(fontColor); g2Menu.setFont(btnFont); g2Menu.drawString( "PENCIL" , 58 , 58 ); // Tool button labels g2Menu.drawString( "BRUSH" , 146 , 58 ); g2Menu.drawString( "SPRAY" , 231 , 58 ); g2Menu.setStroke( new BasicStroke( 2 , BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND)); g2Menu.setColor(selectColor); g2Menu.drawRoundRect( 53 , 35 , 80 , 35 , 20 , 20 ); // Draws border around first selected tool which is the pencil tool g2Menu.setColor(menuColor); g2Menu.drawRoundRect( 138 , 35 , 80 , 35 , 20 , 20 ); // Draws "invisible" border (same color as the menu) on the other two tools g2Menu.drawRoundRect( 223 , 35 , 80 , 35 , 20 , 20 ); } private void makeSizeButton() { // Makes visible size buttons sizeColor = new Color( 253 , 191 , 125 ); g2Menu.setColor(sizeColor); g2Menu.fillRoundRect( 308 , 35 , 60 , 35 , 20 , 20 ); g2Menu.setStroke( new BasicStroke( 2 , BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND)); g2Menu.setColor(selectColor); g2Menu.drawRoundRect( 308 , 35 , 60 , 35 , 20 , 20 ); // Draws border g2Menu.setColor(fontColor); g2Menu.setFont(btnFont); g2Menu.drawString(strokeSize + " px" , 314 , 56 ); } private void makeLayerButtons() { // Makes visible layer buttons layerBtnColor = new Color( 119 , 237 , 156 ); g2Menu.setColor(layerBtnColor); g2Menu.fillRoundRect( 373 , 35 , 70 , 35 , 20 , 20 ); // Layer Button: New Layer g2Menu.fillRoundRect( 448 , 35 , 70 , 35 , 20 , 20 ); // Layer Button: Previous Layer g2Menu.fillRoundRect( 523 , 35 , 70 , 35 , 20 , 20 ); // Layer Button: Next Layer g2Menu.fillRoundRect( 598 , 35 , 70 , 35 , 20 , 20 ); // Layer Button: Delete Layer g2Menu.fillRoundRect( 673 , 35 , 75 , 35 , 20 , 20 ); // Layer Button: Number of current layer g2Menu.setColor(fontColor); g2Menu.setFont(btnFont); g2Menu.drawString( "NEW" , 383 , 58 ); // Layer button labels g2Menu.drawString( "PREV." , 457 , 58 ); g2Menu.drawString( "NEXT" , 533 , 58 ); g2Menu.drawString( "DEL." , 613 , 58 ); g2Menu.setFont( new Font( "Georgia" ,Font.PLAIN, 19 )); g2Menu.drawString( "1 of 1" , 683 , 56 ); // Initial layer status (when the paint program begins) } public void select( int x, int y) { // Selects menu items if (colorRect.contains(x, y)) { // If mouse clicks on the color button selectColor(); } if (pencilRect.contains(x, y)) { // If mouse selects a tool numTool = 1 ; } else if (brushRect.contains(x, y)) { numTool = 2 ; } else if (sprayRect.contains(x, y)) { numTool = 3 ; } if (sizeRect.contains(x, y)) { // If mouse clicks on the size button selectSize(); } if (newRect.contains(x, y)) { // If mouse clicks on a layer button layersArray.newLayer(); } else if (prevRect.contains(x, y)) { layersArray.previousLayer(); } else if (nextRect.contains(x, y)) { layersArray.nextLayer(); } else if (delRect.contains(x, y)) { layersArray.deleteLayer(); } } private void selectColor() { // When the user selects on the color button JColorChooser chooser = new JColorChooser(); // Color panel AbstractColorChooserPanel[] panels = chooser.getChooserPanels(); for (AbstractColorChooserPanel accp : panels) { // Only the RGB tab will show if (accp.getDisplayName().equals( "RGB" )) { JOptionPane.showMessageDialog( null , accp); } } paintLab.repaint(); // Repaints the window in case some of the graphics disappeared due to the color chooser popping up Color pColor = chooser.getColor(); // Since transparent lines are compounded on top of each other when draw in succession causing the transparent lines to appear opaque // I converted the RGBA values into RGB. // Now, the color of the menu's color button matches the color drawn on the canvas int r, g, b; r = pColor.getRed() * pColor.getAlpha() + pColor.getRed() * ( 255 - pColor.getAlpha()); g = pColor.getGreen() * pColor.getAlpha() + pColor.getGreen() * ( 255 - pColor.getAlpha()); b = pColor.getBlue() * pColor.getAlpha() + pColor.getBlue() * ( 255 - pColor.getAlpha()); paintColor = new Color(r / 255 , g / 255 , b / 255 ); changeColorMenu(); } private void selectSize() { // When the user selects on the size button do { stringStroke = JOptionPane.showInputDialog( "How many pixels wide should your paint tools be?" ); if (stringStroke == null ) { // If the user exits the dialog box JOptionPane.showMessageDialog( null , "Since you did not provide a value for the width of the paint tool, the width is set to 15 px." ); strokeSize = 15 ; } else { strokeSize = Integer.parseInt(stringStroke); if (strokeSize < 0 ) // If the user enters a negative value JOptionPane.showMessageDialog( null , "You cannot have a tool with a width less than 0. Please try again with a higher value." ); else if (strokeSize > paintLab.getCanvasHeight()) // If the user enters an extremely large value JOptionPane.showMessageDialog( null , "Using a tool with a width greater than the canvas height (" + paintLab.getCanvasHeight() + " px) is unnecesarily large. Please try again with a lower value." ); } } while ((strokeSize < 0 ) || (strokeSize > paintLab.getCanvasHeight())); // Loop will continue until the user provides a positive number smaller than the canvas height changeSizeMenu(); } private void changeColorMenu() { // Changes the appearance of the color button after it is clicked g2Menu.setColor(Color.white); // Erases previous button g2Menu.fillRect( 13 , 35 , 35 , 35 ); g2Menu.setColor(paintColor); // Paints button with new color g2Menu.fillRect( 13 , 35 , 35 , 35 ); g2Menu.setStroke( new BasicStroke( 2 , BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND)); g2Menu.setColor(selectColor); // Redraws border g2Menu.drawRect( 13 , 35 , 35 , 35 ); } public void changeToolMenu() { // Changes the appearance of the tool button after it is clicked g2Menu.setStroke( new BasicStroke( 2 , BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND)); g2Menu.setColor(selectColor); if (numTool == 1 ) // Draws border around selected tool box g2Menu.drawRoundRect( 53 , 35 , 80 , 35 , 20 , 20 ); else if (numTool == 2 ) g2Menu.drawRoundRect( 138 , 35 , 80 , 35 , 20 , 20 ); else if (numTool == 3 ) g2Menu.drawRoundRect( 223 , 35 , 80 , 35 , 20 , 20 ); g2Menu.setColor(menuColor); // "If" statements instead of "else if", because multiple boxes are not selected at a time if (numTool != 1 ) // Erases border around previously selected tool box by drawing that same rectangle with the menu color g2Menu.drawRoundRect( 53 , 35 , 80 , 35 , 20 , 20 ); if (numTool != 2 ) g2Menu.drawRoundRect( 138 , 35 , 80 , 35 , 20 , 20 ); if (numTool != 3 ) g2Menu.drawRoundRect( 223 , 35 , 80 , 35 , 20 , 20 ); } private void changeSizeMenu() { // Changes the appearance of the size button after it is clicked g2Menu.setColor(sizeColor); g2Menu.fillRoundRect( 308 , 35 , 60 , 35 , 20 , 20 ); // Erases previous size by drawing button again g2Menu.setStroke( new BasicStroke( 2 , BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND)); g2Menu.setColor(selectColor); g2Menu.drawRoundRect( 308 , 35 , 60 , 35 , 20 , 20 ); // Draws border g2Menu.setFont(btnFont); g2Menu.setColor(fontColor); // Depending on the number of digits of the size status, the status is printed with a certain size and location if (strokeSize <= 99 ) { g2Menu.drawString(strokeSize + " px" , 314 , 56 ); } else { g2Menu.setFont( new Font( "Georgia" ,Font.BOLD, 14 )); g2Menu.drawString(strokeSize + " px" , 312 , 56 ); } } public void changeLayerMenu() { // Changes the appearance of the layers' status after the user has created or deleted a layer, or moved to a different layer g2Menu.setColor(layerBtnColor); g2Menu.fillRoundRect( 673 , 35 , 75 , 35 , 20 , 20 ); // Redraw the layer status rectangle to cover the previous status g2Menu.setColor(fontColor); // Depending on the number of digits in the layer status, the status is printed with a certain size and location if ((layersArray.getcLayerNum() < 9 ) && (layersArray.getImageArray().size() < 10 )) { g2Menu.setFont( new Font( "Georgia" ,Font.PLAIN, 19 )); g2Menu.drawString(String.valueOf(layersArray.getcLayerNum() + 1 ) + " of " + String.valueOf(layersArray.getImageArray().size()), 683 , 56 ); } else { g2Menu.setFont( new Font( "Georgia" ,Font.PLAIN, 17 )); g2Menu.drawString(String.valueOf(layersArray.getcLayerNum() + 1 ) + " of " + String.valueOf(layersArray.getImageArray().size()), 683 , 56 ); } } public int getNumTool() { // Returns private numTool attribute return numTool; } public int getStrokeSize() { // Returns private numStrokeSize attribute return strokeSize; } } |
/***************************************************************************** * Lab13: The Paint Program: Menu class * Name: Samantha Yu * Submitted to AP Computer Science 12: January 27, 2015 * Last modified: April 4, 2015 * Teacher: Christopher Slowley ******************************************************************************/ import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.image.BufferedImage; import javax.swing.JColorChooser; import javax.swing.JOptionPane; import javax.swing.colorchooser.AbstractColorChooserPanel; public class Menu { // Menu buttons are not physically seen, but are the "click-able" items Rectangle menuRect, colorRect, sizeRect; Rectangle pencilRect, brushRect, sprayRect; Rectangle newRect, prevRect, nextRect, delRect; // Menu appearance Color menuColor, paintColor, toolColor, sizeColor, fontColor, layerBtnColor, selectColor; Font btnFont; private int numTool, strokeSize; String stringStroke; // Used when getting the color from dialog boxes BufferedImage menuImage; // To prevent the menu bar being erased when the window is no longer active, menuImage will store the current image Graphics2D g2Menu; // g2Menu will paint graphics onto that image when necessary PaintApp paintLab; // A PaintApp object has only one instance and allows this class to access its non-static methods and attributes // I did not make PaintApp's attributes static, because those attributes refer to the one and same object, the paint program // I did not want to place the Menu's methods into PaintApp, because those methods belong in its own separate category // So, this Menu class must be able to access the dimensions of PaintApp such as the get methods like getAppWidth() Layers layersArray; public Menu(PaintApp pLab, Layers lArray) { // When the menu object is constructed, the invisible but "click-able" buttons are also constructed paintLab = pLab; // Initializes paintLab to the actual PaintApp, and layersArray to the actual layers array layersArray = lArray; // So that Menu class' methods can access the non-static fields and methods, such as imageArray selectColor = new Color(0,0,0); fontColor = new Color(0,0,0); btnFont = new Font("Georgia",Font.BOLD,17); numTool = 1; strokeSize = 15; colorRect = new Rectangle(13, 35, 35, 35); // Color button (invisible but "click-able") pencilRect = new Rectangle(53, 35, 80, 35); // Tool buttons (invisible but "click-able") brushRect = new Rectangle(138, 35, 80, 35); sprayRect = new Rectangle(223, 35, 80, 35); sizeRect = new Rectangle(308, 35, 60, 35); // Size buttons (invisible but "click-able") newRect = new Rectangle(373, 35, 70, 35); // Layer buttons (invisible but "click-able") prevRect = new Rectangle(448, 35, 70, 35); nextRect = new Rectangle(523, 35, 70, 35); delRect = new Rectangle(598, 35, 70, 35); menuRect = new Rectangle(8,30,paintLab.getAppWidth(), paintLab.getMenuHeight()); } public void createMenu() { // Creates the physical appearance of the menu menuImage = new BufferedImage(paintLab.getAppWidth(),paintLab.getMenuHeight(),BufferedImage.TYPE_INT_ARGB); g2Menu = (Graphics2D) menuImage.getGraphics(); makeBackgroundMenu(); makeColorButton(); makeSizeButton(); makeToolButtons(); makeLayerButtons(); } private void makeBackgroundMenu() { // Makes background menu menuColor = new Color(71,119,166); g2Menu.setColor(menuColor); g2Menu.fillRect(0,0,paintLab.getAppWidth(), paintLab.getMenuHeight()); } private void makeColorButton() { // Makes visible color buttons paintColor = new Color(121,219,209); g2Menu.setColor(paintColor); g2Menu.fillRect(13, 35, 35, 35); g2Menu.setStroke(new BasicStroke(2, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND)); g2Menu.setColor(selectColor); g2Menu.drawRect(13, 35, 35, 35); // Draws border } private void makeToolButtons() { // Makes visible tool buttons toolColor = new Color(240,236,189); g2Menu.setColor(toolColor); g2Menu.fillRoundRect(53, 35, 80, 35, 20, 20); // 1st Tool Button: Pencil g2Menu.fillRoundRect(138, 35, 80, 35, 20, 20); // 2nd Tool Button: Elastic g2Menu.fillRoundRect(223, 35, 80, 35, 20, 20); // 3rd Tool Button: Paint Bucket g2Menu.setColor(fontColor); g2Menu.setFont(btnFont); g2Menu.drawString("PENCIL", 58, 58); // Tool button labels g2Menu.drawString("BRUSH", 146, 58); g2Menu.drawString("SPRAY", 231, 58); g2Menu.setStroke(new BasicStroke(2, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND)); g2Menu.setColor(selectColor); g2Menu.drawRoundRect(53, 35, 80, 35, 20, 20); // Draws border around first selected tool which is the pencil tool g2Menu.setColor(menuColor); g2Menu.drawRoundRect(138, 35, 80, 35, 20, 20); // Draws "invisible" border (same color as the menu) on the other two tools g2Menu.drawRoundRect(223, 35, 80, 35, 20, 20); } private void makeSizeButton() { // Makes visible size buttons sizeColor = new Color(253, 191, 125); g2Menu.setColor(sizeColor); g2Menu.fillRoundRect(308, 35, 60, 35, 20, 20); g2Menu.setStroke(new BasicStroke(2, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND)); g2Menu.setColor(selectColor); g2Menu.drawRoundRect(308, 35, 60, 35, 20, 20); // Draws border g2Menu.setColor(fontColor); g2Menu.setFont(btnFont); g2Menu.drawString(strokeSize + " px", 314, 56); } private void makeLayerButtons() { // Makes visible layer buttons layerBtnColor = new Color(119,237,156); g2Menu.setColor(layerBtnColor); g2Menu.fillRoundRect(373, 35, 70, 35, 20, 20); // Layer Button: New Layer g2Menu.fillRoundRect(448, 35, 70, 35, 20, 20); // Layer Button: Previous Layer g2Menu.fillRoundRect(523, 35, 70, 35, 20, 20); // Layer Button: Next Layer g2Menu.fillRoundRect(598, 35, 70, 35, 20, 20); // Layer Button: Delete Layer g2Menu.fillRoundRect(673, 35, 75, 35, 20, 20); // Layer Button: Number of current layer g2Menu.setColor(fontColor); g2Menu.setFont(btnFont); g2Menu.drawString("NEW", 383, 58); // Layer button labels g2Menu.drawString("PREV.", 457, 58); g2Menu.drawString("NEXT", 533, 58); g2Menu.drawString("DEL.", 613, 58); g2Menu.setFont(new Font("Georgia",Font.PLAIN,19)); g2Menu.drawString("1 of 1", 683, 56); // Initial layer status (when the paint program begins) } public void select(int x, int y) { // Selects menu items if (colorRect.contains(x, y)) { // If mouse clicks on the color button selectColor(); } if (pencilRect.contains(x, y)) { // If mouse selects a tool numTool = 1; } else if (brushRect.contains(x, y)) { numTool = 2; } else if (sprayRect.contains(x, y)) { numTool = 3; } if (sizeRect.contains(x, y)) { // If mouse clicks on the size button selectSize(); } if (newRect.contains(x, y)) { // If mouse clicks on a layer button layersArray.newLayer(); } else if (prevRect.contains(x, y)) { layersArray.previousLayer(); } else if (nextRect.contains(x, y)) { layersArray.nextLayer(); } else if (delRect.contains(x, y)) { layersArray.deleteLayer(); } } private void selectColor() { // When the user selects on the color button JColorChooser chooser = new JColorChooser(); // Color panel AbstractColorChooserPanel[] panels = chooser.getChooserPanels(); for (AbstractColorChooserPanel accp : panels) { // Only the RGB tab will show if (accp.getDisplayName().equals("RGB")) { JOptionPane.showMessageDialog(null, accp); } } paintLab.repaint(); // Repaints the window in case some of the graphics disappeared due to the color chooser popping up Color pColor = chooser.getColor(); // Since transparent lines are compounded on top of each other when draw in succession causing the transparent lines to appear opaque // I converted the RGBA values into RGB. // Now, the color of the menu's color button matches the color drawn on the canvas int r, g, b; r = pColor.getRed() * pColor.getAlpha() + pColor.getRed() * (255 - pColor.getAlpha()); g = pColor.getGreen() * pColor.getAlpha() + pColor.getGreen() * (255 - pColor.getAlpha()); b = pColor.getBlue() * pColor.getAlpha() + pColor.getBlue() * (255 - pColor.getAlpha()); paintColor = new Color(r / 255, g / 255, b / 255); changeColorMenu(); } private void selectSize() { // When the user selects on the size button do { stringStroke = JOptionPane.showInputDialog("How many pixels wide should your paint tools be?"); if (stringStroke == null) { // If the user exits the dialog box JOptionPane.showMessageDialog(null,"Since you did not provide a value for the width of the paint tool, the width is set to 15 px."); strokeSize = 15; } else { strokeSize = Integer.parseInt(stringStroke); if (strokeSize < 0) // If the user enters a negative value JOptionPane.showMessageDialog(null,"You cannot have a tool with a width less than 0. Please try again with a higher value."); else if (strokeSize > paintLab.getCanvasHeight()) // If the user enters an extremely large value JOptionPane.showMessageDialog(null,"Using a tool with a width greater than the canvas height (" + paintLab.getCanvasHeight() + " px) is unnecesarily large. Please try again with a lower value."); } } while ((strokeSize < 0) || (strokeSize > paintLab.getCanvasHeight())); // Loop will continue until the user provides a positive number smaller than the canvas height changeSizeMenu(); } private void changeColorMenu() { // Changes the appearance of the color button after it is clicked g2Menu.setColor(Color.white); // Erases previous button g2Menu.fillRect(13, 35, 35, 35); g2Menu.setColor(paintColor); // Paints button with new color g2Menu.fillRect(13, 35, 35, 35); g2Menu.setStroke(new BasicStroke(2, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND)); g2Menu.setColor(selectColor); // Redraws border g2Menu.drawRect(13, 35, 35, 35); } public void changeToolMenu() { // Changes the appearance of the tool button after it is clicked g2Menu.setStroke(new BasicStroke(2, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND)); g2Menu.setColor(selectColor); if (numTool == 1) // Draws border around selected tool box g2Menu.drawRoundRect(53, 35, 80, 35, 20, 20); else if (numTool == 2) g2Menu.drawRoundRect(138, 35, 80, 35, 20, 20); else if (numTool == 3) g2Menu.drawRoundRect(223, 35, 80, 35, 20, 20); g2Menu.setColor(menuColor); // "If" statements instead of "else if", because multiple boxes are not selected at a time if (numTool != 1) // Erases border around previously selected tool box by drawing that same rectangle with the menu color g2Menu.drawRoundRect(53, 35, 80, 35, 20, 20); if (numTool != 2) g2Menu.drawRoundRect(138, 35, 80, 35, 20, 20); if (numTool != 3) g2Menu.drawRoundRect(223, 35, 80, 35, 20, 20); } private void changeSizeMenu() { // Changes the appearance of the size button after it is clicked g2Menu.setColor(sizeColor); g2Menu.fillRoundRect(308, 35, 60, 35, 20, 20); // Erases previous size by drawing button again g2Menu.setStroke(new BasicStroke(2, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND)); g2Menu.setColor(selectColor); g2Menu.drawRoundRect(308, 35, 60, 35, 20, 20); // Draws border g2Menu.setFont(btnFont); g2Menu.setColor(fontColor); // Depending on the number of digits of the size status, the status is printed with a certain size and location if (strokeSize <= 99) { g2Menu.drawString(strokeSize + " px", 314, 56); } else { g2Menu.setFont(new Font("Georgia",Font.BOLD,14)); g2Menu.drawString(strokeSize + " px", 312, 56); } } public void changeLayerMenu() { // Changes the appearance of the layers' status after the user has created or deleted a layer, or moved to a different layer g2Menu.setColor(layerBtnColor); g2Menu.fillRoundRect(673, 35, 75, 35, 20, 20); // Redraw the layer status rectangle to cover the previous status g2Menu.setColor(fontColor); // Depending on the number of digits in the layer status, the status is printed with a certain size and location if ((layersArray.getcLayerNum() < 9) && (layersArray.getImageArray().size() < 10)) { g2Menu.setFont(new Font("Georgia",Font.PLAIN,19)); g2Menu.drawString(String.valueOf(layersArray.getcLayerNum() + 1) + " of " + String.valueOf(layersArray.getImageArray().size()), 683, 56); } else { g2Menu.setFont(new Font("Georgia",Font.PLAIN,17)); g2Menu.drawString(String.valueOf(layersArray.getcLayerNum() + 1) + " of " + String.valueOf(layersArray.getImageArray().size()), 683, 56); } } public int getNumTool() { // Returns private numTool attribute return numTool; } public int getStrokeSize() { // Returns private numStrokeSize attribute return strokeSize; } }
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | /***************************************************************************** * Lab13: The Paint Program: Tools class * Name: Samantha Yu * Submitted to AP Computer Science 12: January 27, 2015 * Last modified: April 4, 2015 * Teacher: Christopher Slowley ******************************************************************************/ import java.awt.BasicStroke; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.util.Random; public class Tools { BufferedImage cvMem; // "Current virtual memory"; off-screen image that the current layer which is painted upon Graphics2D cgBuffer; // "Current graphics' buffer"; a graphics context for drawing an off-screen image; all cgBuffer information is sent to cvMem // The Graphics2D class provides "more sophisticated control over geometry, coordinate transformations, color management, and text layout" // (see "http://docs.oracle.com/javase/7/docs/api/java/awt/Graphics2D.html") than its superclass, the Graphics class, // Such as being able to paint lines that have different edges PaintApp paintLab; // A PaintApp object has only one instance and allows this class to access its non-static methods and attributes // I did not make PaintApp's attributes static, because those attributes refer to the one and same object, the paint program // I did not want to place the Tools' methods into PaintApp, because those methods belong in its own separate category // So, this Tools class must be able to access the dimensions of PaintApp such as the get methods like getAppWidth() Menu menuBar; Layers layersArray; private int randX, randY; public Tools(PaintApp pLab, Menu menuB, Layers lArray) { // A Tools object is constructed menuBar = menuB; // Initializes menuBar to the actual menu, paintLab to the actual PaintApp, and layersArray to the actual layers array paintLab = pLab; // So that Tools class' methods can access the non-static fields and methods, such as imageArray layersArray = lArray; } private void pencil( int oldX, int oldY, int newX, int newY) { // Pencil tool with a rounded stroke cgBuffer.setStroke( new BasicStroke(menuBar.getStrokeSize(), BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); cgBuffer.drawLine(oldX,oldY,newX,newY); } private void brush( int oldX, int oldY, int newX, int newY) { // Brush tool (has "missing" lines in its stroke at a curve) cgBuffer.setStroke( new BasicStroke(menuBar.getStrokeSize(), BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)); cgBuffer.drawLine(oldX,oldY,newX,newY); } private void spray( int newX, int newY) { // Spray can tool Random rand = new Random(); for ( int k= 1 ; k< 2 *menuBar.getStrokeSize(); k++) { // Several tiny random circles are painted around the current coordinate randX = rand.nextInt(menuBar.getStrokeSize()) + newX - ( int ) menuBar.getStrokeSize()/ 2 ; randY = rand.nextInt(menuBar.getStrokeSize()) + newY - ( int ) menuBar.getStrokeSize()/ 2 ; cgBuffer.fillOval(randX, randY, ( int ) 3 , ( int ) 3 ); } } public void useTool( int numTool, int oldX, int oldY, int newX, int newY) { // Selects specific tool cvMem = layersArray.getImageArray().get(layersArray.getcLayerNum()); // Grabs the current layer cgBuffer = (Graphics2D) cvMem.getGraphics(); // Creates the graphics context for that layer to be used in double buffering cgBuffer.setColor(menuBar.paintColor); // The y-coordinates are subtracted by the menu bar's height, because the canvas layers do not include the menu bar if (numTool == 1 ) pencil(oldX, oldY - paintLab.getMenuHeight(), newX, newY - paintLab.getMenuHeight()); else if (numTool == 2 ) brush(oldX, oldY - paintLab.getMenuHeight(), newX, newY - paintLab.getMenuHeight()); else if (numTool == 3 ) spray(newX, newY - paintLab.getMenuHeight()); } } |
/***************************************************************************** * Lab13: The Paint Program: Tools class * Name: Samantha Yu * Submitted to AP Computer Science 12: January 27, 2015 * Last modified: April 4, 2015 * Teacher: Christopher Slowley ******************************************************************************/ import java.awt.BasicStroke; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.util.Random; public class Tools { BufferedImage cvMem; // "Current virtual memory"; off-screen image that the current layer which is painted upon Graphics2D cgBuffer; // "Current graphics' buffer"; a graphics context for drawing an off-screen image; all cgBuffer information is sent to cvMem // The Graphics2D class provides "more sophisticated control over geometry, coordinate transformations, color management, and text layout" // (see "http://docs.oracle.com/javase/7/docs/api/java/awt/Graphics2D.html") than its superclass, the Graphics class, // Such as being able to paint lines that have different edges PaintApp paintLab; // A PaintApp object has only one instance and allows this class to access its non-static methods and attributes // I did not make PaintApp's attributes static, because those attributes refer to the one and same object, the paint program // I did not want to place the Tools' methods into PaintApp, because those methods belong in its own separate category // So, this Tools class must be able to access the dimensions of PaintApp such as the get methods like getAppWidth() Menu menuBar; Layers layersArray; private int randX, randY; public Tools(PaintApp pLab, Menu menuB, Layers lArray) { // A Tools object is constructed menuBar = menuB; // Initializes menuBar to the actual menu, paintLab to the actual PaintApp, and layersArray to the actual layers array paintLab = pLab; // So that Tools class' methods can access the non-static fields and methods, such as imageArray layersArray = lArray; } private void pencil(int oldX, int oldY, int newX, int newY) { // Pencil tool with a rounded stroke cgBuffer.setStroke(new BasicStroke(menuBar.getStrokeSize(), BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); cgBuffer.drawLine(oldX,oldY,newX,newY); } private void brush(int oldX, int oldY, int newX, int newY) { // Brush tool (has "missing" lines in its stroke at a curve) cgBuffer.setStroke(new BasicStroke(menuBar.getStrokeSize(), BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)); cgBuffer.drawLine(oldX,oldY,newX,newY); } private void spray(int newX, int newY) { // Spray can tool Random rand = new Random(); for (int k=1; k<2*menuBar.getStrokeSize(); k++) { // Several tiny random circles are painted around the current coordinate randX = rand.nextInt(menuBar.getStrokeSize()) + newX - (int) menuBar.getStrokeSize()/2; randY = rand.nextInt(menuBar.getStrokeSize()) + newY - (int) menuBar.getStrokeSize()/2; cgBuffer.fillOval(randX, randY, (int) 3, (int) 3); } } public void useTool(int numTool, int oldX, int oldY, int newX, int newY) { // Selects specific tool cvMem = layersArray.getImageArray().get(layersArray.getcLayerNum()); // Grabs the current layer cgBuffer = (Graphics2D) cvMem.getGraphics(); // Creates the graphics context for that layer to be used in double buffering cgBuffer.setColor(menuBar.paintColor); // The y-coordinates are subtracted by the menu bar's height, because the canvas layers do not include the menu bar if (numTool == 1) pencil(oldX, oldY - paintLab.getMenuHeight(), newX, newY - paintLab.getMenuHeight()); else if (numTool == 2) brush(oldX, oldY - paintLab.getMenuHeight(), newX, newY - paintLab.getMenuHeight()); else if (numTool == 3) spray(newX, newY - paintLab.getMenuHeight()); } }