Solved

Jbutton image trouble.

Posted on 2006-07-09
26
218 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
  • 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
 
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
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
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

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
triangle challenge 4 77
countHi challenge 25 84
@SBGen Method 3 25
advertisement module in core php 4 89
For customizing the look of your lightweight component and making it look opaque like it was made of plastic.  This tip assumes your component to be of rectangular shape and completely opaque.   (CODE)
Introduction This article is the first of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article explains our test automation goals. Then rationale is given for the tools we use to a…
Viewers learn about the “while” loop and how to utilize it correctly in Java. Additionally, viewers begin exploring how to include conditional statements within a while loop and avoid an endless loop. Define While Loop: Basic Example: Explanatio…
The viewer will learn how to implement Singleton Design Pattern in Java.

757 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

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now