g.drawString fails on MIDP 2.0 phones - java

I made a simple ( I thought) demo that plays music in the background while an animated 128x128 candle Sprite flickers in the background and text is displayed and refreshed every 2 seconds with a TimerTask. This demo works fine in the emulator (MicroEmulator), but failed on all counts but the music on both my LG500G and Motorola EM326G phones. Because they both failed in the same way, I suspect I may be doing something wrong. Neither of the phones will even display any text whatsoever using g.drawString(). Either my phones are severely limited, or I am writing something horribly weirdly:(note I have commented out the code about the Sprite because only one frame displayed)
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.*;
import javax.microedition.media.*;
public class GardenGameCanvas extends GameCanvas implements Runnable {
private Image bgImage;
private Sprite bgSprite;
private boolean stop;
private LayerManager manager;
private int a = 0;
private String[] list;
textTask aTextTask;
Player midiplayer = null;
public GardenGameCanvas() {
super(false);
}
public void start() {
list = new String[] { "As you watch this candle", "It flickers.",
"Against the gale of Life", "It's flickering.", "Persistently" };
try {
midiplayer = Manager.createPlayer(
getClass().getResourceAsStream("/pavane_defunte_mb.mid"),
"audio/midi");
midiplayer.prefetch();
midiplayer.start();
} catch (Exception e) {
}
//try {
//bgImage = Image.createImage("/flame.png");
//bgSprite = new Sprite(bgImage, 128, 128);
//manager = new LayerManager();
//manager.append(bgSprite);
//} catch (IOException ioex) {
// System.err.println(ioex);
//}
stop = false;
Thread runner = new Thread(this);
runner.start();
}
public void run() {
aTextTask = new textTask();
new Timer().schedule(aTextTask, 0, 2000);
while (!stop) {
update(getGraphics());
try {
Thread.currentThread().sleep(30);
} catch (Exception e) {
}
}
}
private void update(Graphics g) {
g.setColor(0xFFFFFF); // white
g.fillRect(0, 0, getWidth(), getHeight());
// bgSprite.setPosition(0, 0);
//bgSprite.nextFrame();
//bgSprite.paint(g);
buildGame(g);
//manager.paint(g, 0, 0);
flushGraphics();
}
private void buildGame(Graphics g) {
g.setColor(0xFFFFFF);
g.fillRect(0, getHeight() / 2, getWidth(), 75);
g.setColor(0x000000);
g.drawString(list[a], 0, getHeight()/2, Graphics.LEFT);
flushGraphics();
}
public class textTask extends TimerTask {
public textTask() {
}
public void run() {
a++;
if (a > 4) {
a = 0;
}
}
}
}

I suspect the error is caused by your multiple calls to flushGraphics()
Your first call to flushGraphics will flush the graphics and display it (except it doesn't get a chance to display anything because of your second call to flushGraphics).
Your second call to flushGraphics right after will flush nothing to the screen, resulting in nothing being displayed.
Try this instead:
(Same code as above, simply with one of the calls to flushGraphics commented out).
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.*;
import javax.microedition.media.*;
public class GardenGameCanvas extends GameCanvas implements Runnable {
private Image bgImage;
private Sprite bgSprite;
private boolean stop;
private LayerManager manager;
private int a = 0;
private String[] list;
textTask aTextTask;
Player midiplayer = null;
public GardenGameCanvas() {
super(false);
}
public void start() {
list = new String[]{"As you watch this candle", "It flickers.",
"Against the gale of Life", "It's flickering.", "Persistently"};
try {
midiplayer = Manager.createPlayer(
getClass().getResourceAsStream("/pavane_defunte_mb.mid"),
"audio/midi");
midiplayer.prefetch();
midiplayer.start();
} catch (Exception e) {
}
//try {
//bgImage = Image.createImage("/flame.png");
//bgSprite = new Sprite(bgImage, 128, 128);
//manager = new LayerManager();
//manager.append(bgSprite);
//} catch (IOException ioex) {
// System.err.println(ioex);
//}
stop = false;
Thread runner = new Thread(this);
runner.start();
}
public void run() {
aTextTask = new textTask();
new Timer().schedule(aTextTask, 0, 2000);
while (!stop) {
update(getGraphics());
try {
Thread.currentThread().sleep(30);
} catch (Exception e) {
}
}
}
private void update(Graphics g) {
g.setColor(0xFFFFFF); // white
g.fillRect(0, 0, getWidth(), getHeight());
// bgSprite.setPosition(0, 0);
//bgSprite.nextFrame();
//bgSprite.paint(g);
buildGame(g);
//manager.paint(g, 0, 0);
flushGraphics();
}
private void buildGame(Graphics g) {
g.setColor(0xFFFFFF);
g.fillRect(0, getHeight() / 2, getWidth(), 75);
g.setColor(0x000000);
g.drawString(list[a], 0, getHeight() / 2, Graphics.LEFT);
//flushGraphics(); // Don't call flushGraphics here, because it'll be called twice then.
}
public class textTask extends TimerTask {
public textTask() {
}
public void run() {
a++;
if (a > 4) {
a = 0;
}
}
}
}

Related

Java animation:can't see anything

I am doing animation with Java and I'm using NetBeans. My applet has started but I don't see anything in the applet viewer? Can anybody see any problem with my code and this is my first programming course as U can see =)! Thanks for advance!!
Problem.1 Do animation with 10 gif pictures by using MediaTracker,addImage and thread.sleep.
(Code)
import java.applet.Applet;
import java.awt.*;
public class Animaatio extends Applet implements Runnable
{
Image images[] = null;
MediaTracker tracker = null;
Thread animaatio;
Graphics g;
#Override
public void init()
{
tracker = new MediaTracker(this);
images = new Image[10];
for (int i=0; i < 10; i++)
{
images[i] = getImage( getCodeBase(),"T" + (i+1) + ".gif");
tracker.addImage(images[i],0);
}
try{
tracker.waitForAll();
}catch (InterruptedException e){}
}
#Override
public void start() {
if (animaatio == null) {
animaatio = new Thread(this);
animaatio.start();
}
}
#Override
public void paint (Graphics g)
{
super.paint(g);
g.drawImage(images[10], 0, 0, this);
}
#Override
public void run(){
while(true){
repaint();
try{
Thread.sleep(1000);
}
catch (InterruptedException e) {}
}
}
}

Swing java animation only works when not called from listener

I am trying to create an function with an animation in java(swing). I want to create a "stack" of cards and then be able to draw one card from the stack using a method. The card i draw should then be "fliped" to reveal the front side.
This is working fine unless when I am trying to draw a new card using listeners.
I start the program by building the stack then drawing one card. Then I have a button that draws a new card(actionlistener). The animation does not show however i can see that the stack decreases by one card. I have tried to create a gif to show the problem.
Gif file showing the problem http://people.dsv.su.se/~chra4852/gif.gif
My best guess would be that it has something to do with threads or the EDT?
Here is the code(I have removed the use of the Scalr class since its not important) :
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.*;
// import org.imgscalr.Scalr; Removed for Stackoverflow
public class Test extends JFrame{
public static JPanel cardPanel = new JPanel();
public static JLayeredPane layerPane = new JLayeredPane();
private final CardFlipp cardFlipp;
Test() {
cardFlipp = new CardFlipp();
this.setLayout(new BorderLayout());
layerPane.setPreferredSize(new Dimension(700, 300));
add(cardPanel, BorderLayout.CENTER);
JButton newJButton = new JButton("New card");
newJButton.addActionListener(new drawNewCardListener());
add(newJButton, BorderLayout.SOUTH);
setSize(800,400);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
Point pos = new Point(10,30);
cardFlipp.createCardFlipp(30, pos, layerPane, cardPanel);
System.out.println("Now running on thread " + Thread.currentThread());
try {
Thread.sleep(3000);
} catch (InterruptedException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
cardFlipp.displayCard("http://imgi.se/image.php?di=IYW9");
}
public static void main(String[] args){
new Test();
}
class drawNewCardListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent ae) {
System.out.println("Now running on thread " + Thread.currentThread());
cardFlipp.displayCard("http://imgi.se/image.php?di=IYW9");
}
}
}
class CardFlipp extends JPanel{
private Point origin;
private BufferedImage icon;
private JLayeredPane lPane;
private JPanel jPanel;
private int lastCardDisplayedId = 0;
public void createCardFlipp(int amount, Point pos, JLayeredPane lPaneRef, JPanel jPanelRef) {
origin = pos;
setIcon("http://imgi.se/image.php?di=HPCJ");
lPane = lPaneRef;
jPanel = jPanelRef;
for(int i = amount; i > 0; i--) {
origin.x += 3;
lPane.add(new Card(origin, icon, i), new Integer(amount-i));
jPanel.add(lPane);
lPane.revalidate();
lPane.repaint();
try {
Thread.sleep(80);
} catch (InterruptedException ex) {
Logger.getLogger(CardFlipp.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public void displayCard(String fileUrl) {
Card c = (Card) lPane.getComponent(0);
if(lastCardDisplayedId == 0) {
origin = new Point(c.getBounds().x + 370, c.getBounds().y);
}
int cardId = c.getId();
setIcon(fileUrl);
c.flippCardRight(lastCardDisplayedId);
lPane.remove(c);
if(lastCardDisplayedId != 0) {
for(int i = 0; i < lPane.getComponentCount(); i++) {
c = (Card) lPane.getComponent(i);
if(c.getId() == lastCardDisplayedId) {
lPane.remove(c);
break;
}
}
}
lPane.repaint();
lPane.add(new Card(origin, icon, cardId), new Integer(0));
jPanel.add(lPane);
lastCardDisplayedId = cardId;
}
private void setIcon(String urlPath) {
try {
URL url = new URL(urlPath);
icon = ImageIO.read(url);
} catch (IOException e) {
System.err.println(e);
System.exit(-1);
icon = null;
}
}
}
class Card extends JComponent {
private BufferedImage buffImg;
private ImageIcon iconImg;
private final int id;
public Card(Point origin, BufferedImage img, int count) {
buffImg = img;
iconImg = new ImageIcon(buffImg);
setBounds(origin.x,origin.y,iconImg.getIconWidth(),iconImg.getIconHeight());
this.id = count;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(iconImg.getImage(), 0, 0, this);
}
public void flippCardRight(int count) {
int x = count * 3;
int newPosX = getBounds().x + iconImg.getIconWidth() + 20;
while(getBounds().x < newPosX + x) {
setBounds(getBounds().x+5,getBounds().y,iconImg.getIconWidth(),iconImg.getIconHeight());
wait10MiliSec();
}
// Removed to not need the scalr class
//int minimize = 10;
//while(iconImg.getIconWidth() > minimize) {
//buffImg = Scalr.resize(buffImg, Scalr.Method.SPEED, Scalr.Mode.FIT_EXACT, //iconImg.getIconWidth()-minimize, iconImg.getIconHeight(), Scalr.OP_ANTIALIAS);
//iconImg = new ImageIcon(buffImg);
//setBounds(getBounds().x+minimize-1,getBounds().y,iconImg.getIconWidth(),iconImg.getIconHeight());
//wait10MiliSec();
//}
}
private void wait10MiliSec() {
try {
Thread.sleep(10);
} catch (InterruptedException ex) {
Logger.getLogger(Card.class.getName()).log(Level.SEVERE, null, ex);
}
}
public int getId() {
return this.id;
}
public int getImgWidth() {
return iconImg.getIconWidth();
}
}
Question = What can be done so that the animation is shown regardless if its called from the listener?
using timer would be the solution for you:) Example of a similar problem that guy had a similar problem, you can read the answers he received. good luck

LayerUI appears only after blocking method is done

I created a little indication of loading using a custom subclass of LayerUI.
The list is and arraylist of StringWorker subclass. Its get method is a blocking call so I assume that's the problem just don't know how to fix it. The layer starts a timer and as far as I know, timers are executed in their own thread so the blocking get shouldn't intefere.
loadingLayer.setVisible(true);
lockComponents();
for(int i = 0; i < list.size(); i++) {
try {
System.out.println("About to check "+i);
if(list.get(i).get() == null) {
}
} catch (InterruptedException e1) {
e1.printStackTrace();
} catch (ExecutionException e1) {
e1.printStackTrace();
}
}
unlockComponents();
loadingLayer.setVisible(false);
The "loadingLayer" appears only after all this code is done.
LoadingLayerUI class:
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JComponent;
import javax.swing.Timer;
import javax.swing.plaf.LayerUI;
public class LoadingLayerUI extends LayerUI<JComponent> implements ActionListener {
/**
*
*/
private static final long serialVersionUID = 827885062549399916L;
private boolean isShowing;
private Timer timer;
private String text;
#Override
public void paint(Graphics g, JComponent jc) {
super.paint(g, jc);
if(!isShowing)
return;
Graphics2D g2 = (Graphics2D) g.create();
int w = jc.getWidth();
int h = jc.getHeight();
g2.setComposite(AlphaComposite.getInstance(
AlphaComposite.SRC_OVER, .7f));
g2.setPaint(Color.LIGHT_GRAY);
g2.fillRect(0, 0, w, h);
g2.setColor(Color.BLACK);
Font font = new Font("Sans-Serif",Font.BOLD, 20);
int width = g2.getFontMetrics(font).stringWidth("Loading");
g2.setFont(font);
if(text != null)
g2.drawString(text, (w-width)/2, h/2);
g2.dispose();
jc.repaint();
}
public void setVisible(boolean set) {
this.isShowing = set;
if(isShowing) {
timer = new Timer(200, this);
timer.start();
}
else {
timer.stop();
}
}
#Override
public void actionPerformed(ActionEvent e) {
if(!isShowing && timer.isRunning())
timer.stop();
if(text == null || text.equals("Downloading...")) {
text = "Downloading";
}
else
text += ".";
}
}
When you use Swing you should make your long running tasks in a separate thread.
Here is the tutorial: http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html
I moved the code which uses the blocking method get to a separate thread and made it call a method when it was done. Now it seems to work. The layer appears and disappears when needed.
loadingLayer.setVisible(true);
new Thread(new Runnable() {
public void run() {
for(int i = 0; i < list.size(); i++) {
try {
if(list.get(i).get() == null) {
}
} catch (InterruptedException e1) {
e1.printStackTrace();
} catch (ExecutionException e1) {
e1.printStackTrace();
}
}
downloadComplete();
}
}).start();
The downloadComplete method simply hides the layer.

I'm working on a Java Appet that fades an image then shows it again in a different spot in the applet window [duplicate]

This question already has answers here:
How do I fade an image in swing?
(3 answers)
Fade in and fade out effect in java applet
(3 answers)
Closed 9 years ago.
The applet is working fine, in showing the image and the text, I would like the image to fade where it is currently but reappear in another spot, then reload in the same spot later.
I would also like to fade and move the test as well,
Here's my code so far, forgive me I'm a newbie!
import java.applet.*;
import java.awt.*;
import java.awt.image.*;
import java.net.*;
public class FadeImage extends Applet {
Image img, faded;
int level, sign;
MediaTracker tracker;
AlphaFilter f;
FilteredImageSource fis;
String msg2 = "University of Utah Football";
public void init() {
setBackground(Color.red);
setForeground(Color.black);
level = 0;
sign = 15;
tracker = new MediaTracker(this);
try {
img = getImage(new URL(getDocumentBase(), "uofu.jpg"));
tracker.addImage(img,0);
tracker.waitForID(0);
}
catch (Exception e) {
e.printStackTrace();
}
f = new AlphaFilter();
f.setLevel(level);
fis = new FilteredImageSource(img.getSource(), f) ;
FadeThread ft = new FadeThread();
ft.delayedFading(this, 20);
ft.start();
}
public void paint(Graphics g) {
Font myFont = new Font("Times New Roman", Font.BOLD, 24);
g.setFont(myFont);
g.setColor(Color.red);
g.drawString(msg2, 10, 465);
if (faded != null) {
g.drawImage(faded,0,0,this);
Font myFont2 = new Font("Times New Roman", Font.BOLD, 33);
g.setFont(myFont2);
setBackground(Color.black);
setForeground(Color.white);
g.setColor(Color.white);
g.drawString("Get Season tickets now!", 10, 490);
}
}
public void fadeIt() {
Graphics g = this.getGraphics();
level += sign;
if (level < 0) {
level=0;
sign = sign * -1;
}
if (level > 255) {
level=255;
sign = sign * -1;
try {
Thread.sleep(1000);
}
catch (Exception e) {}
}
f.setLevel(level);
if (faded != null) faded.flush();
faded = this.createImage(fis);
tracker.addImage(faded,0);
try {
tracker.waitForID(0);
}
catch (Exception ex) {
ex.printStackTrace();
}
repaint();
}
class FadeThread extends Thread {
FadeImage fadeApplet;
int delay;
public void delayedFading(FadeImage f, int delay) {
this.fadeApplet = f;
this.delay = delay;
}
public void run() {
while (true) {
try {
sleep(delay);
fadeApplet.fadeIt();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
}
class AlphaFilter extends RGBImageFilter {
private int level;
public AlphaFilter() {
canFilterIndexColorModel = true;
}
public void setLevel(int lev) {
level = lev;
}
public int filterRGB(int x, int y, int rgb) {
int a = level * 0x01000000;
return (rgb & 0x00ffffff) | a;
}
}
}

Frame refreshing issue

I am trying to create a panel with changing pictures.
This is my panel:
public class AdvertisementPanel extends JPanel {
private BufferedImage image;
private ArrayList<String> pictures;
private int index = 0;
public AdvertisementPanel(String... pics) {
pictures = new ArrayList<String>(Arrays.asList(pics));
Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(
new Runnable() {
#Override
public void run() {
changeImage();
}
}, 0, 5, TimeUnit.SECONDS);
}
public void paint(Graphics g) {
g.drawImage(image, 0, 0, null);
}
private void changeImage() {
String name = pictures.get(index);
try {
File input = new File(name);
image = ImageIO.read(input);
index++;
index %= pictures.size();
} catch (IOException ie) {
Logger.getLogger().log(Level.SEVERE,
"No adds found in given path: " + name);
}
}
I have a frame that holds the panel, but no pictures are shown.
Tried to repaint periodically from the frame - caused some funny, yet unwanted results...
Any ideas why? What am I doing wrong? How should I refresh the frame's components?
you need to repaint each time you change the image.
Oh, and it should be done by the swing event handling thread:
Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(
new Runnable() {
#Override
public void run() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
changeImage();
repaint();
}
};
}
}, 0, 5, TimeUnit.SECONDS);
UPDATE To correct a few other issues
public class AdvertisementPanel extends JPanel {
private BufferedImage image;
private ArrayList<String> pictures;
private int index = 0;
public AdvertisementPanel(String... pics) {
pictures = new ArrayList<String>(Arrays.asList(pics));
Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(
new Runnable() {
#Override
public void run() {
changeImage();
}
}, 0, 5, TimeUnit.SECONDS);
}
private void changeImage() {
final BufferedImage img = nextImage();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
image = img;
repaint();
}
});
}
public void paint(Graphics g) {
if (image != null) {
g.drawImage(image, 0, 0, null);
}
}
private BufferedImage nextImage() {
String name = pictures.get(index);
try {
index++;
index %= pictures.size();
File input = new File(name);
return ImageIO.read(input);
} catch (IOException ie) {
Logger.getLogger("").log(Level.SEVERE,
"No adds found in given path: " + name);
return null;
}
}
}

Categories