This discussion is archived
8 Replies Latest reply: Feb 20, 2011 6:31 AM by 809605 RSS

Swing Timer for "filling up" bottles...

809605 Newbie
Currently Being Moderated
My question is simple as that:

1)I have main class which extends a JFrame.
2)Inside that class there is a JPanel with a BufferedImage on top of it.
3)Finally there is also a JButton which I call "Fire"..that's all for the design..

Now here's the deal:

When pressing the button there's a little method which returns me an array of 5 Ellipse2D objects. (The array is called "points" and is in essence an array of simple circles..).

All I want to do when pressing "Fire" is get these objects show up on the BufferedImage which I call "bf" and gradually get them filled up with color in a way that would give a sense of animation. What's the simplest way to do that?

P.S. I have tried using the swing Timer class but the problem with that approach is that I can't pass parameters into the method call(inside the actionPerformed) which I need if I want to get my array through...

Thank you in advance
  • 1. Re: Swing Timer for "filling up" bottles...
    StanislavL Pro
    Currently Being Moderated
    Let's say we have 1 ellipse and want to fill it. Add a SwingTimer to be called let's say every 100 (or 200 or 500) msecs. On each call we should increase the filled bottom part of the ellipse.

    You can use ellipse getBounds() or getBounds2D() to get surrounding rectangle. Then to fill the bottom 50% of the ellipse we create a smaller (50%) part of the rectangle (rect.y=rect.y+rect.height/2 and rect.height=rect.height/2).

    Then create an Area from the ellipse and intersect the area with the bottom rectangle to have bottom half-ellipse.

    Then just fill the result bottom half-ellipse Area.

    On the next call of timer increase the bottom rectangle to cover 55% or 60% and fill the bigger Area.
  • 2. Re: Swing Timer for "filling up" bottles...
    809605 Newbie
    Currently Being Moderated
    StanislavL wrote:
    Then create an Area from the ellipse and intersect the area with the bottom rectangle to have bottom half-ellipse.

    Then just fill the result bottom half-ellipse Area.

    On the next call of timer increase the bottom rectangle to cover 55% or 60% and fill the bigger Area.
    From that point over... I completely lost you..!

    Here's a small sscce...
    import java.awt.*;
    import java.awt.geom.*;
    import javax.swing.*;
    
    public class myApp extends JFrame{
    
         private JPanel myPanel;
         private JButton myButton;
         private Ellipse2D e[];
    
         public myApp(){
              //the objects I need to draw
              e = new Ellipse2D.Double[2];
              e[0] = new Ellipse2D.Double(50.0, 50.0, 50.0, 50.0);
              e[1] = new Ellipse2D.Double(120.0, 120.0, 50.0, 50.0);
              //--------------------------
              setSize(400,300);
              myPanel = new JPanel(new BorderLayout());
              myButton = new JButton("Fire");
              setLayout(new BorderLayout());
              this.add(myPanel, BorderLayout.SOUTH);
              this.add(myButton, BorderLayout.NORTH);
         }
         public static void main(String args[])  {
              myApp my = new myApp();
              my.setVisible(true);
         }
    }
    How exactly do I create this "intersection" and how do I pass parameters(the ellipses) to the swing timer?
  • 3. Re: Swing Timer for "filling up" bottles...
    StanislavL Pro
    Currently Being Moderated
            Ellipse2D ellipse=null; //obtain next ellipse from the array
            Rectangle r=ellipse.getBounds();
            r.y=r.y+r.height/2;
            r.height=r.height/2;
            Area halfEllipse=new Area(ellipse);
            halfEllipse.intersect(new Area(r));
    No need to pass array f ellipses in the swing timer. You can use all the same array. You need "% of filling" increasing counter.
    On each swing timer call you create the r with position and height according to the % and fill the area. After that increase the counter e.g. +5% till 100% is reached.
  • 4. Re: Swing Timer for "filling up" bottles...
    809605 Newbie
    Currently Being Moderated
    StanislavL wrote:
    Ellipse2D ellipse=null; //obtain next ellipse from the array
    Rectangle r=ellipse.getBounds();
    r.y=r.y+r.height/2;
    r.height=r.height/2;
    Area halfEllipse=new Area(ellipse);
    halfEllipse.intersect(new Area(r));
    No need to pass array f ellipses in the swing timer. You can use all the same array. You need "% of filling" increasing counter.
    On each swing timer call you create the r with position and height according to the % and fill the area. After that increase the counter e.g. +5% till 100% is reached.
    Right. Now you gave me the method but I still don't know how to use it.
    For instance somewhere inside my class I'll place that little piece of code:
    javax.swing.Timer t = new javax.swing.Timer(500, new ActionListener() {
              public void actionPerformed(ActionEvent e) {
                  drawMethod(); //here will be the invocation of the method containing your code
              }
           });
    I'm a little confused here..but say I have an int counter and I want the animation to get finished in 3 steps. How would I do that?
    If say I place a counter instance variable inside the actionPerformed it will reset every time the method is invoked...
  • 5. Re: Swing Timer for "filling up" bottles...
    StanislavL Pro
    Currently Being Moderated
    Suppose you draw your ellipses on a JPanel. You use paintComponent(Graphics g) method where you call something like this
    Graphics2D g2d=(Graphics2D )g;
    g2d.draw(ellipse);
    
    //you can add the shape filling code and call
    g2d.draw(haldEllipseArea);
    So first you set the percentage to 0 and start timer. In the timer's action you increase the % and call the panel.repaint();

    it in turn calls paintComponent() where you redraw shapes.

    If % ==100% you just stop the timer.
  • 6. Re: Swing Timer for "filling up" bottles...
    809605 Newbie
    Currently Being Moderated
    Thank you very much for your quick answers..!
    I think I got it now..! But there's still 1 last question I have to ask you...
    -----
    Let's assume I've got 4 different ellipses contained within an arrayList and scattered
    over the whole screen with different coordinates.
    (In other words they simply don't overlap)

    Now, what I still have not understood very well is how I should pass them in the Timer call in turns...
    I mean you already told me about the percentage counter...and it's done..!
    But it only works for one ellipse...!What about the rest...?How should I instruct the app to take the next
    ellipse in the arrayList since I can't pass any parameters?

    To demonstrate what I mean here's sample:
    public void animateEllipses(){
    ......
    ......
    the code you suggested plus the counter for
    for animation of one ellipse
    ......
    ......
    }
    Now in the constructor of the class there's this:
    t = new javax.swing.Timer(20, new ActionListener() {
              public void actionPerformed(ActionEvent e) {
                  //code goes here
                  animateEllipses();
    
              }
           });
     
    Finally, this is the arrayList
    ArrayList<Ellipse2D> e
    and under the actionPerformed of a JButton on my app I place the
    t.start()
    What can I do now...?

    Thanks again!

    Edited by: konos5 on Feb 19, 2011 6:21 PM
  • 7. Re: Swing Timer for "filling up" bottles...
    StanislavL Pro
    Currently Being Moderated
    Actually no need to pass them somehow. Your array should be available if you create the timer in the frame class. Anther way is to create a custom class let's name it FillingTimerAction which implements ActionListener interface and has the ellipses list field.
    t = new javax.swing.Timer(20, new FillingTimerAction(ellipsesList));

    but actually n need to pass them to timer. You drawing panel must have the list. If the panel can draw ellipses that's enough to get them and create the half filled shapes.
  • 8. Re: Swing Timer for "filling up" bottles...
    809605 Newbie
    Currently Being Moderated
    You are right!
    Here's what I ended up though...:

    The arraylist "e" was set as instance variable of the JFrame class as you suggested...(that is my main class)
    public void drawBuffer(int i){
    
            amountNew[i]+=1;  //This is a new array I created to contain the level of "progress" of each ellipse
    
            Graphics2D gc = bufImage.createGraphics();
    
            Ellipse2D ellipse = e.get(i); //obtain next ellipse from the array
            Rectangle r = ellipse.getBounds();
    
            r.y = r.y + r.height - amountNew;

    if (r.y >= ellipse.getY()){

    // r.height = r.height/2;

    Area halfEllipse = new Area(ellipse);
    halfEllipse.intersect(new Area(r));
    gc.fill(halfEllipse);

    repaint();
    }
    else{
    t.stop();
    }
    }


    Once again, thank you very much for your invaluable input!

    Edited by: konos5 on Feb 20, 2011 2:31 PM

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points