Solved

Jbutton image trouble.

Posted on 2006-07-09
26
224 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
Get 15 Days FREE Full-Featured Trial

Benefit from a mission critical IT monitoring with Monitis Premium or get it FREE for your entry level monitoring needs.
-Over 200,000 users
-More than 300,000 websites monitored
-Used in 197 countries
-Recommended by 98% of users

 
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

Revamp Your Training Process

Drastically shorten your training time with WalkMe's advanced online training solution that Guides your trainees to action.

Question has a verified solution.

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

Are you developing a Java application and want to create Excel Spreadsheets? You have come to the right place, this article will describe how you can create Excel Spreadsheets from a Java Application. For the purposes of this article, I will be u…
In this post we will learn how to make Android Gesture Tutorial and give different functionality whenever a user Touch or Scroll android screen.
Viewers learn about the third conditional statement “else if” and use it in an example program. Then additional information about conditional statements is provided, covering the topic thoroughly. Viewers learn about the third conditional statement …
This theoretical tutorial explains exceptions, reasons for exceptions, different categories of exception and exception hierarchy.

695 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