Animation sequence in JFrame
Alright, there are a lot of problems in your code, let's step into each of them:
You have a lot of spaces between lines, that makes your code a lot larger and harder to read
You haven't indented your code correctly (see the last
}
on your code, it's at the same level than the others; yourfor
loops, etc), it makes the code so much harder to read and understand as wellYou're creating a
JFrame
but extendingJLabel
, I'm not sure why you're doing this, if you're doing it so you can use thepaintComponent()
method, it's not necessary, on my code you can see how you can do it w/o extending anyComponent
If you haven't read the Swing
Timer
docs you should click that link and read what theActionListener
parameter does. In this case, we're going to use this listener to call therepaint()
method and update ourcurrentImage
(ornextImage
in the code below) and change the image accordingly. You failed to do this.You were creating more than 1
Timer
too, you created 6 here! All of them new but they had no action to do when the time finishedfor (int i=0; i < nekopics.length; i++) {
timer = new Timer(1000, this);
timer.setInitialDelay(0);
timer.start();
currentimg = nekopics[i];
repaint();
}You're changing unnecessarily the visibility of the
paintComponent()
method topublic
fromprotected
However I want to congratulate you for not using a null
layout and following the recommendations I made on the comments above.
And finally the code that changes one image for another inside a Timer
is the following, you can copy-paste it and change the image's names so you can see how it works.
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileInputStream;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class ImageSequence {
private JFrame frame;
private JPanel pane;
private Timer timer;
private int nextImage = 0;
private String[] images = {"tokyo", "tokyo2", "starwars"};
private Image img = null;
public static void main (String args[]) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new ImageSequence().createAndShowGui();
}
});
}
public void createAndShowGui() {
frame = new JFrame("Image Sequence");
timer = new Timer(1000, listener);
pane = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
try {
img = ImageIO.read(new FileInputStream("/home/jesus/Pictures/" + images[nextImage] + ".jpg"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
g.drawImage(img , 0, 0, 200, 200, this);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
};
timer.start();
frame.getContentPane().add(pane);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
ActionListener listener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
System.out.println(nextImage);
nextImage = nextImage < images.length - 1 ? nextImage + 1 : 0;
System.out.println(nextImage);
pane.repaint();
}
};
}
Animated Sprites with Java Swing
First of all you have a lot of white spaces between each line, it makes it hard to read the code.
Yes, you could try using a Swing
Timer
, here is an example and another example and another example.You have an empty
catch
block which is not secure, at least do this:catch (IOException e){
e.printStackTrace();
}You're not placing your program on the Event Dispatch Thread (EDT) to solve it just change your
main
method as follows:public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
//Your constructor here
}
});
}You're extending
JFrame
but not making use of the frame generated by it, and at the same time you're creating an instance of aJFrame
, remove theextends JFrame
in your code. Related reading: Java Swing using extends JFrame vs calling it inside of classInstead of calling
frm1.setSize(400, 400);
override thePainel1
'sgetPreferredSize()
method to return a newDimension
of400, 400
and callfrm1.pack()
@Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}The animation processing is too fast!
It's not the animation processing too fast, but the
for
loop prevents the GUI to be painted before it ends, that's why you're only seeing the last sprite being painted.
With all the above points in mind, you now can have your code as follows, which includes the use of a Swing Timer and the above recommendations already included:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class Sprites {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frm1 = new JFrame();
Painel1 pn1 = new Painel1();
frm1.getContentPane().add(pn1);
frm1.pack();
frm1.setVisible(true);
frm1.setLocationRelativeTo(null);
frm1.setResizable(false);
frm1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
});
}
}
class Painel1 extends JPanel {
int[][] spriteSheetCoords = { { 8, 10, 119, 129 }, { 138, 10, 118, 130 }, { 267, 10, 118, 132 },
{ 402, 11, 113, 132 }, { 538, 12, 106, 134 }, { 671, 13, 103, 133 }, { 804, 12, 102, 132 },
{ 23, 161, 100, 134 }, { 157, 162, 96, 134 }, { 287, 159, 95, 135 }, { 418, 158, 95, 133 },
{ 545, 159, 99, 133 }, { 673, 159, 102, 134 }, { 798, 158, 108, 130 }, { 9, 309, 116, 126 },
{ 137, 309, 118, 127 }, { 274, 310, 110, 128 }, { 412, 311, 102, 129 }, { 541, 312, 103, 130 },
{ 671, 312, 104, 131 }, { 806, 312, 98, 132 }, { 29, 463, 94, 135 }, { 155, 462, 98, 135 },
{ 279, 461, 104, 135 }, { 409, 461, 106, 135 }, { 536, 461, 109, 135 }, { 662, 461, 112, 133 } };
int i = 0;
BufferedImage img;
private ActionListener actionListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
i++;
if (i == spriteSheetCoords.length) {
i = 0;
}
revalidate();
repaint();
}
};
public Painel1() {
Timer timer = new Timer(50, actionListener);
timer.setInitialDelay(0);
timer.start();
setBackground(Color.yellow);
try {
img = ImageIO.read(new File("/home/jesus/Pictures/tokyo.jpg"));
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void paintComponent(Graphics g) {
Image subSprite;
super.paintComponent(g);
subSprite = img.getSubimage(spriteSheetCoords[i][0], spriteSheetCoords[i][1], spriteSheetCoords[i][2], spriteSheetCoords[i][3]);
g.drawImage(subSprite, 140, 120, null);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
}
As you can see the Timer
has a delay of 50ms to make the transition of the sprites smoother, you can adjust it as you please.
visualizing JPanel change within a loop
Don't use a loop. Swing will only repaint the frame once the entire loop has finished executing.
Instead you need to use a Swing Timer. When the Timer fires you invoke your logic. Read the section from the Swing tutorial on How to Use Swing Timers.
Here is a simple example of a Timer that simply displays the time every second: Update a Label with a Swing Timer
Also, don't remove/add panels. Instead you can use a Card Layout
and sway the visible panel. Again read the tutorial on How to Use CardLayout.
How do you display a looping statement in a text box?
You should build the full text in a StringBuilder
:
int num = Integer.parseInt(userText.getText());
StringBuilder buf = new StringBuilder();
for (i = 1; i <= num; i++) {
if (num % i == 0)
buf.append(" ").append(i);
}
textFieldAns.setText(buf.substring(1));
Replacing an image once through timer
You're never initializing timerListener
private ActionListener timerListener;
Inside your constructor you have to call (With Java 8 lambdas):
timerListener = e -> {
react = new ImageIcon("reactCircle.png");
main.setIcon(react);
}
Or (Java 7 and lower):
timerListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
react = new ImageIcon("reactCircle.png");
main.setIcon(react);
}
}
And don't forget to call timerListener.stop()
once the timer has fired, so that you don't keep computing more times
From Andrew Thompson's comment below:
As you only want to replace the image once, call timerListener.setRepeats(false)
on your constructor. Check the docs for more information about it.
How to make a 4x4 sudoku solver in java
Here's a page that explains this with a 4x4 grid. By the way, you really should try Googling before asking a question here. I just searched "sudoku solver example program" to find this.
http://www.mathworks.com/company/newsletters/articles/solving-sudoku-with-matlab.html
Creating a Countdown Timer inside of a JFrame
Here's another way to do it. Please note this code is not test.
private void initialize() {
...
new Thread() {
int counter = 10;
public void run() {
while(counter >= 0) {
lblNewLabel.setText("Test" + (counter--));
try{
Thread.sleep(1000);
} catch(Exception e) {}
}
}
}.start();
}
Related Topics
Convert Localdate to Localdatetime or Java.Sql.Timestamp
Hibernate Table Not Mapped Error in Hql Query
@Onetomany List<> VS Set<> Difference
Annotations from Javax.Validation.Constraints Not Working
How to Use Concurrentlinkedqueue
How Does the Jvm Ensure That System.Identityhashcode() Will Never Change
Collection Interface VS Arrays
Why Shouldn't Java Enum Literals Be Able to Have Generic Type Parameters
Java Try/Catch/Finally Best Practices While Acquiring/Closing Resources
Tomcat - Maxthreads VS Maxconnections
How to Configure Hibernate Config File for SQL Server
Why Does Intellij Give Me "Package Doesn't Exist" Error
Find the Most Popular Element in Int[] Array
Jsoup Cookies for Https Scraping
Java Error: Cannot Make a Static Reference to the Non-Static Method