Results 1 to 8 of 8
  1. #1
    Reskaillev is offline Member
    Join Date
    Jul 2011
    Posts
    53
    Rep Power
    0

    Default Runnable JButton takes too much memory <-- Alternative?

    So I got this custom made JButton that shows an animation when you put the mouse on it (in this case a sine wave propels). Now with 8 buttons of this type (the amount I'd like to use) in one JPanel this tends to give me a very slow JApplet. Thus what are alternatives I can use to get this animation? Without using a thread.

    Java Code:
    import java.awt.Color;
    import java.awt.Font;
    import java.awt.FontMetrics;
    import java.awt.Graphics;
    import java.awt.Image;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseListener;
    import java.lang.Math;
    import javax.swing.JButton;
    
    
    public class CustomButton extends JButton implements MouseListener,Runnable {
    
    	Color color1=new Color(0, 50, 0);
    	Color color2=new Color(0, 150, 0);
    	String text;
    	int start=0;
    	int adv,hgt;
    	boolean mouseInside;
    	Font font1 = new Font("Verdana",Font.BOLD, 12);
    	FontMetrics fm=this.getFontMetrics(font1);
    	Thread runner;
    	
    public CustomButton(String text) {
    	super();
    	this.text=text;
    	setContentAreaFilled(false); 
    	setBorderPainted(false); 
    	addMouseListener(this);
    	mouseInside=false;
    	adv=fm.stringWidth(text);
    	hgt=fm.getHeight();
    	runner = new Thread(this);
    	runner.start();
    	}
    
    public void paintComponent(Graphics g)
    {
    	g.setColor(color1);
    	g.setFont(font1);
    	g.fillRect(0, 0, 5, getHeight());
    	g.fillRect(getWidth()-5, 0, getWidth(), getHeight());
    	g.drawLine(0, getHeight()/2, getWidth(), getHeight()/2);
    	DrawSine(g);
    	g.setColor(color2);
    	g.drawString(text, getWidth()/2-adv/2, getHeight()/2+hgt/4);
    }
    
    public void DrawSine(Graphics g)
    {	
    int i=5;
    int j=start;
    while(i<getWidth()-5)
    {
    g.drawLine(i, (int)(Math.sin(6*Math.PI*(j-5)/(getWidth()-10))*((getHeight()/2)-5)+getHeight()/2), i+5, (int)(Math.sin(6*Math.PI*(j)/(getWidth()-10))*((getHeight()/2)-5)+getHeight()/2));
    i=i+5;
    j=j+5;
    }
    }
    
    @Override
    public void mouseClicked(MouseEvent arg0) {
    	// TODO Auto-generated method stub
    }
    
    @Override
    public void mouseEntered(MouseEvent e) {[COLOR="red"]//When the mouse is in the Jbutton the boolean changes to true[/COLOR]
    	// TODO Auto-generated method stub
    	color1=new Color(0, 100, 0);
    	color2=new Color(0, 200, 0);
    	mouseInside=true;
    }
    
    @Override
    public void mouseExited(MouseEvent arg0) { [COLOR="red"]//When the mouse is out the Jbutton the boolean changes to false[/COLOR]
    	// TODO Auto-generated method stub
    	color1=new Color(0, 50, 0);
    	color2=new Color(0, 150, 0);
    	mouseInside=false;
    }
    
    @Override
    public void mousePressed(MouseEvent arg0) {
    	// TODO Auto-generated method stub
    }
    
    @Override
    public void mouseReleased(MouseEvent arg0) {
    	// TODO Auto-generated method stub
    }
    
    @Override
    public void run() { [COLOR="red"]//The runner in question, checks if the mouseInside boolean is true and then start++ and repaint[/COLOR]
    	// TODO Auto-generated method stub
    	while(true)
    	{
    		synchronized (this) {
    		if(mouseInside){
    			if (start<8*Math.PI)
    			{
    			start++;
    			}
    			else{start=0;}
    			repaint();
    			try {	
    				    wait (20);
    			} catch (InterruptedException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		}
    		}
    	}
    }
    
    }
    thnx in advance;
    Last edited by Reskaillev; 08-24-2011 at 06:23 PM.

  2. #2
    JosAH's Avatar
    JosAH is offline Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,570
    Blog Entries
    7
    Rep Power
    21

    Default

    Don't call wait( ... ), it probably doesn't do what you have in mind. Call Thread.sleep( ... ) instead, and use a bit larger number.

    kind regards,

    Jos
    cenosillicaphobia: the fear for an empty beer glass

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

    Default

    I would do things differently and use a pair of BufferedImages (one for the non-moving initial image and one that is 2X the width of the button for the moving image) and a Swing Timer that moves the image with an AffineTransform for this type of problem.

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

    Default

    Heck, no need even for an AffineTransform. Just increment or decrement a variable.

    Java Code:
    import java.awt.*;
    import java.awt.event.*;
    import java.awt.image.BufferedImage;
    import javax.swing.*;
    
    public class CustomButton2 extends JButton {
       private static final float STROKE_WIDTH = 3;
       private static final Color STILL_COLOR = Color.black;
       private static final Color MOVING_COLOR = Color.green;
       private static final int MOTION_PERIOD = 15;
       private static final int DELTA_X = 1;
    
       private BufferedImage stillImage;
       private BufferedImage movingImage;
       private boolean still = true;
       private int sineX = 0;
       private Timer motionTimer = new Timer(MOTION_PERIOD, new MotionListener());
    
       public CustomButton2(String text) {
          super(text);
          addComponentListener(new MyCompListener());
          addMouseListener(new MyMouseAdapter());
       }
    
       @Override
       protected void paintComponent(Graphics g) {
          super.paintComponent(g);
          if (still  && stillImage != null) {
             g.drawImage(stillImage, 0, 0, null);
          } else if (!still && movingImage != null) {
             g.drawImage(movingImage, sineX, 0, null);
          }
       }
       
       private class MyMouseAdapter extends MouseAdapter {
          @Override
          public void mouseEntered(MouseEvent e) {
             still = false;
             repaint();
             motionTimer.start();
          }
          
          @Override
          public void mouseExited(MouseEvent e) {
             still = true;
             repaint();
             motionTimer.stop();
          }
       }
       
       private class MotionListener implements ActionListener {
    
          @Override
          public void actionPerformed(ActionEvent e) {
             sineX -= DELTA_X;
             sineX %= getWidth();
             repaint();
          }
       }
    
       private class MyCompListener extends ComponentAdapter {
    
          private void createImage() {
             Dimension d = getSize();
             stillImage = createSineWaveImage(d, STILL_COLOR);
             movingImage = createSineWaveImage(d, MOVING_COLOR);
          }
    
          private BufferedImage createSineWaveImage(Dimension d, Color color) {
             BufferedImage myImage;
             myImage = new BufferedImage(d.width * 2, d.height,
                   BufferedImage.TYPE_INT_ARGB);
             Graphics2D g2 = myImage.createGraphics();
             g2.setColor(color);
             g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                   RenderingHints.VALUE_ANTIALIAS_ON);
             g2.setStroke(new BasicStroke(STROKE_WIDTH));
             drawSine(g2);
             g2.dispose();
             return myImage;
          }
    
          private void drawSine(Graphics2D g2) {
             int delta = 2;
             int i = delta;
             int j = 0;
             while (i < 2* (getWidth() - delta)) {
                g2.drawLine(i,
                      (int) (Math.sin(6 * Math.PI * (j - delta) / (getWidth() - 10))
                            * ((getHeight() / 2) - delta) + getHeight() / 2), i + delta,
                      (int) (Math.sin(6 * Math.PI * (j) / (getWidth() - 10))
                            * ((getHeight() / 2) - delta) + getHeight() / 2));
                i = i + delta;
                j = j + delta;
             }
          }
    
          @Override
          public void componentResized(ComponentEvent arg0) {
             createImage();
             repaint();
          }
    
          @Override
          public void componentShown(ComponentEvent arg0) {
             createImage();
             repaint();
          }
    
       }
    
       private static void createAndShowGui() {
          JPanel panel = new JPanel(new GridLayout(3, 3));
          for (int i = 0; i < 9; i++) {
             panel.add(new CustomButton2("fubar"));
          }
          panel.setPreferredSize(new Dimension(400, 200));
          JFrame frame = new JFrame("CustomButton");
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.getContentPane().add(panel);
          frame.pack();
          frame.setLocationRelativeTo(null);
          frame.setVisible(true);
       }
    
       public static void main(String[] args) {
          SwingUtilities.invokeLater(new Runnable() {
             public void run() {
                createAndShowGui();
             }
          });
       }
    }
    Last edited by Fubarable; 08-24-2011 at 07:24 PM.

  5. #5
    DarrylBurke's Avatar
    DarrylBurke is offline Forum Police
    Join Date
    Sep 2008
    Location
    Madgaon, Goa, India
    Posts
    11,304
    Rep Power
    20

    Default

    I would use an animated GIF for the ImageIcon and setRolloverIcon(...).

    db

    edit Code will follow after I get the URLs of the attachments

    Runnable JButton takes too much memory &lt;-- Alternative?-pwr0.gif

    Runnable JButton takes too much memory &lt;-- Alternative?-pwr.gif
    Last edited by DarrylBurke; 08-24-2011 at 07:34 PM.

  6. #6
    Reskaillev is offline Member
    Join Date
    Jul 2011
    Posts
    53
    Rep Power
    0

    Default

    mmh thnx for feedback XD

    @Josh: I changed it to Thread.sleep(40), but the applet is still slow as hell :(

    @Fubarable: Never worked with that but I'll see what I can do, I doesn't remove the thread problem though

    @DarrylBurke: That might actually work :O, no idea what setRollovericon is but reading the API now

    But is making the Jbutton runnable a correct and efficient solution for this problem?
    Maybe something else exists?
    Like a mouselistener that repeats checking if the mouse is inside?
    Last edited by Reskaillev; 08-24-2011 at 07:36 PM.

  7. #7
    DarrylBurke's Avatar
    DarrylBurke is offline Forum Police
    Join Date
    Sep 2008
    Location
    Madgaon, Goa, India
    Posts
    11,304
    Rep Power
    20

    Default

    Looks like this site doesn't allow hotlinking to images so I've uploaded them elsewhere.

    The animation is a bit hasty because of a known Java incompatibility with certain animated GIFs and I don't feel like editing the GIF right now. Anyway it's sufficient to demonstrate what I'm suggesting. There's also a delay which won't be noticeable for images on the local hard disk or in the jar.
    Java Code:
    import java.net.*;
    import javax.swing.*;
    
    public class RolloverAnimateButton {
    
      public static void main(String[] args) throws Exception {
        SwingUtilities.invokeLater(new Runnable() {
    
          @Override
          public void run() {
            new RolloverAnimateButton().makeUI();
          }
        });
      }
    
      public void makeUI() {
        String prefix = "http://i660.photobucket.com/albums/uu323/darrylbu/";
    
        JButton button = new JButton();
        try {
          button.setIcon(new ImageIcon(new URI(prefix + "Pwr0.gif").toURL()));
          button.setRolloverIcon(new ImageIcon(new URI(prefix + "Pwr.gif").toURL()));
          JFrame frame = new JFrame();
          frame.add(button);
          frame.pack();
          frame.setLocationRelativeTo(null);
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.setVisible(true);
        } catch (URISyntaxException ex) {
          ex.printStackTrace();
        } catch (MalformedURLException ex) {
          ex.printStackTrace();
        }
      }
    }
    db

  8. #8
    Reskaillev is offline Member
    Join Date
    Jul 2011
    Posts
    53
    Rep Power
    0

    Default

    Sweet didn't know that function existed, that would remove my mouselistener AND my runner XD

    Now..to get the icon working right....

    thnx a lot to those who answered!
    Last edited by Reskaillev; 08-24-2011 at 08:15 PM.

Similar Threads

  1. Do I have what it takes.
    By phil128 in forum Jobs Discussion
    Replies: 0
    Last Post: 03-04-2011, 12:32 PM
  2. Replies: 2
    Last Post: 04-09-2009, 10:46 PM
  3. Which InputStream takes the least memory?
    By arnab321 in forum New To Java
    Replies: 9
    Last Post: 01-13-2009, 05:45 PM
  4. Replies: 2
    Last Post: 08-21-2008, 07:33 PM
  5. It takes very long time.....
    By iresha in forum Advanced Java
    Replies: 6
    Last Post: 05-11-2008, 02:31 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
  •