i'm working on applet that displays a moving banner horizontally and when this text banner
reaches the right boundary of the applet window it should be appear reversed from the start of the left boundary, i write the following class to do the work, the problem is that when the text banner reaches the right banner it crashes, the applet goes to infinite loop:
import java.applet.*;
import java.awt.*;
import java.net.*;
import java.io.*;
import javax.swing.*;
/*
<applet code="banner" width=300 height=50>
</applet>
*/
public class TextBanner extends Applet implements Runnable
{
String msg = "Islam Hamdy", temp="";
Thread t = null;
int state;
boolean stopFlag;
int x;
String[] revMsg;
int msgWidth;
boolean isReached;
public void init()
{
setBackground(Color.BLACK);
setForeground(Color.YELLOW);
}
// Start thread
public void start()
{
t = new Thread(this);
stopFlag = false;
t.start();
}
// Entry point for the thread that runs the banner.
public void run()
{
// Display banner
while(true)
{
try
{
repaint();
Thread.sleep(550);
if(stopFlag)
break;
} catch(InterruptedException e) {}
}
}
// Pause the banner.
public void stop()
{
stopFlag = true;
t = null;
}
// Display the banner.
public void paint(Graphics g)
{
String temp2="";
System.out.println("Temp-->"+temp);
int result=x+msgWidth;
FontMetrics fm = g.getFontMetrics();
msgWidth=fm.stringWidth(msg);
g.setFont(new Font("ALGERIAN", Font.PLAIN, 30));
g.drawString(msg, x, 40);
x+=10;
if(x>bounds().width){
x=0;
}
if(result+130>bounds().width){
x=0;
while((x<=bounds().width)){
for(int i=msg.length()-1;i>0;i--){
temp2=Character.toString(msg.charAt(i));
temp=temp2+temp;
// it crashes here
System.out.println("Before draw");
g.drawString(temp, x, 40);
System.out.println("After draw");
repaint();
}
x++;
} // end while
} //end if
}
}
Let's start with...
Use Swing over AWT components (JApplet instead of Applet)
Don't override the paint methods of top level containers. There are lots of reasons, the major one that is going to effect you is top level containers are not double buffered.
DO NOT, EVER, update the UI from any thread other the Event Dispatching Thread, in fact, for what you are trying to do, a Thread is simply over kill.
DO NOT update animation states with the paint method. You've tried to perform ALL you animation within the paint method, this is not how paint works. Think of paint as a frame in film, it is up to (in your case) the thread to determine what frame where up to, and in fact, it should be preparing what should painted.
You do not control the paint system. repaint is a "request" to the paint sub system to perform an update. The repaint manager will decide when the actual repaint will occur. This makes performing updates a little tricky...
Updated with Example
public class Reverse extends JApplet {
// Set colors and initialize thread.
public void init() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
setBackground(Color.BLACK);
setForeground(Color.YELLOW);
setLayout(new BorderLayout());
add(new TextPane());
}
});
}
// Start thread
public void start() {
}
// Pause the banner.
public void stop() {
}
public class TextPane extends JPanel {
int state;
boolean stopFlag;
char ch;
int xPos;
String masterMsg = "Islam Hamdy", temp = "";
String msg = masterMsg;
String revMsg;
int msgWidth;
private int direction = 10;
public TextPane() {
setOpaque(false);
setBackground(Color.BLACK);
setForeground(Color.YELLOW);
setFont(new Font("ALGERIAN", Font.PLAIN, 30));
// This only needs to be done one...
StringBuilder sb = new StringBuilder(masterMsg.length());
for (int index = 0; index < masterMsg.length(); index++) {
sb.append(masterMsg.charAt((masterMsg.length() - index) - 1));
}
revMsg = sb.toString();
// Main animation engine. This is responsible for making
// the decisions on where the animation is up to and how
// to react to the edge cases...
Timer timer = new Timer(100, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
xPos += direction;
FontMetrics fm = getFontMetrics(getFont());
if (xPos > getWidth()) { // this condition fires when the text banner reaches the right banner
direction *= -1;
msg = revMsg;
} else if (xPos < -fm.stringWidth(masterMsg)) {
direction *= -1;
msg = masterMsg;
}
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
System.out.println(xPos);
FontMetrics fm = g.getFontMetrics();
msgWidth = fm.stringWidth(msg);
g.drawString(msg, xPos, 40);
}
}
}
Updated with additional example
Now, if you want to be a little extra clever...you could take advantage of a negative scaling process, which will reverse the graphics for you...
Updated timer...
Timer timer = new Timer(100, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
xPos += direction;
FontMetrics fm = getFontMetrics(getFont());
System.out.println(xPos + "; " + scale);
if (scale > 0 && xPos > getWidth()) { // this condition fires when the text banner reaches the right banner
xPos = -(getWidth() + fm.stringWidth(msg));
scale = -1;
} else if (scale < 0 && xPos >= 0) {
xPos = -fm.stringWidth(msg);
scale = 1;
}
repaint();
}
});
And the updated paint method...
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.scale(scale, 1);
FontMetrics fm = g2d.getFontMetrics();
msgWidth = fm.stringWidth(msg);
g2d.drawString(msg, xPos, 40);
g2d.dispose();
}
Updated with "bouncing"...
This replaces the TextPane from the previous example
As the text moves beyond the right boundary, it will "reverse" direction and move back to the left, until it passes beyond that boundary, where it will "reverse" again...
public class TextPane public class TextPane extends JPanel {
int state;
boolean stopFlag;
char ch;
int xPos;
String msg = "Islam Hamdy";
int msgWidth;
private int direction = 10;
public TextPane() {
setBackground(Color.BLACK);
setForeground(Color.YELLOW);
setFont(new Font("ALGERIAN", Font.PLAIN, 30));
Timer timer = new Timer(100, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
xPos += direction;
FontMetrics fm = getFontMetrics(getFont());
if (xPos > getWidth()) {
direction *= -1;
} else if (xPos < -fm.stringWidth(msg)) {
direction *= -1;
}
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
FontMetrics fm = g2d.getFontMetrics();
msgWidth = fm.stringWidth(msg);
g2d.drawString(msg, xPos, 40);
g2d.dispose();
}
}
I now think you mean 'should jump back to the start', but this slides back. But as an aside, I would not consider an applet for this sort of thing, for two reasons.
Scrolling text sucks.
If the page 'must have' scrolling text, better to do it using HTML and JS (and CSS).
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/*
* <applet code="TextBanner" width=600 height=50> </applet>
*/
public class TextBanner extends JApplet {
private TextBannerPanel banner;
// Set colors and initialize thread.
#Override
public void init() {
banner = new TextBannerPanel("Islam Hamdy");
add(banner);
}
// Start animation
#Override
public void start() {
banner.start();
}
// Stop animation
#Override
public void stop() {
banner.stop();
}
}
class TextBannerPanel extends JPanel {
String msg;
int x;
int diff = 5;
Timer timer;
Font font = new Font("ALGERIAN", Font.PLAIN, 30);
public TextBannerPanel() {
new TextBannerPanel("Scrolling Text Banner");
}
public TextBannerPanel(String msg) {
this.msg = msg;
setBackground(Color.BLACK);
setForeground(Color.YELLOW);
ActionListener animate = new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
repaint();
}
};
timer = new Timer(100, animate);
}
// Display the banner.
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setFont(font);
FontMetrics fm = g.getFontMetrics();
int w = (int) fm.getStringBounds(msg, g).getWidth();
g.drawString(msg, x, 40);
x += diff;
diff = x+w > getWidth() ? -5 : diff;
diff = x < 0 ? 5 : diff;
}
public void start() {
timer.start();
}
public void stop() {
timer.stop();
}
}
Old answer
..should .. appear reversed .. "Islam Hamdy"
See also JArabicInUnicode:
import javax.swing.*;
import java.awt.*;
/**
* "Peace Be Upon You", "Aslam Alykm' to which the common reply is "Wa alaykum
* as salaam", "And upon you, peace". Information obtained from the document
* http://www.unicode.org/charts/PDF/U0600.pdf Copyright © 1991-2003
* Unicode, Inc. All rights reserved. Arabic is written and read from right to
* left. This source is adapted from the original 'Peace' source written by
* mromarkhan ("Peace be unto you").
*
* #author Omar Khan
* #author Andrew Thompson
* #version 2004-05-31
*/
public class JArabicInUnicode extends JFrame {
/**
* Unicode constant used in this example.
*/
public final static String ALEF = "\u0627",
LAM = "\u0644",
SEEN = "\u0633",
MEEM = "\u0645",
AIN = "\u0639",
YEH = "\u064A",
KAF = "\u0643",
HEH = "\u0647";
/**
* An array of the letters that spell 'Aslam Alykm'.
*/
String text[] = {
ALEF, //a
LAM + SEEN, //s
LAM, //l
ALEF, //a
MEEM, //m
" ",
AIN, //a
LAM, //l
YEH, //y
KAF, //k
MEEM //m
};
/**
* Displays the letters of the phrase 'Aslam Alykm' as well as the words
* spelt out letter by letter.
*/
public JArabicInUnicode() {
super("Peace be upon you");
JTextArea textwod = new JTextArea(7, 10);
textwod.setEditable(false);
textwod.setFont(new Font("null", Font.PLAIN, 22));
String EOL = System.getProperty("line.separator");
// write the phrase to the text area
textwod.append(getCharacters() + EOL);
// now spell it, one letter at a time
for (int ii = 0; ii <= text.length; ii++) {
textwod.append(getCharacters(ii) + EOL);
}
textwod.setCaretPosition(0);
getContentPane().add(
new JScrollPane(textwod,
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED),
BorderLayout.CENTER);
pack();
setMinimumSize(getPreferredSize());
try {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
} catch (Exception e) {
} // allows to run under 1.2
}
/**
* Get a string of the entire phrase.
*/
String getCharacters() {
return getCharacters(text.length);
}
/**
* Get a string of the 1st 'num' characters of the phrase.
*/
String getCharacters(int num) {
StringBuffer sb = new StringBuffer();
for (int ii = 1; ii < num; ii++) {
sb.append(text[ii]);
}
return sb.toString();
}
/**
* Instantiate an ArabicInUnicode frame.
*/
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
new JArabicInUnicode().setVisible(true);
}
};
// Swing GUIs should be created and updated on the EDT
// http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
SwingUtilities.invokeLater(r);
}
}
Related
I have a task in university to draw an ellipse and make it move step by step on the screen pressing the button only once. Here is my code:
public class Window extends JPanel {
private static Ellipse2D.Double Ellipse;
private JFrame frame;
public Window() {
super();
int width = 20;
int height = 30;
Ellipse = new Ellipse2D.Double(width, height, 100, 50);
}
public Dimension getPreferredSize()
{
return (new Dimension(frame.getWidth(), frame.getHeight()));
}
#Override
public void paintComponent(Graphics g) {
super.paintComponents(g);
Graphics2D brush = (Graphics2D) g;
int width = getWidth();
int height = getHeight();
g.clearRect(0, 0, width, height);
brush.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
brush.draw(Ellipse);
}
public class MoveCircle implements KeyListener, ActionListener {
#Override
public void keyPressed(KeyEvent e) {
System.out.println("Working on top!");
double newX = 0; double newY = 0;
if (e.getKeyCode() == Event.ENTER) {
for (int i = 0; i < 26; i ++)
{
System.out.println("Working on bottom!");
newX = Ellipse.x + 10;
Ellipse.x = newX;
newY = Ellipse.y + 10;
Ellipse.y = newY;
repaint();
}
}
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}
}
private void createAndDisplayGUI(Window window)
{
frame = new JFrame();
Container container = frame.getContentPane();
container.add(window);
window.addKeyListener(new MoveCircle());
frame.setSize(400, 400);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setVisible(true);
window.requestFocusInWindow();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
Window window = new Window();
window.createAndDisplayGUI(window);
}
});
}
}
Although I call the function repaint() in cycle each time still the ellipse just moves radically from the original point to the point defined in the last iteration without drawing position of the ellipse in each iteration.
Is it possible to use a Swing Timer to make it repaint the ellipse in each iteration? I will be very glad to get help in this.
You have two problems: The first is that your loop is being run on the UI thread. The second is your misunderstanding in how repaint works. All repaint does is adds a request to the UI thread to do a repaining. It doesn't perform a repaint in and of itself. So if you are running operations on the UI thread, calling it multiple times will have no effect. As you suggested, you can fix this with a Swing Timer, as I've put together below
ActionListener al = new ActionListener() {
int iterations = 0;
public void actionPerformed(ActionEvent ae) {
if (iterations == 25) {
timer.stop();
}
interations++;
System.out.println("Working on bottom!");
newX = Ellipse.x + 10;
Ellipse.x = newX;
newY = Ellipse.y + 10;
Ellipse.y = newY;
repaint();
}
};
final timer = new javax.swing.Timer(delay, al);
timer.start();
These are the specific instruction but they are kind of confusing to me (are the instructions confusing/ambiguous or am I just not getting it?)
write a method public static void draw shooter(Graphics g, Color c);
call draw shooter using the shooter color as the last parameter in drawAll(?)
test the program you should see a red disk centered near the bottom of the screen(?)
import java.awt.*;
public class Project2{
public static final int PANEL_WIDTH = 300;
public static final int PANEL_HEIGHT = 300;
public static final int SLEEP_TIME = 50;
public static Color SHOOTER_COLOR = Color.RED;
public static Color BACKGROUND_COLOR = Color.WHITE;
public static final int SHOOTER_SIZE = 20; //diameter of the shooter
public static final int GUN_SIZE = 10; //length og the gun
public static final int SHOOTER_POSITION_Y = PANEL_HEIGHT - SHOOTER_SIZE;
public static final int SHOOTER_INITIAL_POSITION_X = 150;
int shooterPosition;
public static void initialize(){
int shooterPositionX = SHOOTER_INITIAL_POSITION_X;
}
public static void main(String[] args) {
DrawingPanel panel = new DrawingPanel(PANEL_WIDTH, PANEL_HEIGHT);
Graphics g = panel.getGraphics( );
initialize();
startGame(panel, g);
drawShooter(g, SHOOTER_COLOR);
}
public static void drawShooter(Graphics g, Color C){
g.setColor(Color);
g.fillOval(shooterPosition, SHOOTER_POSITION_Y, SHOOTER_SIZE, SHOOTER_SIZE);
}
public static void drawAll(Graphics g){
g.drawString("Project 2 by Jasmine Ramirez", 10, 15);
}
public static void startGame(DrawingPanel panel, Graphics g) {
for (int i = 0; i <= 10000; i++) {
panel.sleep(SLEEP_TIME);
drawAll(g);
}
}
}
this is my code I guessed that I needed to draw and color in a circle inside the method but I am getting errors with the g.setColor inside the method and I'm not sure what the second step means. Thanks just started learning to program.
Drawing Panel
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.ArrayList;
public class DrawingPanel implements ActionListener {
private static final String versionMessage =
"Drawing Panel version 1.1, January 25, 2015";
private static final int DELAY = 100; // delay between repaints in millis
private static final boolean PRETTY = false; // true to anti-alias
private static boolean showStatus = false;
private static final int MAX_KEY_BUF_SIZE = 10;
private int width, height; // dimensions of window frame
private JFrame frame; // overall window frame
private JPanel panel; // overall drawing surface
private BufferedImage image; // remembers drawing commands
private Graphics2D g2; // graphics context for painting
private JLabel statusBar; // status bar showing mouse position
private volatile MouseEvent click; // stores the last mouse click
private volatile boolean pressed; // true if the mouse is pressed
private volatile MouseEvent move; // stores the position of the mouse
private ArrayList<KeyInfo> keys;
// construct a drawing panel of given width and height enclosed in a window
public DrawingPanel(int width, int height) {
this.width = width;
this.height = height;
keys = new ArrayList<KeyInfo>();
image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
statusBar = new JLabel(" ");
statusBar.setBorder(BorderFactory.createLineBorder(Color.BLACK));
statusBar.setText(versionMessage);
panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0));
panel.setBackground(Color.WHITE);
panel.setPreferredSize(new Dimension(width, height));
panel.add(new JLabel(new ImageIcon(image)));
click = null;
move = null;
pressed = false;
// listen to mouse movement
MouseInputAdapter listener = new MouseInputAdapter() {
public void mouseMoved(MouseEvent e) {
pressed = false;
move = e;
if (showStatus)
statusBar.setText("moved (" + e.getX() + ", " + e.getY() + ")");
}
public void mousePressed(MouseEvent e) {
pressed = true;
move = e;
if (showStatus)
statusBar.setText("pressed (" + e.getX() + ", " + e.getY() + ")");
}
public void mouseDragged(MouseEvent e) {
pressed = true;
move = e;
if (showStatus)
statusBar.setText("dragged (" + e.getX() + ", " + e.getY() + ")");
}
public void mouseReleased(MouseEvent e) {
click = e;
pressed = false;
if (showStatus)
statusBar.setText("released (" + e.getX() + ", " + e.getY() + ")");
}
public void mouseEntered(MouseEvent e) {
// System.out.println("mouse entered");
panel.requestFocus();
}
};
panel.addMouseListener(listener);
panel.addMouseMotionListener(listener);
new DrawingPanelKeyListener();
g2 = (Graphics2D)image.getGraphics();
g2.setColor(Color.BLACK);
if (PRETTY) {
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setStroke(new BasicStroke(1.1f));
}
frame = new JFrame("Drawing Panel");
frame.setResizable(false);
try {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // so that this works in an applet
} catch (Exception e) {}
frame.getContentPane().add(panel);
frame.getContentPane().add(statusBar, "South");
frame.pack();
frame.setVisible(true);
toFront();
frame.requestFocus();
// repaint timer so that the screen will update
new Timer(DELAY, this).start();
}
public void showMouseStatus(boolean f) {
showStatus = f;
}
public void addKeyListener(KeyListener listener) {
panel.addKeyListener(listener);
panel.requestFocus();
}
// used for an internal timer that keeps repainting
public void actionPerformed(ActionEvent e) {
panel.repaint();
}
// obtain the Graphics object to draw on the panel
public Graphics2D getGraphics() {
return g2;
}
// set the background color of the drawing panel
public void setBackground(Color c) {
panel.setBackground(c);
}
// show or hide the drawing panel on the screen
public void setVisible(boolean visible) {
frame.setVisible(visible);
}
// makes the program pause for the given amount of time,
// allowing for animation
public void sleep(int millis) {
panel.repaint();
try {
Thread.sleep(millis);
} catch (InterruptedException e) {}
}
// close the drawing panel
public void close() {
frame.dispose();
}
// makes drawing panel become the frontmost window on the screen
public void toFront() {
frame.toFront();
}
// return panel width
public int getWidth() {
return width;
}
// return panel height
public int getHeight() {
return height;
}
// return the X position of the mouse or -1
public int getMouseX() {
if (move == null) {
return -1;
} else {
return move.getX();
}
}
// return the Y position of the mouse or -1
public int getMouseY() {
if (move == null) {
return -1;
} else {
return move.getY();
}
}
// return the X position of the last click or -1
public int getClickX() {
if (click == null) {
return -1;
} else {
return click.getX();
}
}
// return the Y position of the last click or -1
public int getClickY() {
if (click == null) {
return -1;
} else {
return click.getY();
}
}
// return true if a mouse button is pressed
public boolean mousePressed() {
return pressed;
}
public synchronized int getKeyCode() {
if (keys.size() == 0)
return 0;
return keys.remove(0).keyCode;
}
public synchronized char getKeyChar() {
if (keys.size() == 0)
return 0;
return keys.remove(0).keyChar;
}
public synchronized int getKeysSize() {
return keys.size();
}
private synchronized void insertKeyData(char c, int code) {
keys.add(new KeyInfo(c,code));
if (keys.size() > MAX_KEY_BUF_SIZE) {
keys.remove(0);
// System.out.println("Dropped key");
}
}
private class KeyInfo {
public int keyCode;
public char keyChar;
public KeyInfo(char keyChar, int keyCode) {
this.keyCode = keyCode;
this.keyChar = keyChar;
}
}
private class DrawingPanelKeyListener implements KeyListener {
int repeatCount = 0;
public DrawingPanelKeyListener() {
panel.addKeyListener(this);
panel.requestFocus();
}
public void keyPressed(KeyEvent event) {
// System.out.println("key pressed");
repeatCount++;
if ((repeatCount == 1) || (getKeysSize() < 2))
insertKeyData(event.getKeyChar(),event.getKeyCode());
}
public void keyTyped(KeyEvent event) {
}
public void keyReleased(KeyEvent event) {
repeatCount = 0;
}
}
}
1st Error
In your drawShooter() method you do:
g.setColor(Color)
This is incorrect, since you need to pass an instance of the class Color not the class itself.
So instead use this:
g.setColor(C);
2nd Error
change the shooterPosition to static so that it can be accessed by a static method.
I assume that the method initialize() is also wrong because you are declaring a new shooterPosition int for no reason so do these changes:
int shooterPosition;
To:
public static int shooterPosition;
And
public static void initialize(){
int shooterPositionX = SHOOTER_INITIAL_POSITION_X;
}
To:
public static void initialize() {
shooterPosition = SHOOTER_INITIAL_POSITION_X;
}
3rd Error
In startGame() you are looping for 10000 times and each time you are waiting for a bit more than 1/20th of a second, which means that you will have to wait for almost 10 minutes until the red circle is drawn. So you have two options.
1st option: decrease the amount of iterations or even better remove the loop.
public static void startGame(DrawingPanel panel, Graphics g) {
for (int i = 0; i <= 10000; i++) {
panel.sleep(SLEEP_TIME);
drawAll(g);
}
}
To:
public static void startGame(DrawingPanel panel, Graphics g) {
for (int i = 0; i <= 1; i++) {
panel.sleep(SLEEP_TIME);
drawAll(g);
}
}
or
public static void startGame(DrawingPanel panel, Graphics g) {
panel.sleep(SLEEP_TIME);
drawAll(g);
}
2nd option: execute the drawShooter() method before the startGame() method or don't execute the startGame() at all.
startGame(panel, g); drawShooter(g, SHOOTER_COLOR);
To:
drawShooter(g, SHOOTER_COLOR);
startGame(panel, g);
or
drawShooter(g, SHOOTER_COLOR);
Didn't you ask this same question or something similar to it yesterday? And you're passing in the class name to g.setColor(Color) method and need to pass in the parameter which holds the object: g.setColor(C)
Your use of Graphics is not good, as you shouldn't use a Graphics obtained from a component via getGraphics(), but I'm guessing that it's because that's what your instructor told you to do. Same for use of a while (true) loop. Instead you should use a Swing Timer.
Like stated before g.setcolor(c) is required
check your error msgs since it allows you to gather that error and the shooterPosition error(its not public so cant be used inside a method)
How can I implement Marquee effect in Java Swing
Here's an example using javax.swing.Timer.
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
/** #see http://stackoverflow.com/questions/3617326 */
public class MarqueeTest {
private void display() {
JFrame f = new JFrame("MarqueeTest");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
String s = "Tomorrow, and tomorrow, and tomorrow, "
+ "creeps in this petty pace from day to day, "
+ "to the last syllable of recorded time; ... "
+ "It is a tale told by an idiot, full of "
+ "sound and fury signifying nothing.";
MarqueePanel mp = new MarqueePanel(s, 32);
f.add(mp);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
mp.start();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new MarqueeTest().display();
}
});
}
}
/** Side-scroll n characters of s. */
class MarqueePanel extends JPanel implements ActionListener {
private static final int RATE = 12;
private final Timer timer = new Timer(1000 / RATE, this);
private final JLabel label = new JLabel();
private final String s;
private final int n;
private int index;
public MarqueePanel(String s, int n) {
if (s == null || n < 1) {
throw new IllegalArgumentException("Null string or n < 1");
}
StringBuilder sb = new StringBuilder(n);
for (int i = 0; i < n; i++) {
sb.append(' ');
}
this.s = sb + s + sb;
this.n = n;
label.setFont(new Font("Serif", Font.ITALIC, 36));
label.setText(sb.toString());
this.add(label);
}
public void start() {
timer.start();
}
public void stop() {
timer.stop();
}
#Override
public void actionPerformed(ActionEvent e) {
index++;
if (index > s.length() - n) {
index = 0;
}
label.setText(s.substring(index, index + n));
}
}
I know this is a late answer, but I just saw another question about a marquee that was closed because it was considered a duplicate of this answer.
So I thought I'd add my suggestion which takes a approach different from the other answers suggested here.
The MarqueePanel scrolls components on a panel not just text. So this allows you to take full advantage of any Swing component. A simple marquee can be used by adding a JLabel with text. A fancier marquee might use a JLabel with HTML so you can use different fonts and color for the text. You can even add a second component with an image.
Basic answer is you draw your text / graphic into a bitmap and then implement a component that paints the bitmap offset by some amount. Usually marquees / tickers scroll left so the offset increases which means the bitmap is painted at -offset. Your component runs a timer that fires periodically, incrementing the offset and invalidating itself so it repaints.
Things like wrapping are a little more complex to deal with but fairly straightforward. If the offset exceeds the bitmap width you reset it back to 0. If the offset + component width > bitmap width you paint the remainder of the component starting from the beginning of the bitmap.
The key to a decent ticker is to make the scrolling as smooth and as flicker free as possible. Therefore it may be necessary to consider double buffering the result, first painting the scrolling bit into a bitmap and then rendering that in one go rather than painting straight into the screen.
Here is some code that I threw together to get you started. I normally would take the ActionListener code and put that in some sort of MarqueeController class to keep this logic separate from the panel, but that's a different question about organizing the MVC architecture, and in a simple enough class like this it may not be so important.
There are also various animation libraries that would help you do this, but I don't normally like to include libraries into projects only to solve one problem like this.
public class MarqueePanel extends JPanel {
private JLabel textLabel;
private int panelLocation;
private ActionListener taskPerformer;
private boolean isRunning = false;
public static final int FRAMES_PER_SECOND = 24;
public static final int MOVEMENT_PER_FRAME = 5;
/**
* Class constructor creates a marquee panel.
*/
public MarqueePanel() {
this.setLayout(null);
this.textLabel = new JLabel("Scrolling Text Here");
this.panelLocation = 0;
this.taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
MarqueePanel.this.tickAnimation();
}
}
}
/**
* Starts the animation.
*/
public void start() {
this.isRunning = true;
this.tickAnimation();
}
/**
* Stops the animation.
*/
public void stop() {
this.isRunning = false;
}
/**
* Moves the label one frame to the left. If it's out of display range, move it back
* to the right, out of display range.
*/
private void tickAnimation() {
this.panelLocation -= MarqueePanel.MOVEMENT_PER_FRAME;
if (this.panelLocation < this.textLabel.getWidth())
this.panelLocaton = this.getWidth();
this.textLabel.setLocation(this.panelLocation, 0);
this.repaint();
if (this.isRunning) {
Timer t = new Timer(1000 / MarqueePanel.FRAMES_PER_SECOND, this.taskPerformer);
t.setRepeats(false);
t.start();
}
}
}
Add a JLabel to your frame or panel.
ScrollText s= new ScrollText("ello Everyone.");
jLabel3.add(s);
public class ScrollText extends JComponent {
private BufferedImage image;
private Dimension imageSize;
private volatile int currOffset;
private Thread internalThread;
private volatile boolean noStopRequested;
public ScrollText(String text) {
currOffset = 0;
buildImage(text);
setMinimumSize(imageSize);
setPreferredSize(imageSize);
setMaximumSize(imageSize);
setSize(imageSize);
noStopRequested = true;
Runnable r = new Runnable() {
public void run() {
try {
runWork();
} catch (Exception x) {
x.printStackTrace();
}
}
};
internalThread = new Thread(r, "ScrollText");
internalThread.start();
}
private void buildImage(String text) {
RenderingHints renderHints = new RenderingHints(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
renderHints.put(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
BufferedImage scratchImage = new BufferedImage(1, 1,
BufferedImage.TYPE_INT_RGB);
Graphics2D scratchG2 = scratchImage.createGraphics();
scratchG2.setRenderingHints(renderHints);
Font font = new Font("Serif", Font.BOLD | Font.ITALIC, 24);
FontRenderContext frc = scratchG2.getFontRenderContext();
TextLayout tl = new TextLayout(text, font, frc);
Rectangle2D textBounds = tl.getBounds();
int textWidth = (int) Math.ceil(textBounds.getWidth());
int textHeight = (int) Math.ceil(textBounds.getHeight());
int horizontalPad = 600;
int verticalPad = 10;
imageSize = new Dimension(textWidth + horizontalPad, textHeight
+ verticalPad);
image = new BufferedImage(imageSize.width, imageSize.height,
BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = image.createGraphics();
g2.setRenderingHints(renderHints);
int baselineOffset = (verticalPad / 2) - ((int) textBounds.getY());
g2.setColor(Color.BLACK);
g2.fillRect(0, 0, imageSize.width, imageSize.height);
g2.setColor(Color.GREEN);
tl.draw(g2, 0, baselineOffset);
// Free-up resources right away, but keep "image" for
// animation.
scratchG2.dispose();
scratchImage.flush();
g2.dispose();
}
public void paint(Graphics g) {
// Make sure to clip the edges, regardless of curr size
g.setClip(0, 0, imageSize.width, imageSize.height);
int localOffset = currOffset; // in case it changes
g.drawImage(image, -localOffset, 0, this);
g.drawImage(image, imageSize.width - localOffset, 0, this);
// draw outline
g.setColor(Color.black);
g.drawRect(0, 0, imageSize.width - 1, imageSize.height - 1);
}
private void runWork() {
while (noStopRequested) {
try {
Thread.sleep(10); // 10 frames per second
// adjust the scroll position
currOffset = (currOffset + 1) % imageSize.width;
// signal the event thread to call paint()
repaint();
} catch (InterruptedException x) {
Thread.currentThread().interrupt();
}
}
}
public void stopRequest() {
noStopRequested = false;
internalThread.interrupt();
}
public boolean isAlive() {
return internalThread.isAlive();
}
}
This is supposed to be an improvement of #camickr MarqueePanel. Please see above.
To map mouse events to the specific components added to MarqueePanel
Override add(Component comp) of MarqueePanel in order to direct all mouse events of the components
An issue here is what do do with the MouseEvents fired from the individual components.
My approach is to remove the mouse listeners form the components added and let the MarqueePanel redirect the event to the correct component.
In my case these components are supposed to be links.
#Override
public Component add(Component comp) {
comp = super.add(comp);
if(comp instanceof MouseListener)
comp.removeMouseListener((MouseListener)comp);
comp.addMouseListener(this);
return comp;
}
Then map the component x to a MarqueePanel x and finally the correct component
#Override
public void mouseClicked(MouseEvent e)
{
Component source = (Component)e.getSource();
int x = source.getX() + e.getX();
int y = source.getY();
MarqueePanel2 marqueePanel = (MarqueePanel2) ((JComponent)e.getSource()).getParent();
double x2 = marqueePanel.getWidth();
double x1 = Math.abs(marqueePanel.scrollOffset);
if(x >= x1 && x <= x2)
{
System.out.println("Bang " + x1);
Component componentAt = getComponentAt(x+marqueePanel.scrollOffset, y);
if(comp instanceof MouseListener)
((MouseListener) componentAt).mouseClicked(e);
System.out.println(componentAt.getName());
}
else
{
return;
}
//System.out.println(x);
}
Is it possible to be able to change the bar colour depending on the value of the progress? I tried the following but it doesn't work:
percentUsed = (int)(((float) used / (float) max) * BAR_PERCENTAGE);
if (percentUsed >= ORANGE_THRESHOLD && percentUsed < RED_THRESHOLD) {
if (!m_orangeIndicator) {
LOG.warn(String.format("Memory usage exceeds %d percent.", ORANGE_THRESHOLD));
m_orangeIndicator = true;
}
colour = Color.ORANGE;
m_redIndicator = false;
}
else if (percentUsed >= RED_THRESHOLD) {
if (!m_redIndicator) {
LOG.warn(String.format("Memory usage exceeds %d percent.", RED_THRESHOLD));
m_orangeIndicator = true;
m_redIndicator = true;
}
colour = Color.RED;
}
else {
m_orangeIndicator = false;
m_redIndicator = false;
colour = Color.GREEN;
}
m_memUsageBar.setForeground(colour);
m_memUsageBar.setValue(percentUsed);
m_memUsageBar.updateUI();
I am guessing it is not a trivial thing to do because JProgressbar is not meant to be used that way... But is it possible or are there alternatives?
This sample was inspired from:
http://harmoniccode.blogspot.jp/2011/05/varying-gradients.html
http://java-swing-tips.blogspot.jp/2011/06/gradient-translucent-track-jslider.html
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.image.*;
import java.beans.*;
import javax.swing.*;
import javax.swing.plaf.basic.*;
import javax.swing.event.*;
public class GradientPalletProgressBarDemo {
public JComponent makeUI() {
final JProgressBar progressBar = new JProgressBar();
progressBar.setOpaque(false);
progressBar.setUI(new GradientPalletProgressBarUI());
JPanel p = new JPanel();
p.add(progressBar);
p.add(new JButton(new AbstractAction("Start") {
#Override public void actionPerformed(ActionEvent e) {
SwingWorker<Void,Void> worker = new SwingWorker<Void,Void>() {
#Override public Void doInBackground() {
int current = 0, lengthOfTask = 100;
while(current<=lengthOfTask && !isCancelled()) {
try { // dummy task
Thread.sleep(50);
} catch(InterruptedException ie) {
return null;
}
setProgress(100 * current / lengthOfTask);
current++;
}
return null;
}
};
worker.addPropertyChangeListener(new ProgressListener(progressBar));
worker.execute();
}
}));
return p;
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.getContentPane().add(new GradientPalletProgressBarDemo().makeUI());
frame.setSize(320, 240);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
class ProgressListener implements PropertyChangeListener {
private final JProgressBar progressBar;
ProgressListener(JProgressBar progressBar) {
this.progressBar = progressBar;
this.progressBar.setValue(0);
}
#Override public void propertyChange(PropertyChangeEvent evt) {
String strPropertyName = evt.getPropertyName();
if("progress".equals(strPropertyName)) {
progressBar.setIndeterminate(false);
int progress = (Integer)evt.getNewValue();
progressBar.setValue(progress);
}
}
}
class GradientPalletProgressBarUI extends BasicProgressBarUI {
private final int[] pallet;
public GradientPalletProgressBarUI() {
super();
this.pallet = makeGradientPallet();
}
private static int[] makeGradientPallet() {
BufferedImage image = new BufferedImage(100, 1, BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = image.createGraphics();
Point2D start = new Point2D.Float(0f, 0f);
Point2D end = new Point2D.Float(99f, 0f);
float[] dist = {0.0f, 0.5f, 1.0f};
Color[] colors = { Color.RED, Color.YELLOW, Color.GREEN };
g2.setPaint(new LinearGradientPaint(start, end, dist, colors));
g2.fillRect(0, 0, 100, 1);
g2.dispose();
int width = image.getWidth(null);
int[] pallet = new int[width];
PixelGrabber pg = new PixelGrabber(image, 0, 0, width, 1, pallet, 0, width);
try {
pg.grabPixels();
} catch(Exception e) {
e.printStackTrace();
}
return pallet;
}
private static Color getColorFromPallet(int[] pallet, float x) {
if(x < 0.0 || x > 1.0) {
throw new IllegalArgumentException("Parameter outside of expected range");
}
int i = (int)(pallet.length * x);
int max = pallet.length-1;
int index = i<0?0:i>max?max:i;
int pix = pallet[index] & 0x00ffffff | (0x64 << 24);
return new Color(pix, true);
}
#Override public void paintDeterminate(Graphics g, JComponent c) {
if (!(g instanceof Graphics2D)) {
return;
}
Insets b = progressBar.getInsets(); // area for border
int barRectWidth = progressBar.getWidth() - (b.right + b.left);
int barRectHeight = progressBar.getHeight() - (b.top + b.bottom);
if (barRectWidth <= 0 || barRectHeight <= 0) {
return;
}
int cellLength = getCellLength();
int cellSpacing = getCellSpacing();
// amount of progress to draw
int amountFull = getAmountFull(b, barRectWidth, barRectHeight);
if(progressBar.getOrientation() == JProgressBar.HORIZONTAL) {
// draw the cells
float x = amountFull / (float)barRectWidth;
g.setColor(getColorFromPallet(pallet, x));
g.fillRect(b.left, b.top, amountFull, barRectHeight);
} else { // VERTICAL
//...
}
// Deal with possible text painting
if(progressBar.isStringPainted()) {
paintString(g, b.left, b.top, barRectWidth, barRectHeight, amountFull, b);
}
}
}
You can do either of this way:
UIManager.put("ProgressBar.background", Color.BLACK); //colour of the background
UIManager.put("ProgressBar.foreground", Color.RED); //colour of progress bar
UIManager.put("ProgressBar.selectionBackground",Color.YELLOW); //colour of percentage counter on black background
UIManager.put("ProgressBar.selectionForeground",Color.BLUE); //colour of precentage counter on red background
There is a thread here.
Setting the colors of a JProgressBar text
There is a sample demo here at this link as well.
how to change color progressbar
As you noticed, is value-dependent "progress" painting not supported. Theoretically, setting the foregound of the progressBar instance dynamically (that is depending on value) is the way to go.
But: the details of progressBar painting are highly LAF dependent
in simple LAFs (like Metal) setting the foreground is fine
in fully skinnable LAFs (like synth-based LAF) that support per-instance skinning (f.i. Nimbus) you can try to provide a Painter which uses the foreground
in not-skinnable LAFs there is no way (except overriding the concrete LAF and try to hook into the painting code)
Some snippet:
final JProgressBar bar = new JProgressBar();
// used for Nimbus (beware: just a proof-of-concept - this looks extremely ugly!)
Painter p = new Painter() {
#Override
public void paint(Graphics2D g, Object object, int width, int height) {
JProgressBar bar = (JProgressBar) object;
g.setColor(bar.getForeground());
g.fillRect(0, 0, width, height);
}
};
// install custom painter on the bar
UIDefaults properties = new UIDefaults();
properties.put("ProgressBar[Enabled].foregroundPainter", p);
bar.putClientProperty("Nimbus.Overrides", properties);
// simulate progress
Action action = new AbstractAction("timer") {
#Override
public void actionPerformed(ActionEvent e) {
bar.setValue(bar.getValue() + 1);
// change foreground value-dependent
if (bar.getValue() > 10) {
bar.setForeground(Color.RED);
}
}
};
Timer timer = new Timer(100, action);
timer.start();
Thanks for the help but by trial and error I found a way to get the colour changing with using my existing code.
I am not sure if its the quirk of JPrgressbar but if call do the following call the foreground bar colour can be changed dynamically with minimal rework:
progressBar.setStringPainted(true);
I want to change Background color of Jpanel and its font on button click.
Can anyone tell me what i am doing wrong?
Can I set JPanel background transparent?if yes How?
On button click test4.action method is called where i need to change Jpanel background color?
Here is the code:
import java.applet.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.event.*;
import javax.swing.*;
public class test3 extends Applet {
JPanel c;
JScrollPane s;
Button connect;
Panel controls;
Color back, fore;
public void init() {
back = Color.black;
fore = Color.white;
setBackground(Color.darkGray);
setLayout(new BorderLayout());
s = new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
//s.setSize(100, 100);
add("Center", s);
c = new myCanvas11(this);
s.setOpaque(false);
s.setViewportView(c);
//s.add(c);
c.setSize(1000, 16000);
add("North", controls = new Panel());
controls.setLayout(new FlowLayout());
controls.add(connect = new Button("Change Color"));
}
public void start() {
// s.setScrollPosition(100, 100);
}
public boolean action(Event e, Object arg) {
back = Color.magenta;
fore = Color.blue;
//setBackground(back);
//invalidate();
//repaint();
c.setBackground(back);
c.repaint();
//s.getViewport().setBackground(back);
// s.getViewport().repaint();
//c.repaint();
c.setFocusable(true);
return true;
}
}
class myCanvas11 extends JPanel implements KeyListener {
Image buffImage;
Graphics offscreen;
boolean initDone = false;
int chw, chh; // size of a char (in pixels)
int chd; // offset of char from baseline
int width, height; // size of applet (in pixels)
int w, h; // size of applet (in chars)
Font fn;
Graphics gr;
int nh, nw;
test3 owner;
static int counter = 0;
myCanvas11(test3 t) {
super();
owner = t;
nh = 16000;
nw = 1000;
this.setOpaque(true);
this.setFocusable(true);
addKeyListener(this);
}
public void reshape(int nx, int ny, int nw1, int nh1) {
if (nw1 != width || nh1 != height) {
width = nw;
height = nh;
gr = getGraphics();
fn = new Font("Courier", Font.PLAIN, 11);
if (fn != null) {
gr.setFont(fn);
}
FontMetrics fnm = gr.getFontMetrics();
chw = fnm.getMaxAdvance();
chh = fnm.getHeight();
chd = fnm.getDescent();
// kludge for Windows NT and others which have too big widths
if (chw + 1 >= chh) {
chw = (chw + 1) / 2;
}
// work out size of drawing area
h = nh / chh;
w = nw / chw;
buffImage = this.createImage(nw, nh);
offscreen = buffImage.getGraphics();
//offscreen.setColor(Color.black);
//offscreen.fillRect(0, 0, nw, nh);
offscreen.setColor(Color.blue);
offscreen.setFont(fn);
if (initDone) {
offscreen.drawString("Hello World!", 0, 50);
} else {
offscreen.drawString("khushbu", 2, 50);
}
initDone = true;
offscreen.drawImage(buffImage, 0, 0, this);
}
super.reshape(nx, ny, nw, nh);
}
public void paint(Graphics g) {
// if (!initDone)
// initpaint(g);
// else
g.drawImage(buffImage, 0, 0, this);
//g.drawImage(buffImage, 0, 0, owner.back, this);
}
public void update(Graphics g) {
g.drawImage(buffImage, 0, 0, this);
super.update(g);
//g.drawImage(buffImage, 0, 0, owner.back, this);
}
public void initpaint(Graphics g) {
try {
nh = getHeight();
nw = getWidth();
gr = getGraphics();
fn = new Font("Courier", Font.PLAIN, 11);
if (fn != null) {
gr.setFont(fn);
}
FontMetrics fnm = gr.getFontMetrics();
chw = fnm.getMaxAdvance();
chh = fnm.getHeight();
chd = fnm.getDescent();
// kludge for Windows NT and others which have too big widths
if (chw + 1 >= chh) {
chw = (chw + 1) / 2;
}
// work out size of drawing area
h = nh / chh;
w = nw / chw;
buffImage = this.createImage(nw, nh);
offscreen = buffImage.getGraphics();
//offscreen.setColor(Color.black);
//offscreen.fillRect(0, 0, nw, nh);
offscreen.setColor(Color.white);
offscreen.setFont(fn);
if (initDone) {
offscreen.drawString("Hello World!", 0, 50);
} else {
offscreen.drawString("khushbu", 2, 50);
}
initDone = true;
g.drawImage(buffImage, 0, 0, this);
} catch (Exception e) {
e.printStackTrace();
}
}
/** Handle the key typed event from the text field. */
public void keyTyped(KeyEvent e) {
}
/** Handle the key pressed event from the text field. */
public void keyPressed(KeyEvent e) {
String s;
offscreen.setColor(owner.fore);
offscreen.setFont(fn);
for (int i = counter; i < counter + 25; ++i) {
s = Integer.toString(i);
offscreen.drawString(s, 3, i * chh);
offscreen.drawLine(10, i * chh, 160, i * chh);
}
//owner.s.setScrollPosition(0, counter * 16);
counter = counter + 25;
repaint();
}
/** Handle the key released event from the text field. */
public void keyReleased(KeyEvent e) {
}
public boolean keyDown(Event e, int k) {
String s;
offscreen.setColor(owner.fore);
offscreen.setFont(fn);
for (int i = counter; i < counter + 25; ++i) {
s = Integer.toString(i);
offscreen.drawString(s, 3, i * chh);
offscreen.drawLine(10, i * chh, 160, i * chh);
}
//owner.s.setScrollPosition(0, counter * 16);
counter = counter + 25;
repaint();
return true;
}
}
Can I set JPanel background transparent?if yes How?
Yes, just call setOpaque(false); on that JPanel. On the contrary, if you want the background to be painted, call setOpaque(true); on that panel.
Additional remarks:
public boolean action(Event e, Object arg) is Deprecated. Add the appropriate listeners instead.
Follow Java coding conventions and use an Uppercase letter for the first character of a class
You should almost never call getGraphics(); on a Component
Don't override public void paint(Graphics g) but protected void paintComponent(Graphics g). Don't forget to call super.paintComponent if you want the background to be painted
Why do you override reshape?
Why do you create an internal buffer? Swing already has built-in double buffering and they do a much better job.
If you overrode already paint() why do you also override update()? You are performing the same job twice.
Remove that gr class variable, it does not make any sense. When you use Graphics object, use the one provided as a parameter of the paintComponent method but don't keep a reference to it, as it will be disposed later.
counter does not need to be static. Try to avoid static as much as possible.
Try to avoid so much coupling between your classes. It makes your code harder to maintain and less predictable.
Next time, post an SSCCE with something else than an Applet (a JFrame, for example) unless the problem you are having really requires an Applet to be reproduced.