Solved

Jbutton image trouble.

Posted on 2006-07-09
26
223 Views
Last Modified: 2010-03-31
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
Comment
Question by:List244
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 11
  • 8
  • 5
  • +1
26 Comments
 
LVL 26

Expert Comment

by:ksivananth
ID: 17069271
try

Button[i].validate() ;
Button[i].repaint() ;
0
 
LVL 8

Author Comment

by:List244
ID: 17069282
Still no paint.
0
 
LVL 26

Expert Comment

by:ksivananth
ID: 17069354
execute all the update code in SwingUtilities.invokeLater method if you execute this in separate thread
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 86

Expert Comment

by:CEHJ
ID: 17069607
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
 
LVL 8

Author Comment

by:List244
ID: 17069720
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
 
LVL 86

Expert Comment

by:CEHJ
ID: 17069730
I'm not sure precisely what timing you want though...
0
 
LVL 8

Author Comment

by:List244
ID: 17069739
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
 
LVL 86

Expert Comment

by:CEHJ
ID: 17069742
(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
 
LVL 8

Author Comment

by:List244
ID: 17069745
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
 
LVL 8

Author Comment

by:List244
ID: 17069749
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
 
LVL 86

Expert Comment

by:CEHJ
ID: 17069751
Depends where 'i' is defined. If it's a local variable, define it as final, like the Random
0
 
LVL 92

Expert Comment

by:objects
ID: 17069761
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
 
LVL 92

Expert Comment

by:objects
ID: 17069772
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
 
LVL 92

Expert Comment

by:objects
ID: 17069775
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
 
LVL 86

Expert Comment

by:CEHJ
ID: 17069783
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
 
LVL 8

Author Comment

by:List244
ID: 17069843
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
 
LVL 92

Expert Comment

by:objects
ID: 17069849
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
 
LVL 8

Author Comment

by:List244
ID: 17069854
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
 
LVL 92

Expert Comment

by:objects
ID: 17069859
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
 
LVL 8

Author Comment

by:List244
ID: 17069873
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
 
LVL 8

Author Comment

by:List244
ID: 17069884
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
 
LVL 92

Expert Comment

by:objects
ID: 17069897
put the code in RollDice
0
 
LVL 92

Expert Comment

by:objects
ID: 17069903
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
 
LVL 8

Author Comment

by:List244
ID: 17069924
     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
 
LVL 92

Accepted Solution

by:
objects earned 500 total points
ID: 17069931
>                           stop();

thould be T.stop()

and make T a member variable
0
 
LVL 8

Author Comment

by:List244
ID: 17069946
That works, thanks again, Objects.
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

After being asked a question last year, I went into one of my moods where I did some research and code just for the fun and learning of it all.  Subsequently, from this journey, I put together this article on "Range Searching Using Visual Basic.NET …
Java functions are among the best things for programmers to work with as Java sites can be very easy to read and prepare. Java especially simplifies many processes in the coding industry as it helps integrate many forms of technology and different d…
Viewers learn about the “for” loop and how it works in Java. By comparing it to the while loop learned before, viewers can make the transition easily. You will learn about the formatting of the for loop as we write a program that prints even numbers…
This tutorial covers a practical example of lazy loading technique and early loading technique in a Singleton Design Pattern.

696 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question