Results 1 to 13 of 13
Thread: Paint Program Help
- 05-08-2010, 02:31 AM #1
Member
- Join Date
- May 2010
- Posts
- 6
- Rep Power
- 0
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
PaintCanvas.javaJava 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(); } }); } }
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) { } }
- 05-08-2010, 04:19 AM #2
Senior Member
- Join Date
- Jul 2009
- Posts
- 1,158
- Rep Power
- 5
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.
- 05-08-2010, 06:44 PM #3
Member
- Join Date
- May 2010
- Posts
- 6
- Rep Power
- 0
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); } }
-
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 06:59 PM.
- 05-08-2010, 06:54 PM #5
Senior Member
- Join Date
- Jul 2009
- Posts
- 1,158
- Rep Power
- 5
Thats because you need two loops: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.
Java Code:for (all the strokes) get the position ArrayList for (all the positions) canvas.drawLine(...);
- 05-08-2010, 07:20 PM #6
Member
- Join Date
- May 2010
- Posts
- 6
- Rep Power
- 0
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.
-
No need to apologize, but if there is any error, it is not in not knowing but in not asking for clarification.
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.But as of right now if I use paintComponent rather than paint it doesn't draw anything at all.
It didn't work this way for me when I used your latest code.Also, when minimizing and restoring while using paint, whatever was drawn does remain where it is exactly as it should rather than erasing itself.
Again, without code, who knows what you're doing wrong.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.
- 05-08-2010, 07:49 PM #8
Member
- Join Date
- May 2010
- Posts
- 6
- Rep Power
- 0
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); } }
-
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(); } } }
- 05-08-2010, 08:22 PM #10
Senior Member
- Join Date
- Jul 2009
- Posts
- 1,158
- Rep Power
- 5
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.Or can you add a JPanel as a child component to a JInternalFrame?
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....
- 05-09-2010, 01:29 AM #11
Member
- Join Date
- May 2010
- Posts
- 6
- Rep Power
- 0
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.
- 05-10-2010, 07:39 AM #12
Member
- Join Date
- May 2010
- Posts
- 6
- Rep Power
- 0
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?
- 05-10-2010, 04:24 PM #13
Senior Member
- Join Date
- Jul 2009
- Posts
- 1,158
- Rep Power
- 5
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:Do you think creating a stroke class would a more elegant way of doing this?
a) color
b) stroke size
c) ArrayList of Points
Similar Threads
-
Simple Paint program question
By StressaJune in forum New To JavaReplies: 1Last Post: 03-30-2009, 08:46 PM -
Some confusions with paint()
By kendaop in forum Java AppletsReplies: 1Last Post: 01-24-2009, 12:23 AM -
finished paint!
By diggitydoggz in forum New To JavaReplies: 3Last Post: 01-04-2009, 10:33 AM -
just started paint program. am i going the right direction?
By diggitydoggz in forum New To JavaReplies: 3Last Post: 12-31-2008, 05:57 AM -
paint() and paintComponent()
By goldhouse in forum Java 2DReplies: 1Last Post: 07-17-2007, 03:43 AM


LinkBack URL
About LinkBacks
Reply With Quote

Bookmarks