Needing JAVA help in animation - java

I'm new in Java (still learning) all the other works have gone well but only this animation gives my headache and the coffee won't even help=(!
I should make an animation of Javaman (10 gif pictures named as T1, T2,...T10) I should use Thread, MediaTracker-class and addImage-method. Then I should specify the speed of the animation by using sleep-method (I used join-method if that's right??).
(MY JAVA CODE GOES LIKE THIS)
import java.applet.Applet;
import java.awt.*;
public class Animaatio extends Applet implements Runnable {
Image[] images = null;
MediaTracker tracker = null;
int current = 0;
Thread animThread;
#Override
public void init() {
// Creating a new media tracker, to track loading images
tracker = new MediaTracker(this);
// Creating an array of ten images
images = new Image[10];
// Downloading the images
for (int i = 0; i < 10; i++) {
// Loading the images
images[i] = getImage(getCodeBase(), (i + 1) + "T.gif");
tracker.addImage(images[i], 0);
}
try {
tracker.waitForAll();
} catch (InterruptedException e) {
}
}
#Override
public void start() {
if (animThread == null) {
animThread = new Thread(this);
animThread.start();
}
try {
animThread.join();
} catch (InterruptedException e) {
}
}
#Override
public void paint(Graphics g) {
g.drawImage(images[current++], 0, 0, this);
}
#Override
public void run() {
while (true) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
}
}
}
The problem is that I don't see any animation just an empty applet viewer which just keeps running. Problem might be caused if the images are storaged in the wrong place? If someone could wreally help me, I would be really thankful for my knight=).

Related

Performance issue displaying JFreeChart points, when running in the EDT

Background:
A well-known Swing best-practice requirement is that code that
interacts with the Swing framework must also execute in EDT (Event
Dispatch Thread).
I thus changed my code to have my JFreeChart-based updates to run in EDT.
However, a complete chart display task that usually took about 7 minutes to finish on a “normal” thread, become a several hours task when running in EDT!
What am I doing wrong? Did I misunderstood the Swing Concurrency lesson? Do I really have to run org.jfree.data.time.TimeSeries.addOrUpdate(date, double) inside EDT?
Please advise!
Details:
Clicking a Swing GUI button, my program triggers a time-consuming task.
Basically, it reads a (large) file with pair-values (date, double) and then shows them by using the JFreeChart framework.
Because this is a time-consuming task, while reading and displaying data, a JProgreessBar shows user the progress status in foreground, while the chart is updated in background (user is still able to visually see every chart update, behind the progress bar).
This worked fine, until I decided to review the code to have my chart data being updated and displayed inside Swing EDT. Then, a complete task that usually took about 7 minutes to finish, started to take several hours to complete!
Here’s the list of threads I’m using:
1) Since the task is triggered by a Swing Button Listener, it is running in EDT. The JProgressBar is also running in this same thread;
2) While showing the JProgressBar, a second (“normal”) thread is created and executed in the background. This is where the heavy work is done.
It includes the update of the JProgressBar status on the other thread (by calling JProgressBar.setvalue()) and the update of my JFreeChart chart (by calling TimeSeries.addOrUpdate(date, double), which automatically updates a org.jfree.chart.ChartPanel).
Updating the chart in my second (“normal”) thread usually took about 7 minutes to finish. Without any noticeable issue.
However, knowing that most Swing object methods are not "thread safe" and ChartPanel is just a Swing GUI component for displaying a JFreeChart object, I decided to run my chart update code TimeSeries.addOrUpdate(date, double) inside EDT.
Still running in my second “normal” thread, I tested with the following asynchronous code:
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
TimeSeries.addOrUpdate(date, double);
}
});
but I realized my JProgressBar would reach 100% much before the chart was updated.
I guess this was expected as displaying chart data is much slower than getting and processing the data.
I then tried following synchronous code:
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
TimeSeries.addOrUpdate(date, double);
}
});
} catch (InvocationTargetException | InterruptedException e) {
e.printStackTrace();
}
And this is where I found the performance issue: now a complete task that used to take about 7 minutes to finish, started to take hours to complete!
So, my question is:
What am I doing wrong? Did I misunderstood the Swing Concurrency lesson? Do I really have to run TimeSeries.addOrUpdate(date, double) inside EDT?
Please advise!
UPDATE:
The complete code would be too large to show here, but you can find a code snapshot below.
Perhaps, the only thing noticeable about the code is that I use Reflection. This is because I use a generic ProgressBar Class that invokes in background whatever class I send it as an argument (though this is not clearly shown in the snapshot below).
//BUTTON LISTENER (EDT)
public void actionPerformed(ActionEvent arg0) {
new Process_offline_data();
}
public Process_offline_data() {
//GET DATA
String[][] data = get_data_from_file();
//CREATE PROGRESS BAR
int maximum_progressBar = data.length;
JProgressBar jpb = init_jpb(maximum_progressBar);
//JDIALOG MODAL WINDOW
JDialog jdialog = create_jdialog_window(jpb);
Object class_to_invoke_obj = (Object) new Show_data_on_chart();
String main_method_str = "do_heavy_staff";
Runnable r = new Runnable() {
public void run() {
//REFLECTION
Method method = null;
try {
method = class_to_invoke_obj.getClass().getDeclaredMethod(main_method_str, JProgressBar.class, String[][].class);
} catch (NoSuchMethodException | SecurityException e1) {
e1.printStackTrace();
jdialog.dispose(); //UNBLOCKS MAIN THREAD
return;
}
try {
method.invoke(class_to_invoke_obj, jpb, data);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e1) {
e1.printStackTrace();
jdialog.dispose(); //UNBLOCKS MAIN THREAD
return;
}
//----------------
jdialog.dispose(); //UNBLOCKS MAIN THREAD
}
};
new Thread(r).start();
//----------------
//THIS IS STILL EDT
jdialog.setVisible(true); //BLOCKS HERE UNTIL THE THREAD CALLS jdialog.dispose();
}
public class Show_data_on_chart {
public void do_heavy_staff(JProgressBar jpb, String[][] data) {
TimeSeries time_series = get_TimeSeries(); //JFreeChart datamodel
int len = data.length;
for (int i=0; i<len; i++) {
jpb.setValue(i+1);
Millisecond x_axys_millisecond = convert_str2date(data[i][0]);
Double y_axys_double = convert_str2double(data[i][1]);
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
//AUTOMATICALLY UPDATES org.jfree.chart.ChartPanel
time_series.addOrUpdate(x_axys_millisecond, y_axys_double);
}
});
} catch (InvocationTargetException | InterruptedException e) {
e.printStackTrace();
}
}
}
}
This is how i solved the problem of updating the chart.
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.data.xy.XYSeries;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;
import org.jfree.chart.plot.XYPlot;
import java.lang.reflect.InvocationTargetException;
import javax.swing.SwingUtilities;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
public class App extends ApplicationFrame {
XYSeries sin = new XYSeries("Sin");
public App(String applicationTitle, String chartTitle) {
super(applicationTitle);
JFreeChart xylineChart = ChartFactory.createXYLineChart(chartTitle, "X", "Y", new XYSeriesCollection(sin),
PlotOrientation.VERTICAL, false, true, false);
ChartPanel chartPanel = new ChartPanel(xylineChart);
chartPanel.setPreferredSize(new java.awt.Dimension(560, 367));
final XYPlot plot = xylineChart.getXYPlot();
XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer(true, false);
plot.setRenderer(renderer);
setContentPane(chartPanel);
}
public Runnable r = new Runnable() {
double x, y;
int i;
public void run() {
int steps = 69999;
for (i = 0; i < steps; i++) {
//sample plot data
x = Math.PI * 2.0 * 10.0 / ((double) steps) * ((double) i);
y = Math.sin(x);
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
if ((i % 1000) == 0) {
//adding data and redrawing chart
sin.addOrUpdate(x, y);
} else {
//adding point without redrawing of the chart
sin.add(x, y, false);
}
}
});
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//redrawing chart if all data loaded
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
sin.fireSeriesChanged();
}
});
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
public Runnable rupdate = new Runnable() {
public void run() {
while (true) {
//redrawing chart
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
sin.fireSeriesChanged();
}
});
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
//waiting for next update
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
public static void main(String[] args) {
final App chart [] = new App[1];
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
chart[0] = new App(null, null);
chart[0].pack();
RefineryUtilities.centerFrameOnScreen(chart[0]);
chart[0].setVisible(true);
}
});
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
Thread job = new Thread(chart[0].r);
job.start();
Thread job2 = new Thread(chart[0].rupdate);
job2.start();
}
}
The above code includes two solutions. You can use either of them or both. Chart can be updated during data feeding. For example every 100th point and after last poit. Eventually you can make external thread that updates chart after some time. I have used updateAndWait every time instead of updateLater.
In your code do not use reflections like that. You should make interface. For example:
public interface IHardWork {
public void do_heavy_staff(JProgressBar jpb, String[][] data);
}
and implement it on every object that do the work:
public class Show_data_on_chart implements IHardWork {
public void do_heavy_staff(JProgressBar jpb, String[][] data) {
// TODO Auto-generated method stub
}
}
then use it:
IHardWork hwObj = new Show_data_on_chart();
hwObj.do_heavy_staff(jpb, data);
hwObj = new OtherHWObj();
hwObj.do_heavy_staff(jpb, data);
Eventualy You can make a base class for it and use polymorphism.

Creating new Thread to update JLabel and setIcon() in said separate Thread

Trying to get an image from another application sending an array of bytes through socket, translating it to a BufferedImage and setting a JLabel in the GUI that updates every 3 seconds.
I tried looking it up on forums but questions regarding graphical update are recurrent to me and I never seem to get it right -- there's at least 6 update methods in java for graphical interface and every one I tried won't work.
I know the problem isn't in the connection to the client because I can easily save the image I receive with ImageIO.write() and it updates every 3 seconds to the image I was expecting to receive. I just can't have Java updating the JLabel correctly without having to go to forums and ask people. Such a complex task I guess. Here is the code: http://pastebin.com/95nMGLvZ. I am doing this project in Netbeans so there's a lot of stuff in there that is unnecessary to read as it does not directly relate to the problem.
I think the answer lies in creating a separate thread to update my JLabel from the ever-changing BufferedImage that is received from the ObjectInputStream. Anyone mind giving me a hand at this? What is better for my code? SwingWorker, Threading (wtf is setDaemon(flag)?), Runnable, Timer, invokeLater? Tried all of this. Not correctly apparently.
EDIT1:
Tried your answer immibis:
public void startRunning() {
try {
server = new ServerSocket(666, 10);
connection = server.accept();
networkStatus("Connected to " + connection.getInetAddress().getHostName());
Thread thr = new Thread(new Runnable() {
#Override
public void run() {
try {
input = new ObjectInputStream(connection.getInputStream());
} catch (IOException ex) {
JOptionPane.showMessageDialog(null, ex.toString());
}
}
});
thr.start();
System.out.println(!connection.isInputShutdown());
while (connection.isConnected()) {
try {
byte[] byteImage = (byte[]) input.readObject();
InputStream in = new ByteArrayInputStream(byteImage);
final BufferedImage bi = ImageIO.read(in);
jLabel_screen.setIcon(new ImageIcon(bi));
ImageIO.write(bi, "jpg", new File("C:\\Users\\User\\Desktop\\test.jpg"));
System.out.println("i'm working");
} catch (IOException ex) {
JOptionPane.showMessageDialog(null, ex.toString());
} catch (ClassNotFoundException ex) {
Logger.getLogger(SpyxServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
} catch (IOException ex) {
JOptionPane.showMessageDialog(null, ex.toString());
}
}
It does not work. It says byte[] byteImage = (byte[]) input.readObject(); line has a NullPointerException. The only value that can be null is the return from readObject(), meaning either the input was not initialized correctly or the connection is not synchronized. I hope it's the first option because I wouldn't know how to handle the last.
EDIT2:
Tried your answer blazetopher:
public void startRunning() throws IOException {
server = new ServerSocket(666, 10);
try {
connection = server.accept();
networkStatus("Connected to " + connection.getInetAddress().getHostName());
input = new ObjectInputStream(connection.getInputStream());
while (true) {
try {
byte[] byteImage = (byte[]) input.readObject();
InputStream in = new ByteArrayInputStream(byteImage);
final BufferedImage bi = ImageIO.read(in);
SwingUtilities.invokeLater(new Runnable() {//<-----------
#Override
public void run() {
jLabel_screen.setIcon(new ImageIcon(bi));
}
});
ImageIO.write(bi, "jpg", new File("C:\\Users\\User\\Desktop\\test.jpg"));
System.out.println("i'm working");
} catch (IOException ex) {
JOptionPane.showMessageDialog(null, ex.toString());
} catch (ClassNotFoundException ex) {
Logger.getLogger(SpyxServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
} catch (EOFException eofException) {
networkStatus("Connection Closed. :(");
} finally {
input.close();
connection.close();
}
}
Using SwingUtilities.invokeLater didn't work either. At least the program runs and can even save the image but still can't update the JLabel. Am I running out of options here?
EDIT3:
Tried Jordan's code:
#Override
public void paint(Graphics g) {
g.drawImage(biGlobal, 0, 0, null);
}
The GUI kind of crashed and was "drawing" the components just when I had my mouse cursor hovering it. When I started the code, it did not crashed (+1) but it did not draw anything, even when I try to hover the cursor into where the BufferedImage should be painted. Maybe I should add revalidate() or repaint after calling the Overwritten paint(getGraphics()) inside the startRunning() method?
EDIT4: the while(true) that the code is actually in may be the problem but when I use a SwingTimer it gets out of sync with the client and crashes after first cycle. Any alternatives to this?
Generally speaking you have a producer/consumer pattern. Something is producing images and something wants to consume images. Normally, the consumer would wait on the producer to tell it something has been produced, but in this case, we can use a observer pattern instead, having the producer notify the consumer that something was been produced (instead of waiting for it)
We need someway for the producer to communicate with the consumer...
public interface PictureConsumer {
public void newPicture(BufferedImage img);
}
You would create an implementation of this in your UI code, this would then set the icon property of the JLabel
Now, we need something to produce the images...
public class PictureProducer extends SwingWorker<Object, BufferedImage> {
private PictureConsumer consumer;
public PictureProducer(PictureConsumer consumer) {
this.consumer = consumer;
}
#Override
protected void process(List<BufferedImage> chunks) {
// Really only interested in the last image
BufferedImage img = chunks.get(chunks.size() - 1);
consumer.newPicture(img);
}
#Override
protected Object doInBackground() throws Exception {
/*
This whole setup worries me. Why is this program acting as the
server? Why aren't we pooling the image producer?
*/
try (ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(666, 10)) {
try (Socket socket = server.accept()) {
try (ObjectInputStream ois = new ObjectInputStream(socket.getInputStream())) {
// Using `while (true)` is a bad idea, relying on the fact
// that an exception would be thrown when the connection is closed is
// a bad idea.
while (!socket.isClosed()) {
// Generally, I'd discourage using an ObjectInputStream, this
// is just me, but you could just as easily read directly from
// the ByteArrayInputStream...assuming the sender was sending
// the data as a byte stream ;)
byte[] bytes = (byte[]) ois.readObject();
try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes)) {
BufferedImage img = ImageIO.read(bis);
publish(img);
}
}
}
}
}
return null;
}
#Override
protected void done() {
try {
get();
} catch (Exception e) {
e.printStackTrace();
JOptionPane.showMessageDialog(null, "Image Producer has failed: " + e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
}
}
}
See Worker Threads and SwingWorker for more details
You can a reverse example of this (where some server is producing images and a client is consuming them) here
To update your label, you want to ensure you're using the EDT thread, so use SwingUtilities.invokeLater from the code where you're receiving the BufferedImage (which would ideally be in a separate "worker" thread:
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
// Update your label here
}
});
What is it you are attempting to accomplish.there might be a better way all together.
For example replace the JLabel with a JPanel then use that JPanel paint method
#Override
public void paint(Graphics g) {
g.drawImage(Img, xcord, ycord, null);
}
Then make that JPanel implement runnable and do your updates in that run method.
JPanel class
public class GraphicsPanel extends JPanel{
private BufferedImage img;
#Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D G2D = (Graphics2D) g;
G2D.drawImage(img, 0, 0, null);
}
public void setImg(BufferedImage img) {
this.img = img;
}
}
then make sure this panel is visible from wherever you wish to call its methods.
this will look something like this
GraphicsPanel graphicsPanel = new GraphicsPanel();
boolean running;
BufferedImage srcImage;
public void run(){
while(running){
graphicsPanel.setImg(srcImage);
graphicsPanel.repaint();
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

Drawing in a bitmap sometimes gets screwedup

I have a android that draws a mandelbrot image.
I have 16 threads that each draw 1/16 part of the image, they have their own bitmap.
for(int x=0;x<xw;x++) {
for(int y=0;y<yh;y++) {
c_real=realMin+((double)(x+x1)*scaleReal);
c_imag=imagMin+((double)(y+y1)*scaleImag);
tmp=cal_pixel(c_real, c_imag, mag);
while(pause[thread]) {
try{
Thread.sleep(5);
}catch(InterruptedException ie){
}
}
plot(x,y,c[tmp], thread);
active[thread]=true;
}
dirty=true;
}
public void plot(int x, int y, int c, int myId) {
bitmap[myId].setPixel(x, y, c);
}
The run method for each piece
public void run() {
int myId=id++;
Log.i("run","Starting thread "+myId);
while(true) {
if (redraw[myId]) {
Log.i("run","redraw");
calc(myId);
redraw[myId]=false;
}
try{
Thread.sleep(100);
}catch(InterruptedException ie) {
}
}
}
I have a separate thread that 10 times a second takes the bitmaps and draws them on the canvas.
image.pause(true);
for(int i=0;i<16;i++) {
c.drawBitmap(image.getBitmap(i), (i%4)*w/4, (i/4)*h/4, null);
}
image.pause(false);
This is the thread that draws them
public void run() {
Canvas c;
while (true) {
if (run) {
if (view.dirty()) {
c = null;
try {
c = holder.lockCanvas(null);
synchronized (holder) {
view.onDraw(c);
}
} finally {
// do this in a finally so that if an exception is thrown
// during the above, we don't leave the Surface in an
// inconsistent state
if (c != null) {
holder.unlockCanvasAndPost(c);
}
}
}
try{
Thread.sleep(100);
}catch(InterruptedException ie){
}
}else{
//Log.i("Waiting the night away","Waiting the night away");
try{
Thread.sleep(1000);
}catch(InterruptedException ie){
}
}
}
}
Sometimes one or several of these pieces gest screwed up and are not drawn to the canvas, any idea why that happense.
It worked better in android 2.3.x it almost never happened, but noww in android 4.x it happens qquite often, if you want to check the program out and experience the bug here is the link https://play.google.com/store/apps/details?id=se.klockar.mandelbrotmobile

Open image file nullpointer exception

I have to change the icon of a label every 2 seconds. I have 3 pictures in src folder. To change them i use a thread. The code i wrote:
private Thread t;
private int indexIcon;
public ImageIcon[] icons = {new ImageIcon(this.getClass().getResource("orange.jpg")),
new
ImageIcon(this.getClass().getResource("cosmote.jpg")), new
ImageIcon(this.getClass().getResource("vodafone.jpg"))};
public void run() {
while (true) {
try {
Thread.sleep(2000);
if (Thread.interrupted()) {
return;
}
indexIcon++;
if (indexIcon > 2) {
indexIcon = 0;
}
jLabel8.setIcon(icons[indexIcon]);
} catch (InterruptedException ex) {
Logger.getLogger(CarteDeTelefonGUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
And in the class constructor:
t = new Thread(this);
t.start();
It works fine, but the problem is that when i run the program on a different computer it doesn't read the images, i get a nullpointer exception.
How could i solve this problem?

display.async and smooth transitions

I have got my custom widget that changes background when hover. It is working nice but I would like to have smooth transition between no background and hover background. It will work with GC.setAlpha(), but:
Display.getDefault().asyncExec(new Runnable() {
public void run() {
for (int i=0;i<255;i++) {
setBG(BGHelper(imgHover,i)); //i - alpha
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
This code wait until i == 255, but it doesn't display a smooth transition. Why?
This can not work, because as long as you are in your Code SWT will not repaint or change the component.
You should do the work in a separate Thread and call Display.asyncExec for every change.
for (int i = 0; i < 255; i++) {
final int x = i;
Display.getDefault().asyncExec(new Runnable() {
public void run() {
setBG(BGHelper(imgHover,x)); //x - alpha
}
});
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

Categories