Change ImageIcon in JLabel using Timer - java

I have two classes: logic and the JFrame. In frame I have a JLabel and a JButton, and I would like to:
When this button is clicked, the ImageIcon in the label changes after a determined time using a Swing Timer, like if it is flashing. To do it I loaded two images with different brightness (img1b and img1). I tried to make the timer change the image twice with different delays, but I was unsuccessful. I also put a listener in the button and implemented the actionPerformed as below:
public void actionPerformed(ActionEvent e) {
if(e.getSource().equals(btnImg1)) {
logic.piscaImagen(img1, lblImg1);
logic.piscaImagen(img1b, lblImg1);
In logic class:
public void piscaImagen(ImageIcon img, JLabel lbl) {
Timer timer = new Timer(1250, null);
timer.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt){
if(lbl.getIcon() != img){
lbl.setIcon(img);
}
}
});
timer.setRepeats(false);
timer.start();
}
But when I run it nothing changes in the logic.piscaImagen. Any tips?

logic.piscaImagen(img1, lblImg1);
logic.piscaImagen(img1b, lblImg1);
It looks to me like you are starting two Timers. So the first Timer fires and it changes the image, then the second timer fires and it restores the image so basically you only see the first image.
All you need is one Timer. Each time the Timer fires you change the image. So the basic code in your Timer would be:
if (lbl.getIcon() == img1)
lbl.setIcon(img1b);
else
lbl.setIcon(img1);
Or for a more flexible solution you can use the Animated Icon.
The Animated Icon will allow you to specify a List of Icons to display. Then when the Timer fires the next Icon in the List is displayed. You can set the Animated Icon for continuous display or you can control the number of cycles.

EDIT: answer inaccurate, repaint() not necessary - see comments.
You're missing the repaint() call that tells the program it needs to update the display.
#Override
public void actionPerformed(ActionEvent evt) {
if(lbl.getIcon() != img){
lbl.setIcon(img);
lbl.repaint();
}
}
(your if statement was also missing a closing brace, unsure what impact that would have / if it was a typo)

Related

Change a JLabel Text while an JButton listener is working

I have a JButton, lets call it "button" and added an ActionListener to it:
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
call();
}
});
It is correctly added to my frame etc. In that JFrame I also have a JLabel, and I want to change its text while the JButton method is working(because it takes ~30 secs to finish). How do I do that? Do I have to use some multi-thread-thingy?
Here is the basic principle(the JLabel is called output):
public void call(){
output.setText("test1");
try { Thread.sleep(1000);
} catch (InterruptedException e) {}
output.setText("test2");
}
This will result in the "output" Label being changed to "test2" after one second. How can I make it instantly display "test1"?
Don't use Thread.sleep(). This will prevent the GUI from repainting itself.
Do I have to use some multi-thread-thingy?
Yes.
For a long running task you need to start a separate Thread, so the GUI can remain responsive.
In this case you can use a SwingWorker.
Read the section from the Swing tutorial on Concurrency for more information and an example of using a SwingWorker.

Changing the same variable for all existing subthreads

sorry in advance if that question did get asked before somewhere here. I really tried to find something that helps me. Sadly I had no luck.
Here is my situation:
I have a Frame class with a button and a slider. And I have a thread class. With the button in the frame class, I create instances of the thread class. One instance of a thread class represents an picture. All the subthreads(pictures) will be displayed in the same frame and move around with a certain interval.
Here is my problem:
The slider controles the interval of the moving pictures. So they move faster or slower. All pictures should get faster or slower simultaneously. Unluckily only the first created thread gets affected by the slider. Same problem is with my ComponentAdapter that has his componentResized function. All the threads(or the pictures) should get bigger or smaller simultaneously relatively to the frame size.
Here I will try to show you roughly how I am doing it:
frame class:
//The actionPerformed for the button that keeps creating threads
//Every thread is a picture (ant in this case) that
// moves through the same field of buttons
public void actionPerformed(ActionEvent e){
a = new AmeiseThread(this);
a.start();
}
// The slider in the frame.When it changes, also the picture movement speed changes
sliderKind.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
JSlider source = (JSlider) e.getSource();
if (!source.getValueIsAdjusting()) {
int speed = source.getValue();
a.sleeptime = 1000 / speed;
}
}
});
// Whenever the Frame gets resized, it will change the Pictures
// on its buttons relatively to its new size
class MyComponentAdapter extends ComponentAdapter {
public void componentResized(ComponentEvent e) {
xScale = jbArray.get(1).getSize().width;
yScale = jbArray.get(1).getSize().height;
a.ameisen.clear();
a.ameisen.add(new ImageIcon(new ImageIcon("ameise.gif").getImage()
.getScaledInstance(xScale, yScale, Image.SCALE_SMOOTH)));
a.ameisen.add(new ImageIcon(new ImageIcon("ameise90.gif").getImage()
.getScaledInstance(xScale, yScale, Image.SCALE_SMOOTH)));
a.ameisen.add(new ImageIcon(new ImageIcon("ameise180.gif").getImage()
.getScaledInstance(xScale, yScale, Image.SCALE_SMOOTH)));
a.ameisen.add(new ImageIcon(new ImageIcon("ameise270.gif").getImage()
.getScaledInstance(xScale, yScale, Image.SCALE_SMOOTH)));
}
}
I can't think of anything that is written in my thread class, that could be of interest. I think the problem lies within my already posted code somewhere. But if you do need more informations, comment it and I will post more informations right away.
Sorry again, if that question already exists. I feel like it does, because it sounds rather simple. Though I really tried to find a question similar to this but I had no luck.
Save all the threads you create
threadList.add(a);
itarate over it when the slider changed
for (AmeiseThread a: threadList)
if (!source.getValueIsAdjusting()) {
int speed = source.getValue();
a.sleeptime = 1000 / speed;
}

Changing the color of a jButton every couple of seconds

I'm trying to create a little button game for a school project. What the game is, is there are a couple buttons that every like 3 seconds will flash a color then if you press it when the color is up, it stays that color.
I have all the buttons created and they display just fine. I just need help with the actual handling code.
What I'm getting stuck on
timer = new Timer(length, jButton1ActionPerformed);
timer.setInitialDelay(pause);
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
jButton1.setBackground(Color.blue);
}
Now this isn't my actual game, I'm just trying to get the hang of the Swing Timers
Now that I have the button changing colors this is the code that I tried to get it to stay that color when clicked.
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
if(jButton1.getBackground().equals(Color.blue){
jButton1.setBackground(Color.blue);
timer.stop();
}
}
You will want to use a Swing Timer to handle your animation. In the Timer's ActionListener, you would have code that randomly selects a button (the Random class can help here) and changes its color, possibly via setForground(...), or even by using ImageIcons and swapping icons via setIcon(...). The JButton's ActionListener can then check the button's icon or foreground color and act accordingly.
Since this is a school project, I'm not posting a code solution but will add some links that should help:
Overall Swing Tutorial
Swing Timer Tutorial
JButton Tutorial
java.util.Random API
To create an ActionListener for your Timer, do just that -- create one inline:
ActionListener timerListener = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
// code to be performed every xxx mSec goes here
}
}
int timerDelay = 3 * 1000; // or whatever length of time needed
Timer timer = new Timer(timerDelay, timerListener);
// later on in the block where you want to start your Timer
timer.start();

Simple animations in Java

I'm attempting to code a simple animation or physics example in a Java Swing application. I have the actual windows application open and working, but I can't figure out how to actually draw my shapes, and how I'd format the code for calculations between frames, that sort of stuff.
I've read some stuff about over riding a paint method, but I don't know what that means, and I don't believe I'm using it in the code I'm using right now. This is my code:
public class Physics extends JFrame{
public Physics() {
initUI();
}
private void initUI() {
JPanel panel = new JPanel();
getContentPane().add(panel);
panel.setLayout(null);
final JLabel label = new JLabel("Hi, press the button to do something");
label.setBounds(20, 0, 2000, 60);
final JButton submitButton = new JButton("Start");
submitButton.setBounds(20, 150, 80, 20);
submitButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
//Put button code here later
}
});
panel.add(label);
panel.add(submitButton);
setTitle("Program");
setSize(300, 250);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Physics ex = new Physics();
ex.setVisible(true);
}
});
}
}
So I have some blank space above my button where I'd like to draw maybe a square or circle moving across the screen to start off with, once I get that down I can start getting into the more advanced stuff. Any hints on how to do that would be appriciated :D
Thanks!
"I've read some stuff about over riding a paint method, but I don't know what that means"
So you've overridden actionPerformed, so you know what an #Override is. As you'll notice from the ActionListener, you never actually explicitly call actionPerformed, but whatever you put in the there, still get's used. That's because the ActionListener implicitly call it for you.
The same is true with painting. In the Swing painting process, there is a paint chain that Swing uses to paint components. Along the way paint is called somewhere. So just like actionPerformed, you can override paint and it will get implicitly called for you.
#Override
public void paint(Graphics g) {
super.paint(g);
}
The Graphics object passed to the method is the graphics context that Swing will use for the painting. You can look at the Graphics API to see the methods you can use. You can use drawOval to draw a circle
#Override
public void paint(Graphics g) {
super.paint(g);
g.drawOval(x, y, width, height);
}
Now here's the thing. You don't actually want to override paint. In the tutorials linked above, some of the examples will use applets and override paint, but you shouldn'y paint on top level containers like JFrame or JApplet. Instead paint on a JPanel or JComponent and just add it the JFrame. When you do paint on JPanel or JComponent, you'll instead override paintComponent (which also gets called along the paint chain), instead of paint
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawOval(x, y, width, height);
}
You see how I used variables for the drawOval method. The x is the x location from the top-let of the screen, and y and the y point. width and height are width and height of the circle. The great thing about using variables is that their values can be changed at runtime.
That's where the animation comes to play. As pointed out, you an use a javax.swing.Timer
The basic construct is
public Timer(int delay, ActionListener listener) {
}
The delay is the milliseconds to delay each call to the listener. The listener will have your actionPerformed call back that will do what's inside, every delay milliseconds. So what you can do, is just change the x from the drawOval and repaint(), and it will animate. Something like
Timer timer = new Timer(40, new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
x += 5;
repaint();
}
});
timer.start();
The timer code you can just put in the constructor. That's probably simplest explanation I can give. Hope it helps.
Don't forget the to see Custom Painting and Grapics2D for more advance topics on graphics. Also see some example of timers and animation here and here and here and here and here
Also avoid using null layouts. See Laying out Components Within a Container to learn how to use layout managers, as should be done with Swing apps.
Take a look at the Swing tutorial on Custom Painting.
The example shows you how to do painting. If you want animation, then you would use a Swing Timer to schedule the animation. The tutorial also has a section on How to use a Swing Timer.
Put the two tutorial together and you have a solution.
There are any number of ways to achieve this.
Start by taking a look at:
Performing Custom Painting
2D Graphics
For details about how painting in Swing is done.
Animation is not as simple as just pausing a small period of time and then repainting, theres acceleration and deceleration and other concepts that need to be considered.
While you could write your own, that's not a small task, a better solution might be to use a pre-existing engine, for example...
Then take a look at:
Timing Framework
Trident
java-universal-tween-engine
Which are all examples of animation engines in Swing. While I prefer the Timing Framework as it provides me with a lower level API, this is a personal opinion. Both Trident and the JUWE seem to be geared more towards component/property based animation (which the Timing Framework can do if you want to build some of the feature sets up)
I created a simple animation with two rockets blasting off. The full eclipse project is here: https://github.com/CoachEd/JavaExamples/tree/master/RaceToSpace. Here's a screenshot:

Using mouse Motion Listener on JButton?

hii
I have used Image as JButton for set in to panel
but now i want to use mouse motion listener actions on that image
for that purpose what can i do
following is the code for image
JButton buttonForPicture = new JButton();
buttonForPicture.setBorder(new EmptyBorder(0, 0, 0, 0));
buttonForPicture.setOpaque(false);
buttonForPicture.setIcon(new ImageIcon("/Users/hussainalisyed/Documents/Images/pic9.jpg"));
panel5.add(buttonForPicture,BorderLayout.CENTER);
is there any another way to do that
or
...
I'm not sure exactly what you're asking?
Your button is like any other JButton:
buttonForPicture.addMouseMotionListener(new MouseMotionListener() {
#Override
public void mouseMoved(MouseEvent e) {
}
#Override
public void mouseDragged(MouseEvent e) {
}
});
That catches movement events for the whole button, not just the image.
Read the JButton API there are methods to change the icon on a mouse rollover, if thats what you are trying to do. Search the API for methods containing "icon" to see what your options are.
If you just want to know how to write a MouseMotionListener, then read the section from the Swing tutorail on How to Write a Mouse Motion Listener for a working example.

Categories