Results 1 to 13 of 13
  1. #1
    ngiannini is offline Member
    Join Date
    May 2010
    Posts
    6
    Rep Power
    0

    Default Paint Program Help

    So I'm having a couple of problems with my program and would really appreciate it if anyone could help.

    1. I'm interpolating a pencil like tool to draw on the canvas. However, when the mouse is released and clicked again it interpolates all the way over when it should be starting a new stroke. I've tried making a vector of vectors and clearing the vectors before starting a new stroke but have failed to fix the issue.

    2. I'd like the buttons in the toolbar frame to change the color of the next stroke I am about to draw, but I can't access canvas.Setcolor from the PaintProgram class.

    I am only a beginner in java so I apologize if I don't understand some of these concepts.

    Here is my code as of now.

    PaintProgram.java
    Java Code:
    import javax.swing.*;
    import java.awt.event.*;
    import java.awt.*;
    
    public class PaintProgram extends JFrame implements ActionListener {
    	
    	//Create background containing window
        JDesktopPane bgWindow = new JDesktopPane();
       
        //Create button array and list buttons to change pencil color
        JButton[] button;
    	static final String[] BUTTON_STR = {"Red", "Green", "Blue", "Black", "White"};
    	
    	
    	//Constructor for PaintProgram
        public PaintProgram() {
            super();
            
            //Change background color
            bgWindow.setBackground(Color.gray);
            
            //Find the dimensions of user's screen
            Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
            
            //set amount GUI will be indented
            int indent = 100;
            
            //Indent and position GUI
            setBounds(indent, indent, screenSize.width  - indent*2, screenSize.height - indent*2);
    
       
            //Set up the GUI.
            createToolBar(); //Creates a toolbar for the different tools
            createCanvas(); //Create a new canvas
            setContentPane(bgWindow); //Insert canvas in containing window
            setJMenuBar(createMenuBar()); //Create and setup menubar
        }
        
        //Create Toolbar
        public void createToolBar(){
        	JInternalFrame toolBar = new JInternalFrame();
        	toolBar.setSize(100,600);
            toolBar.setVisible(true);
            toolBar.setLocation(0,0);
            bgWindow.add(toolBar);
            
            //Layout buttons
            JPanel controlPanel = new JPanel(new GridLayout(5,1));
            button = new JButton[BUTTON_STR.length];
    		for (int i=0; i<BUTTON_STR.length; i++) {
    			button[i] = new JButton(BUTTON_STR[i]);
    			button[i].addActionListener(this);
    			controlPanel.add(button[i]);
    		}
    		toolBar.add(controlPanel);
        }
        
        //Create Menubar
        public JMenuBar createMenuBar() {
        	
            JMenuBar menuBar = new JMenuBar();
            JMenu menu = new JMenu("File");
            menuBar.add(menu);
    
            //New Document Item
            JMenuItem menuItem = new JMenuItem("New Canvas");
            menuItem.setActionCommand("new");
            menuItem.addActionListener(this);
            menu.add(menuItem);
    
            //Exit Item
            menuItem = new JMenuItem("Exit");
            menuItem.setActionCommand("exit");
            menuItem.addActionListener(this);
            menu.add(menuItem);
    
            return menuBar;
        }
    
        //Menu item methods
        public void actionPerformed(ActionEvent e) {
            if ("new".equals(e.getActionCommand())) {
                createCanvas();
            } 
            else if ("exit".equals(e.getActionCommand())) {
                exit();
            }
            
            Object obj = e.getSource();
            boolean noButtonHit = true;
    		for (int i=0; i<button.length; i++) {
    			if (obj == button[i]) {
    				System.out.println(BUTTON_STR[i] + " was hit");
    				noButtonHit = false;
    				if(i==0){
    					red();
    				}
    				else if(i==1){
    					green();
    				}
    				else if (i==2){
    					blue();
    				}
    				else if(i==3){
    					black();
    				}
    				else if(i==4){
    					white();
    				}
    			}
    		}
        }
        
        private void black() {
    		
    	}
    
    	private void white() {
    		
    	}
    
    	private void blue() {
    		
    	}
    
    	private void green() {
    		
    	}
    
    	private void red() {
    
    	}
    
    	//Create a new canvas
        public void createCanvas() {
            PaintCanvas frame = new PaintCanvas();
            frame.setVisible(true);
            bgWindow.add(frame);
            try {
                frame.setSelected(true);
            } 
            catch (java.beans.PropertyVetoException e) {}
        }
    
        //Quit the application.
        public void exit() {
            System.exit(0);
        }
    
        private static void createAndShowGUI() {
            //Give application Java GUI style
            JFrame.setDefaultLookAndFeelDecorated(true);
    
            //Create and set up the window.
            PaintProgram frame = new PaintProgram();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            //Display the window.
            frame.setVisible(true);
        }
    
        //Displays GUI
        public static void main(String[] args) {
            javax.swing.SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    createAndShowGUI();
                }
            });
        }
    }
    PaintCanvas.java
    Java Code:
    import javax.swing.JInternalFrame;
    
    import java.awt.event.*;
    import java.awt.*;
    import java.util.Vector;
    
    //Creates a new Canvas to paint on
    public class PaintCanvas extends JInternalFrame implements MouseMotionListener, MouseListener {
    	
    	//Keep track of number of canvases open
        static int canvasCount = 0;
        //Create vector to keep track of mouse positions
        private Vector positions;
        private Vector strokes;
    
        //PaintCanvas Constructor
        public PaintCanvas() {
        	
        	//Set canvas attributes
            super("Canvas #" + (++canvasCount), true, true, true, true);
            setSize(700,600);
            setBackground(Color.white);
            setLocation(100, 0);
            
            addMouseMotionListener(this);
            strokes = new Vector();
            positions = new Vector();
        }
        
        //Paint Method
        public void paint(Graphics canvas) {
        	super.paint(canvas);
        	canvas.setColor(Color.black);
       	 	for (int i = 1; i < positions.size(); i++){
       	 		Point point1 = (Point) (positions.elementAt(i - 1));
       	 		Point point2 = (Point) (positions.elementAt(i));
       	 		canvas.drawLine(point1.x, point1.y, point2.x, point2.y);
       	 	}
        }
    
    	//Control interpolation
    	public void mouseDragged(MouseEvent myCoord) {
    		positions.addElement(new Point(myCoord.getX(), myCoord.getY()));
    		repaint();
        }
    
    	@Override
    	public void mouseMoved(MouseEvent arg0) {
    		
    	}
    
    	@Override
    	public void mouseClicked(MouseEvent e) {
    		
    	}
    
    	@Override
    	public void mouseEntered(MouseEvent e) {
    		
    	}
    
    	@Override
    	public void mouseExited(MouseEvent e) {
    		
    	}
    
    	@Override
    	public void mousePressed(MouseEvent e) {
    
    	}
    
    	@Override
    	public void mouseReleased(MouseEvent e) {
    		
    	}
    }

  2. #2
    camickr is offline Senior Member
    Join Date
    Jul 2009
    Posts
    1,236
    Rep Power
    7

    Default

    1) I would guess you need to create a new Vector() on mousePressed. Then mouseDragged() adds new points to the Vector. Then mouseReleased() adds the Vector to the main Vector, so you now have a "Vector of Vectors".

    2) For each line you draw you need to save the color of the line, which means you really need to create a custom class the has two pieces of information

    a) the color
    b) the Vector of Points.

    So really the Vector of Vectors becomes a Vector of "YourCustomClass".

    3) Custom painting is done by overriding the paintComponent() method , NOT the paint() method.

    Check out the Custom Painting Approaches for an example to get you started.

  3. #3
    ngiannini is offline Member
    Join Date
    May 2010
    Posts
    6
    Rep Power
    0

    Default

    I by no means intend to disregard your comments but after experimenting with ArrayLists and using your suggestions in regards to mouse motion I managed to get the tool to properly interpolate but only when I remove the line super.paint(canvas); from the paint method. The problem is that if I keep that line of code it draws a stroke and then erases it when i draw a new one. If I remove it, it removes the GUI for the frame but draws properly.

    Any suggestions for this would be appreciated and thanks again for your initial suggestions which I'm still exploring.

    The updated PaintCanvas.java

    Java Code:
    import javax.swing.JInternalFrame;
    import javax.swing.event.InternalFrameAdapter;
    
    import java.awt.event.*;
    import java.awt.*;
    import java.util.ArrayList;
    import java.util.Vector;
    
    //Creates a new Canvas to paint on
    public class PaintCanvas extends JInternalFrame implements MouseMotionListener, MouseListener {
    	
    	//Keep track of number of canvases open
        static int canvasCount = 0;
        //Create vector to keep track of mouse positions
        private ArrayList<Point> positions;
        private ArrayList<ArrayList> stroke = new ArrayList<ArrayList>();
        private Point point1;
        private Point point2;
        private Point point3;
    
        //PaintCanvas Constructor
        public PaintCanvas() {
        	
        	//Set canvas attributes
            super("Canvas #" + (++canvasCount), true, true, true, true);
            setSize(700,600);
            setBackground(Color.white);
            setLocation(100, 0);
            addMouseListener(this);
            addMouseMotionListener(this);
            positions = new ArrayList<Point>();
        }
        
        //Paint Method
        public void paint(Graphics canvas) {
        //	super.paint(canvas);
        	canvas.setColor(Color.black);
       	 	for (int i = 1; i < positions.size(); i++){
       	 			point1 =  (positions.get(i - 1));
       	 			point2 =  (positions.get(i));
       	 			canvas.drawLine(point1.x, point1.y, point2.x, point2.y);
       	 	}
        }
        
        public ArrayList<ArrayList> getStroke(){
        	return stroke;
        }
        
        public ArrayList<Point> getPositions(){
        	return positions;
        }
    
        public void setPositions(int x, int y){
        	positions.add(new Point(x, y));
        }
        
    	//Control interpolation
    	public void mouseDragged(MouseEvent myCoord) {
    		setPositions(myCoord.getX(), myCoord.getY());
    		stroke.add(getPositions());
    		repaint();
        }
    
    	@Override
    	public void mouseMoved(MouseEvent arg0) {
    		
    	}
    
    	@Override
    	public void mouseClicked(MouseEvent e) {
    		
    	}
    
    	@Override
    	public void mouseEntered(MouseEvent e) {
    		
    	}
    
    	@Override
    	public void mouseExited(MouseEvent e) {
    		
    	}
    
    	@Override
    	public void mousePressed(MouseEvent myCoord) {
    		positions = new ArrayList<Point>();
    	}
    
    	@Override
    	public void mouseReleased(MouseEvent myCoord) {
    		stroke.add(positions);
    	}
    }

  4. #4
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

    Default

    Quote Originally Posted by ngiannini View Post
    I by no means intend to disregard your comments but after experimenting with ArrayLists and using your suggestions in regards to mouse motion I managed to get the tool to properly interpolate but only when I remove the line super.paint(canvas); from the paint method.
    My experience has been that whenever I ignore camickr's suggestions, I continue to make foolish mistakes, though it's entirely your choice. Myself, I see no fault in what he says above, and I see lots of problems in your code including (sorry about being blunt) your current attempt to fix bad code with worse. Using ArrayLists instead of Vectors is fine, but again, paint in a JPanel's paintComponent method, and again, use super.paintComponent(g) to repaint the background of the JPanel.

    edit: For example, what happens to your current drawing if you minimize your JFrame and then restore it?

    Much luck.
    Last edited by Fubarable; 05-08-2010 at 07:59 PM.

  5. #5
    camickr is offline Senior Member
    Join Date
    Jul 2009
    Posts
    1,236
    Rep Power
    7

    Default

    The problem is that if I keep that line of code it draws a stroke and then erases it when i draw a new one.
    Thats because you need two loops:

    Java Code:
    for (all the strokes)
        get the position ArrayList
        for (all the positions)
             canvas.drawLine(...);

  6. #6
    ngiannini is offline Member
    Join Date
    May 2010
    Posts
    6
    Rep Power
    0

    Default

    I apologize for not understanding everything that you are telling me to do. But as of right now if I use paintComponent rather than paint it doesn't draw anything at all. Also, when minimizing and restoring while using paint, whatever was drawn does remain where it is exactly as it should rather than erasing itself.

    I also tried implementing a a nested for loop as you suggested (I'm guessing I did it wrong) but receive an Unknown source error and OutofMemoryError when doing so.

    Again, I'm sorry if this comes a little slow to me and I'm really grateful for your help.

  7. #7
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

    Default

    Quote Originally Posted by ngiannini View Post
    I apologize for not understanding everything that you are telling me to do.
    No need to apologize, but if there is any error, it is not in not knowing but in not asking for clarification.


    But as of right now if I use paintComponent rather than paint it doesn't draw anything at all.
    My guess is that you're still trying to do this from within a JInternalFrame rather than a JPanel as suggested, but without code, who knows.

    Also, when minimizing and restoring while using paint, whatever was drawn does remain where it is exactly as it should rather than erasing itself.
    It didn't work this way for me when I used your latest code.


    I also tried implementing a a nested for loop as you suggested (I'm guessing I did it wrong) but receive an Unknown source error and OutofMemoryError when doing so.
    Again, without code, who knows what you're doing wrong.

  8. #8
    ngiannini is offline Member
    Join Date
    May 2010
    Posts
    6
    Rep Power
    0

    Default

    Here is my latest code. I guess what I'm having trouble comprehending is that if I switch to JPanel rather than JInternalFrame woulnd't that defeat the purpose of using a JDesktopPane? Or can you add a JPanel as a child component to a JInternalFrame?

    Java Code:
    import javax.swing.JInternalFrame;
    import javax.swing.JPanel;
    import javax.swing.event.InternalFrameAdapter;
    
    import java.awt.event.*;
    import java.awt.*;
    import java.util.ArrayList;
    import java.util.Vector;
    
    //Creates a new Canvas to paint on
    public class PaintCanvas extends JInternalFrame implements MouseMotionListener, MouseListener {
    	
    	//Keep track of number of canvases open
        static int canvasCount = 0;
        //Create vector to keep track of mouse positions
        private ArrayList<Point> positions;
        private ArrayList<ArrayList> stroke = new ArrayList<ArrayList>();
        private Point point1;
        private Point point2;
    
        //PaintCanvas Constructor
        public PaintCanvas() {
        	
        	//Set canvas attributes
            super();
            setSize(700,600);
            setBackground(Color.white);
            setLocation(100, 0);
            addMouseListener(this);
            addMouseMotionListener(this);
            positions = new ArrayList<Point>();
        }
        
        //Paint Method
        public void paintComponent(Graphics canvas) {
        	super.paintComponent(canvas);
        	canvas.setColor(Color.black);
        	for (int i = 0; i < stroke.size(); i++){
        		stroke.add(positions);
    	   	 	for (int j = 1; j < positions.size(); j++){
    	   	 		point1 =  (positions.get(j - 1));
    	   	 		point2 =  (positions.get(j));
    	   	 		canvas.drawLine(point1.x, point1.y, point2.x, point2.y);
    	   	 	}
        	}
        }
        
        public ArrayList<ArrayList> getStroke(){
        	return stroke;
        }
        
        public ArrayList<Point> getPositions(){
        	return positions;
        }
    
        public void setPositions(int x, int y){
        	positions.add(new Point(x, y));
        }
        
    	//Control interpolation
    	public void mouseDragged(MouseEvent myCoord) {
    		setPositions(myCoord.getX(), myCoord.getY());
    		stroke.add(getPositions());
    		repaint();
        }
    
    	@Override
    	public void mouseMoved(MouseEvent arg0) {
    		
    	}
    
    	@Override
    	public void mouseClicked(MouseEvent e) {
    		
    	}
    
    	@Override
    	public void mouseEntered(MouseEvent e) {
    		
    	}
    
    	@Override
    	public void mouseExited(MouseEvent e) {
    		
    	}
    
    	@Override
    	public void mousePressed(MouseEvent myCoord) {
    		positions = new ArrayList<Point>();
    	}
    
    	@Override
    	public void mouseReleased(MouseEvent myCoord) {
    		stroke.add(positions);
    	}
    }

  9. #9
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

    Default

    Quote Originally Posted by ngiannini View Post
    Here is my latest code. I guess what I'm having trouble comprehending is that if I switch to JPanel rather than JInternalFrame woulnd't that defeat the purpose of using a JDesktopPane? Or can you add a JPanel as a child component to a JInternalFrame?
    The tutorials and the API would answer this. A JInternalFrame is similar to a JFrame in that it has a contentPane that allows components to be added, or the contentPane itself can be replaced. For instance,...

    Java Code:
    import java.awt.BasicStroke;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Point;
    import java.awt.event.*;
    import java.util.ArrayList;
    
    import javax.swing.*;
    
    public class SimplePaint {
    
      private static void createAndShowUI() {
        JFrame frame = new JFrame("Simple Paint");
        frame.getContentPane().add(new SimplePaintMainGui().getMainPanel());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
      }
    
      public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(new Runnable() {
          public void run() {
            createAndShowUI();
          }
        });
      }
    }
    
    class SimplePaintMainGui {
      private static final Dimension APP_SIZE = new Dimension(800, 600);
      private static final Dimension PAINT_PANEL_SIZE = new Dimension(500, 400);
      private JDesktopPane mainDesktopPane = new JDesktopPane();
    
      public SimplePaintMainGui() {
        mainDesktopPane.setPreferredSize(APP_SIZE);
        
        SimplePaintPanel paintPanel = new SimplePaintPanel();
        paintPanel.setPreferredSize(PAINT_PANEL_SIZE);
        JInternalFrame intFrame = new JInternalFrame("Paint Panel", true, true, true, true);
        intFrame.getContentPane().add(paintPanel);
        intFrame.pack();
        intFrame.setLocation(100, 100);
        intFrame.setVisible(true);
        mainDesktopPane.add(intFrame);
      }
    
      public JComponent getMainPanel() {
        return mainDesktopPane;
      }
    
    }
    
    @SuppressWarnings("serial")
    class SimplePaintPanel extends JPanel {
      private static final float STROKE_POINTS = 4.0f;
      private static final Color LINE_COLOR = Color.blue;
      private static final Color CURRENT_LINE_COLOR = Color.red;
      private ArrayList<ArrayList<Point>> pointsLists = new ArrayList<ArrayList<Point>>();
      private ArrayList<Point> currentPointList;
      public SimplePaintPanel() {
        setBackground(Color.white);
        MouseAdapter myMouseAdapter = new MyMouseAdapter();
        
        addMouseListener(myMouseAdapter);
        addMouseMotionListener(myMouseAdapter);
      }
    
      @Override
      protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setStroke(new BasicStroke(STROKE_POINTS, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
        g2.setColor(LINE_COLOR);
        for (ArrayList<Point> pointList : pointsLists) {
          if (pointList.size() > 2) {
            for (int i = 1; i < pointList.size(); i++) {
              Point p1 = pointList.get(i - 1);
              Point p2 = pointList.get(i);
              g2.drawLine(p1.x, p1.y, p2.x, p2.y);
            }
          }
        }
        
        g2.setColor(CURRENT_LINE_COLOR);
        if (currentPointList != null && currentPointList.size() > 2) {
          for (int i = 1; i < currentPointList.size(); i++) {
            Point p1 = currentPointList.get(i - 1);
            Point p2 = currentPointList.get(i);
            g2.drawLine(p1.x, p1.y, p2.x, p2.y);
          }
        }
      }
      
      private class MyMouseAdapter extends MouseAdapter {
        
        @Override
        public void mousePressed(MouseEvent e) {
          currentPointList = new ArrayList<Point>();
          currentPointList.add(e.getPoint());
          repaint();
        }
        
        @Override
        public void mouseDragged(MouseEvent e) {
          currentPointList.add(e.getPoint());
          repaint();
        }
        
        @Override
        public void mouseReleased(MouseEvent e) {
          currentPointList.add(e.getPoint());
          
          pointsLists.add(currentPointList);
          currentPointList = null;
          
          repaint();
        }
      }
    }

  10. #10
    camickr is offline Senior Member
    Join Date
    Jul 2009
    Posts
    1,236
    Rep Power
    7

    Default

    Or can you add a JPanel as a child component to a JInternalFrame?
    Have you read the API for JInternalFrame? Did you follow the link to the Swing tutorial on "How to Use Internal Frames? A JInternalFrame is designed to be used just like a JFrame or JDialog. That is you can add any component to it.

    It appears to me that your problem is that you never use the "positions" ArrayList. YOur mousePressed() and mouseReleased() code looks reasonable. You create it and then add it to the "stroke" ArrayList. The problem is you never add any Points to it. Your mouseDragged() code adds the Point directly to the "stroke" ArrayList. You should be adding the Point to the "positions" ArrayList. That is the change that will allow you to draw multiple lines, instead of just one line.

    Edit:

    Way too slow again....

  11. #11
    ngiannini is offline Member
    Join Date
    May 2010
    Posts
    6
    Rep Power
    0

    Default

    I thank you both for your help I'll take the time to dissect the sample code you gave me and read up more on java components because clearly I need to. I'll report back with what I have after then.

    Thanks again.

  12. #12
    ngiannini is offline Member
    Join Date
    May 2010
    Posts
    6
    Rep Power
    0

    Default

    Based on the code you provided how would you recommend changing the stroke size and stroke color? I added a button which brings up the JColorChooser and a slider to change stroke size and am now attempting to store both color and stroke size into ArrayLists as well. Do you think creating a stroke class would a more elegant way of doing this?

  13. #13
    camickr is offline Senior Member
    Join Date
    Jul 2009
    Posts
    1,236
    Rep Power
    7

    Default

    Do you think creating a stroke class would a more elegant way of doing this?
    That is exactly what I suggested in point 2 of my first reply. If you look at my example code from the Custom Painting Approaches you will notice I create the "ColoredRectangle" class to store 2 pieces of information. In your case you will need to store 3 pieces of information:

    a) color
    b) stroke size
    c) ArrayList of Points

Similar Threads

  1. Simple Paint program question
    By StressaJune in forum New To Java
    Replies: 1
    Last Post: 03-30-2009, 09:46 PM
  2. Some confusions with paint()
    By kendaop in forum Java Applets
    Replies: 1
    Last Post: 01-24-2009, 01:23 AM
  3. finished paint!
    By diggitydoggz in forum New To Java
    Replies: 3
    Last Post: 01-04-2009, 11:33 AM
  4. Replies: 3
    Last Post: 12-31-2008, 06:57 AM
  5. paint() and paintComponent()
    By goldhouse in forum Java 2D
    Replies: 1
    Last Post: 07-17-2007, 04:43 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •