Results 1 to 12 of 12
  1. #1
    Cu Annan is offline Member
    Join Date
    Jul 2011
    Posts
    7
    Rep Power
    0

    Default Simple questions from a very new java user

    Ok, so I studied java back in the pre-Swing days. I've read the trails, but they're not really digestable so I just copied the code presented to tinker with it.
    I have me a very very simple mandlebrot explorer. There are constructors. One for if nothing is provided, one for if the top right and bottom left imaginary coordinates are provided and one for if both coordinates and a width and height are provided.

    My thinking was that if the frame is resized, I can just resize the mandlebrot set by calling the relevant setters and if the image is clicked and dragged on, it would re-generate the set for the given new top right and bottom left.

    I'm having trouble figuring out how to show a white rectangle during the click and drag. In fact, the entire life cycle of the JPanel is confusing me a little.


    Java Code:
    import mandlebrot.*;
    
    import java.util.ArrayList;
    
    import java.awt.*;
    import java.awt.event.*;
    
    import javax.swing.*;
    
    public class Driver extends JFrame
    {
    	/**
    	 * Auto generated serialVersionUID by eclipse
    	 */
    	private static final long serialVersionUID = -648629675951097404L;
    	
    	
    	protected Mandlebrot fractal;
    	
    	protected Integer maxDepth;
    	
    	protected Integer rectX;
    	protected Integer rectY;
    	protected Integer rectWidth;
    	protected Integer rectHeight;
    	
    	protected Graphics2D g;
    		
    	public Driver()
    	{
    		super("The mandlebrot set");
    		this.fractal = new Mandlebrot();
    		
    		System.out.println("Instantiating");
    		
    		this.addMouseListener(new MouseAdapter()
    			{
    				public void mousePressed(MouseEvent e)
    				{
    					Driver d = (Driver)e.getSource();
    					System.out.println("Mouse Pressed");
    					d.setRectX(e.getX());
    					d.setRectY(e.getY());
    				}
    				
    				public void mouseReleased(MouseEvent e)
    				{
    					Driver d = (Driver)e.getSource();
    					System.out.println("Mouse released");
    				}
    				
    				public void mouseDragged(MouseEvent e)
    				{
    					System.out.println("Here");
    					Driver d = (Driver)e.getSource();
    				}
    			}
    		);
    	}
    	
    	public Driver(Integer w, Integer h, Integer maxDepth)
    	{
    		this();
    		this.fractal = new Mandlebrot(w, h);
    		this.maxDepth = maxDepth;
    	}
    	
    	public void drawRect()
    	{
    		this.repaint();
    	}
    	
    	public void repaint()
    	{
    		this.g.setColor(Color.white);
    		this.g.drawRect(this.rectX, this.rectY, 20, 20);
    	}
    	
    	public void paint(Graphics g)
    	{
    		this.g = (Graphics2D) g;
    		this.g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    		
    		this.render();
    	}
    	
    	public void render()
    	{
    		this.fractal.generate(this.maxDepth);
    		
    		ArrayList<ArrayList<Integer>> plane = this.fractal.getComplexPlane();
    		
    		for(Integer i = 0; i < plane.size(); i++)
    		{
    			ArrayList<Integer> row = plane.get(i);
    			for(Integer r = 0; r < row.size(); r++)
    			{
    				Color c;
    				Integer depth = row.get(r);
    				if(depth == 1000)
    				{
    					c = Color.black;
    				}
    				else
    				{
    					float hue = (depth.floatValue() * 5 / maxDepth) % maxDepth;
    					
    					c = Color.getHSBColor(hue, 1, 1);
    				}
    				this.g.setColor(c);
    				this.g.fillRect(r, i, 1, 1);
    			}
    			
    		}
    	}
    
    	public Integer getRectX()
    	{
    		return rectX;
    	}
    
    	public void setRectX(Integer rectX)
    	{
    		this.rectX = rectX;
    	}
    
    	public Integer getRectY()
    	{
    		return rectY;
    	}
    
    	public void setRectY(Integer rectY)
    	{
    		this.rectY = rectY;
    	}
    
    	public Integer getRectWidth()
    	{
    		return rectWidth;
    	}
    
    	public void setRectWidth(Integer rectWidth)
    	{
    		this.rectWidth = rectWidth;
    	}
    
    	public Integer getRectHeight()
    	{
    		return rectHeight;
    	}
    
    	public void setRectHeight(Integer rectHeight)
    	{
    		this.rectHeight = rectHeight;
    	}
    	
    	
    }
    The mouseDragged event never gets triggered, though. I can S.o.pl in mousePressed and mouseReleased and they show up as expected. I was wondering if anyone could tell me what I've done wrong.

    My second question is a lot simpler. The docs say that Swing handles double buffering. Does that mean I don't have to worry about it at all or is there something I need to tell it to do to double buffer. I noticed in one of my earlier versions that when I ran the code my graphics card had a panic attack and there was even a General Protection Fault at one point.

  2. #2
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    SW Missouri
    Posts
    17,306
    Rep Power
    25

    Default

    A suggestion that never hurts: Add @Override before all the methods you override in an adapter. If you misspell a method or its args the compiler very happily adds it as a new method. Since the adapter provides all listener methods, your code is never called.

    Double check the API doc. The mouseDragged method is part of a a motion listener. You need to add one of those.
    Last edited by Norm; 07-04-2011 at 09:24 PM.

  3. #3
    Cu Annan is offline Member
    Join Date
    Jul 2011
    Posts
    7
    Rep Power
    0

    Default

    Thanks Norm,

    That's a new one on me. I've added it, but the compiler's not complaining. Should it just be
    Java Code:
    this.addMouseListener(new MouseAdapter()
    			{
    				@Override
    				public void mousePressed(MouseEvent e)
    				{
    					Driver d = (Driver)e.getSource();
    					System.out.println("Mouse Pressed");
    					d.setRectX(e.getX());
    					d.setRectY(e.getY());
    				}
    				
    				@Override
    				public void mouseReleased(MouseEvent e)
    				{
    					Driver d = (Driver)e.getSource();
    					System.out.println("Mouse released");
    				}
    				
    				@Override
    				public void mouseDragged(MouseEvent e)
    				{
    					System.out.println("Here");
    					Driver d = (Driver)e.getSource();
    				}
    			}
    		);

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

    Default

    You've got several issues that need to be addressed:

    • Don't draw directly in a root container such as a JFrame.
    • Do not try to save a Graphics object into a class field and try to use it later. It is not a stable object and will be disposed of by the JVM after use. Instead if you draw in the component itself, use the Graphics object provided by the paint/paintComponent method each time you need to draw.
    • Instead if you draw in the component itself, draw in the paintComponent method override of a class that derives from JComponent such as JPanel or JComponent.
    • I would suggest that you do your drawing onto a BufferedImage object. Here you actually will get it's Graphics object via something like getGraphics. You'll actually want to get its Graphics2D object via the BufferedImage's createGraphics() method, and you'll want to dispose this Graphics2D object once you've finished drawing it.
    • Then place your BufferedImage into an ImageIcon and the ImageIcon into a JLabel that is held by your GUI.
    • I'd create a MouseAdapter and add to the JLabel as a MouseListener and MouseMotionListener.
    • To check out a simple example of using a MouseAdapter in this way, please have a look at my reply #7 in this thread: How to compare Range of numbers?


    Hope this helps!
    Last edited by Fubarable; 07-04-2011 at 09:27 PM.

  5. #5
    Cu Annan is offline Member
    Join Date
    Jul 2011
    Posts
    7
    Rep Power
    0

    Default

    Fubarable,

    Thanks for all the feedback, I'll look up those classes now. I solved the mousedrag event when I realised i'd forgotten to copy that code from the tutorial.

  6. #6
    Cu Annan is offline Member
    Join Date
    Jul 2011
    Posts
    7
    Rep Power
    0

    Default

    Thanks again, Fubarable.

    I've started drawing to a BufferedImage. And drawn that directly to the JPanel. I'll start working on the ImageIcon now to follow the rest of your advice.

    Really just posting to say "thank you".

  7. #7
    Cu Annan is offline Member
    Join Date
    Jul 2011
    Posts
    7
    Rep Power
    0

    Default

    Hello again Fubarable,

    I've done most of what you suggested, I think, and my class looks like this:
    Java Code:
    import mandlebrot.*;
    
    import java.util.ArrayList;
    
    import java.awt.*;
    import java.awt.event.*;
    import java.awt.image.BufferedImage;
    
    import javax.swing.*;
    
    public class Driver extends JPanel
    {
    	/**
    	 * Auto generated serialVersionUID by eclipse
    	 */
    	private static final long serialVersionUID = -648629675951097404L;
    	
    	
    	protected Mandlebrot fractal;
    	
    	protected Integer maxDepth;
    	
    	protected Integer rectX;
    	protected Integer rectY;
    	protected Integer rectWidth;
    	protected Integer rectHeight;
    	
    	protected BufferedImage bi;
    	
    	protected Dimension preferredSize;
    	
    	protected Rectangle rect;
    	
    	private class MyMouseAdapter extends MouseAdapter
    	{
    		Integer startX;
    		Integer startY;
    		
    		Boolean active = false;
    		
    		public void mousePressed(MouseEvent e)
    		{
    			this.active = true;
    			this.startX = e.getX();
    			this.startY = e.getY();
    			rect.x = startX;
    			rect.y = startY;
    		}
    		
    		public void mouseReleased(MouseEvent e)
    		{
    			this.active = false;
    		}
    		
    		public void mouseDragged(MouseEvent e)
    		{
    			if(this.active)
    			{
    				Integer rectWidth = this.startX - e.getX();
    				Integer rectHeight = this.startY - e.getY();
    				
    				rect.width = (rectHeight);
    				rect.height = (rectWidth);
    				repaint();
    			}
    		}
    		
    	}
    	
    	public Driver()
    	{
    		this.fractal = new Mandlebrot();
    		
    		MyMouseAdapter l = new MyMouseAdapter();
    		
    		this.addMouseListener(l);
    		this.addMouseMotionListener(l);
    	}
    	
    	public Driver(Integer w, Integer h, Integer maxDepth)
    	{
    		this();
    		this.fractal = new Mandlebrot(w, h);
    		
    		this.bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
    		this.maxDepth = maxDepth;
    		this.preferredSize = new Dimension(w, h);
    		rect = new Rectangle(0, 0, 0, 0);
    	}
    	
    	@Override
    	public Dimension getPreferredSize()
    	{
    		return this.preferredSize;
    	}
    	
    	@Override
    	public void paintComponent(Graphics g)
    	{
    		super.paintComponent(g);
    		Graphics2D g2 = (Graphics2D) g;
    		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    		
    		if(rect.x != 0 && rect.y != 0 && rect.width != 0 && rect.height !=0)
    		{
    			g2.setColor(Color.white);
    			g2.drawRect(this.rect.x, this.rect.y, this.rect.width, this.rect.height);
    		}
    	}
    	
    	public void paint(Graphics g)
    	{
    		super.paint(g);
    		Graphics2D g2 = (Graphics2D) g;
    		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    		
    		this.render();
    		g2.drawImage(bi, 0, 0, this);
    	}
    	
    	public void render()
    	{
    		this.fractal.generate(this.maxDepth);
    		Graphics2D g = this.bi.createGraphics();
    		
    		ArrayList<ArrayList<Integer>> plane = this.fractal.getComplexPlane();
    		
    		for(Integer i = 0; i < plane.size(); i++)
    		{
    			ArrayList<Integer> row = plane.get(i);
    			for(Integer r = 0; r < row.size(); r++)
    			{
    				Color c;
    				Integer depth = row.get(r);
    				if(depth == 1000)
    				{
    					c = Color.black;
    				}
    				else
    				{
    					float hue = (depth.floatValue() * 5 / maxDepth) % maxDepth;
    					
    					c = Color.getHSBColor(hue, 1, 1);
    				}
    				g.setColor(c);
    				g.drawRect(r, i, 1, 1);
    			}
    		}
    		
    	}
    }
    The rectangle still isn't showing up when I click and drag, even though I'm pretty sure I've copied your implementation.
    If I S.o.pl inside the if statement, it shows up every now and then (which I suspect is down to the multiple levels of threading going on between eclipse and the JVM, but I'm not 100% sure on).

    Can you point me at what I'm doing wrong?

  8. #8
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    SW Missouri
    Posts
    17,306
    Rep Power
    25

    Default

    Your paint and paintComponent might be competing. Change the name of paint to paintXXX and see what happens

  9. #9
    Cu Annan is offline Member
    Join Date
    Jul 2011
    Posts
    7
    Rep Power
    0

    Default

    I commented it out, as it was just an override of the JPanel paint method, but now everything's gone grey and none of it happens.
    Inside the paintComponent method; I've put in check to see if the fractal has been rendered at all and, if not, render it and then do the rect stuff, but nothing's painting at all.

  10. #10
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    SW Missouri
    Posts
    17,306
    Rep Power
    25

    Default

    Whoops. Looks like you needed to move the rendering/drawing code from the paint to the paintComponent method.

    Did the mouse drag draw the rectangle?
    Last edited by Norm; 07-04-2011 at 11:23 PM. Reason: Ask about rectangle

  11. #11
    Cu Annan is offline Member
    Join Date
    Jul 2011
    Posts
    7
    Rep Power
    0

    Default

    Figured it out.
    I had already moved the render call, but I had accidentally left the g.drawImage inside the if statement to see if the image needed to be rendered this paintcycle.
    I think I understand how it all works now.
    The image is rendering and drawing now, anyway.

    Thanks again guys.

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

    Default

    More Suggestions:
    • Do not call render() from within paint or paintComponent. These methods (paint/paintComponent) need to be as lean and fast as possible so your program seems responsive to the user, so you'll want to not call any cpu-intensive methods in there if can be avoided.
    • In fact, you'll probably want to do your fractal calculations and BufferedImage drawing from within a background thread.
    • Draw your BufferedImage in the paintComponent just below your call to superPaintComponent.
    • For efficiency and speed, use int rather than Integer wherever possible. You cannot use int however as the generic type of a collection. So you must continue to do ArrayList<Integer> not ArrayList<int>.
    • I would use the Math utility methods abs and min in my mouseDragged method so that the user can draw their rectangle from any direction. For e.g., please see below:


    Java Code:
          public void mouseDragged(MouseEvent e) {
             if (active) {
                rect.x = Math.min(startX, e.getX());
                rect.y = Math.min(startY, e.getY());
                rect.width = Math.abs(startX - e.getX());
                rect.height = Math.abs(startY - e.getY());
                repaint();
             }
          }

Similar Threads

  1. Simple Questions- Stop JPanel Blinking
    By MrFish in forum AWT / Swing
    Replies: 7
    Last Post: 04-10-2011, 06:23 PM
  2. Simple Java IO Questions
    By TheWolfe in forum New To Java
    Replies: 3
    Last Post: 11-30-2010, 01:40 AM
  3. Ask user multiple Yes/No Questions
    By jlafber in forum AWT / Swing
    Replies: 1
    Last Post: 03-30-2010, 11:55 AM
  4. Simple array questions
    By jigglywiggly in forum New To Java
    Replies: 6
    Last Post: 02-15-2009, 05:57 AM
  5. 2 simple java questions
    By jimJohnson in forum New To Java
    Replies: 2
    Last Post: 02-02-2008, 09:35 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
  •