• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 228
  • Last Modified:

Jbutton image trouble.

I have the following:
long STime = System.currentTimeMillis();
while(System.currentTimeMillis()-STime <3000)
{
      for(int i =0;i<5;i++)
      {
            Random RandGen = new Random();
            SetImage(Button[i],(1+RandGen.nextInt(6))+".jpg"); //Set Button[i] to random image 1,2,3,4,5, or 6.jpg
      }
}

Rather than changing the images constantly for 3 seconds however, it changes the images ONCE after 3 seconds.
What is the best way to force the images to refresh after a call to SetImage?
0
List244
Asked:
List244
  • 11
  • 8
  • 5
  • +1
1 Solution
 
ksivananthCommented:
try

Button[i].validate() ;
Button[i].repaint() ;
0
 
List244Author Commented:
Still no paint.
0
 
ksivananthCommented:
execute all the update code in SwingUtilities.invokeLater method if you execute this in separate thread
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
CEHJCommented:
Easiest to use a swing Timer. Example in API docs:

http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/Timer.html
0
 
List244Author Commented:
CEHJ, I have tried this as well, can you give a code example?  Either implemented in my code, or something similar so
I can see how it is done?
0
 
CEHJCommented:
I'm not sure precisely what timing you want though...
0
 
List244Author Commented:
I would say pretty fast, and I could always alter that.  I just would like to see some working example of how to do it
properly.  I have tried a timer previously, and it didn't work, so I assume my method is faulty.
0
 
CEHJCommented:
(assuming every 3 seconds)

int delay = 3000; // 3 seconds
final Random RandGen = new Random();
ActionListener taskPerformer = new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
            SetImage(Button[i],(1+RandGen.nextInt(6))+".jpg"); //Set Button[i] to random image 1,2,3,4,5, or 6.jpg
      }
};
new Timer(delay, taskPerformer).start();
0
 
List244Author Commented:
Have yet to try this, but I remember previously, I had an issue where it said can not access non-final member 'i'.
Is this still going to occur?
0
 
List244Author Commented:
Basically, what I am trying to do is this:

User clicks a jbutton, for 3 seconds, the images switch randomly.  At the end of the three seconds,
the button images remain constant at whatever the last randomly generated set was.  The problem
is, everytime I try this, it only shows the images LAST chosen.  As if the loop is too busy so it does not
draw until completed.
0
 
CEHJCommented:
Depends where 'i' is defined. If it's a local variable, define it as final, like the Random
0
 
objectsCommented:
try the following, where Timer and STimer are member vars of your class

ActionListener taskPerformer = new ActionListener() {
     Random RandGen = new Random();
     public void actionPerformed(ActionEvent evt) {
          SetImage(Button[i],(1+RandGen.nextInt(6))+".jpg"); //Set Button[i] to random image 1,2,3,4,5, or 6.jpg
          if (System.currentTimeMillis()-STime <3000) {
             Timer.stop();
          }
 }
};
STime = System.currentTimeMillis();
Timer = new Timer(100, taskPerformer).start();
0
 
objectsCommented:
you should avoid using final, if you are just updating one button at a time then instead use a member var

ActionListener taskPerformer = new ActionListener() {
     Random RandGen = new Random();
      public void actionPerformed(ActionEvent evt) {
          SetImage(UpdateButton,(1+RandGen.nextInt(6))+".jpg"); //Set Button[i] to random image 1,2,3,4,5, or 6.jpg
          if (System.currentTimeMillis()-STime <3000) {
             Timer.stop();
          }
 }
};
STime = System.currentTimeMillis();
Timer = new Timer(100, taskPerformer).start();
0
 
objectsCommented:
If you are updating more than one button at a time, then instead define the button to update and the time as member vars of the *inner* class. Let me know if you have any questions :)
0
 
CEHJCommented:
Try the following - you can't set the Timer too fast or the eye won't register the changes


private class ImageRandomizer implements ActionListener {
      private final MAX_ITERATIONS = 2 * 3;
      private int iterations;
      private Random RandGen = new Random();
      
      public void actionPerformed(ActionEvent evt) {
            if (++iterations == MAX_ITERATIONS) {
                  randomizerTimer.cancel();
            }
            SetImage(Button[i],(1+RandGen.nextInt(6))+".jpg");
      }

}

....

randomizerTimer = new Timer(delay, new ImageRandomizer()).start(); // randomizerTimer is a member var
0
 
List244Author Commented:
Can either of you show a working example?  I can not get any of this working within the method I first supplied.
I can not access the variables because they are not final, and they can not be final because they need to change.
Maybe it would be easier to thread the set-image function?
0
 
objectsCommented:
the code i posted above should do what you want (and does not require any final vars). have u tried it?

ActionListener taskPerformer = new ActionListener() {
     Random RandGen = new Random();
      public void actionPerformed(ActionEvent evt) {
          SetImage(UpdateButton,(1+RandGen.nextInt(6))+".jpg"); //Set Button[i] to random image 1,2,3,4,5, or 6.jpg
          if (System.currentTimeMillis()-STime <3000) {
             Timer.stop();
          }
 }
};
UpdateButton = Button[i];
STime = System.currentTimeMillis();
Timer = new Timer(100, taskPerformer).start();
0
 
List244Author Commented:
Objects, yes I have, but I do not know how to use it.  For example, where would this go?

ActionListener taskPerformer = new ActionListener() {
     Random RandGen = new Random();
      public void actionPerformed(ActionEvent evt) {
          SetImage(UpdateButton,(1+RandGen.nextInt(6))+".jpg"); //Set Button[i] to random image 1,2,3,4,5, or 6.jpg
          if (System.currentTimeMillis()-STime <3000) {
             Timer.stop();
          }
 }
};
0
 
objectsCommented:
put it in the action listener that gets called when the button is clicked
ie. where you have your existing code (which it will replace)
0
 
List244Author Commented:
Objects, I am not doing it quite that way, maybe I should post my code:

public class Yahtzee extends JApplet implements ActionListener
{
      private static final long serialVersionUID = 3932602065490549886L;
      final JButton Dice[] = new JButton[5];
      final JButton Roll = new JButton("Roll dice");
      public void init()
      {
            Container Form = getContentPane();
            JPanel MainPanel = new JPanel();
            MainPanel.setBackground(Color.BLACK);
            Form.add(MainPanel);
            MainPanel.add(DiceFrame(),BorderLayout.NORTH);
            Form.add(Roll,BorderLayout.SOUTH);
            Roll.addActionListener(this);
      }
      private JPanel DiceFrame()
      {
            JPanel DicePanel = new JPanel();
            DicePanel.setBackground(Color.BLACK);
            for(int i=0;i<5;i++)//Loop through 5 dice.
            {
                  Dice[i] = new JButton();
                  SetImage(Dice[i],(i+1) + ".jpg");
                  Dice[i].setBorder(BorderFactory.createBevelBorder(0));
                  Dice[i].setBackground(Color.BLACK);
                  Dice[i].setVerticalTextPosition(SwingConstants.BOTTOM);
                  Dice[i].setHorizontalTextPosition(SwingConstants.CENTER);
                  Dice[i].setForeground(Color.BLUE);
                  DicePanel.add(Dice[i]);
                  Dice[i].addActionListener(this);
            }
            return DicePanel;      
      }
      private int SetImage(JButton Button,String File)
      {
            URL ImageLoc = getClass().getResource("/" + File);
            Icon ThePic = new ImageIcon(ImageLoc);
            Button.setIcon(ThePic);
            return 1;
      }
      public void actionPerformed(ActionEvent e)
      {
            if (e.getSource() == Roll)
            {
                  RollDice();
                  return;
            }
            for(int i=0;i<5;i++)
            {
                  if (e.getSource() == Dice[i])
                  {
                        if(IsHeld(Dice[i]))
                        {
                              Dice[i].setBorder(BorderFactory.createBevelBorder(0));
                              Dice[i].setText("");
                        }
                        else
                        {
                              Dice[i].setBorder(BorderFactory.createBevelBorder(1));
                              Dice[i].setText("Held");
                        }
                  }
            }
      }
      private void RollDice()
      {
            long STime = System.currentTimeMillis();
            while(System.currentTimeMillis()-STime <3000)
            {
                 for(int i =0;i<5;i++)
                 {
                      Random RandGen = new Random();
                      if (!IsHeld(Dice[i]))
                            SetImage(Dice[i],(1+RandGen.nextInt(6))+".jpg"); //Set Button[i] to random image 1,2,3,4,5, or 6.jpg
                 }
            }
      }
      private boolean IsHeld(JButton Button)
      {
            Border b = Button.getBorder();
            if (b instanceof BevelBorder)
            {
                BevelBorder bb = (BevelBorder) b;
                if (bb.getBevelType()==0)
                      return false;
                else if (bb.getBevelType()==1)
                      return true;
            }
            return false;
      }
}
0
 
List244Author Commented:
So, you can see, I can't really replace the current listener, as it is handling more than one object.
Also, at current, I am not inside of a listener for the changing of an image, I have moved it away
to separate things since I am using global listeners.
0
 
objectsCommented:
put the code in RollDice
0
 
objectsCommented:
you''; also want to add your existing loop into the new action listener

ActionListener taskPerformer = new ActionListener() {
     Random RandGen = new Random();
      public void actionPerformed(ActionEvent evt) {
         for(int i =0;i<5;i++)
         {
             if (!IsHeld(Dice[i]))
               SetImage(Button[i],(1+RandGen.nextInt(6))+".jpg"); //Set Button[i] to random image 1,2,3,4,5, or 6.jpg
             if (System.currentTimeMillis()-STime <3000) {
                Timer.stop();
              }
        }
    }
};
0
 
List244Author Commented:
     private void RollDice()
      {
            Timer T = new Timer(100,new ActionListener()
            {
                 Random RandGen = new Random();
                 long STime = System.currentTimeMillis();
                  public void actionPerformed(ActionEvent evt)
                  {
                     for(int i =0;i<5;i++)
                     {
                         if (!IsHeld(Dice[i]))
                           SetImage(Dice[i],(1+RandGen.nextInt(6))+".jpg"); //Set Button[i] to random image 1,2,3,4,5, or 6.jpg
                         if (System.currentTimeMillis()-STime >3000)
                         {
                               SetImage(Dice[0],"6.jpg");
                            stop();
                          }
                    }
                }
            });
            T.start();
      }

Okay, the above is my code, it works, almost.  Everything is as expected until "stop();"  It does not stop.  I added an image change
before stop, to test that it is happening, and it is, however, it continues on with the timer.
0
 
objectsCommented:
>                           stop();

thould be T.stop()

and make T a member variable
0
 
List244Author Commented:
That works, thanks again, Objects.
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 11
  • 8
  • 5
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now