Refresh text in Applet - java

I am doing this small race between two cars, in a java applet.
Just two pictures moving at random speed. I am calculating the distance between current position and the finish line, and you are suppose to be able to see the distance in the upper corner.
The thing is I am not able to refresh the text field, instead it just applies a new layer on top of the old number so it is almost impossible to read.
Here are pictures to demonstrate my problem.
I thought I would be able to solve it by creating the blue rectangle at the start of each loop but that does not seem to solve it.
public void action(){
Random rand = new Random();
boolean race = true;
int x1 =500, y1 = 233;
int x2 = 500, y2 = 333;
int speed1 = rand.nextInt(15) + -16;
int speed2 = rand.nextInt(15) + -16;
int finishline = 30;
Text winnerBlue = new Text("Winner: BLUE",new Font("SansSerif",Font.BOLD,20), Color.blue,Color.white);
Text winnerRed = new Text("Winner: RED",new Font("SansSerif",Font.BOLD,20), Color.red,Color.white);
//background
Text text =null;
Text text2 = null;
window.fillRect(0, 0, 600, 400, Color.GREEN);
//track 1
window.fillRect(20, 330, 550, 39, Color.gray);
//track2
window.fillRect(20, 230, 550, 39, Color.gray);
//Finish line
window.fillRect(40, 210, 10, 180, Color.BLACK);
while(race){
text = new Text(Integer.toString(x1),new Font("Courier",Font.BOLD,20), Color.WHITE);
text2 = new Text(Integer.toString(x2),new Font("SansSerif",Font.BOLD,20), Color.WHITE);
window.fillRect(0, 0, 70, 50, Color.blue);
window.fillRect(70, 0, 70, 50, Color.red);
window.showImage(text, 0, 0);
window.showImage(text2, 70, 0);
window.showImage(car1.getImage(), x1, y1);
window.showImage(car2.getImage(), x2, y2);
car1.moveTo(x1 += speed1, y1);
car2.moveTo(x2 += speed2, y2);
window.pause(50);
if(x1 <= (finishline ) ){
speed1 = 0;
speed2 = 0;
window.showImage(winnerBlue, 200, 200);
race = false;
}
if(x2 <= (finishline)){
speed2 = 0;
speed1 = 0;
window.showImage(winnerRed, 200, 200);
race = false;
}
}
}
}

For the two screen shots and supplied code snippt, it's clear that you don't understand how painting works in Swing/AWT.
Do NOT ever, maintain any kind of refernce to the Graphics context out side of the paintXxx methods.
The paint methods perform a number of very important steps to prepare the Graphics context for painting
Start by taking a look through Performing Custom Painting

Related

how do I detect key presses with just one method in java?

I'm trying to paint 6 colors, 10 shapes, a jpeg image, and 3 things that change when a key is pressed in java.
However I'm trying to program all of this in one method. I've done everything else except detecting a key press. I've looked at a lot of examples, but all of them use different methods or classes that work together to detect a key press. But how to do I detect key presses and at the same time change pictures/images in JPanel all in just one method.
I tried to write some code but it doesn't work (nothing shows up on the JPanel/screen) Here's my code so far:
public void paint(Graphics g){
g.setColor(Color.WHITE);
g.fillRect(0, 0, 1000, 1000);
BufferedImage photo = null;
try
{
File file = new File("holiday.jfif");
photo = ImageIO.read(file);
}
catch (IOException e)
{
g.drawString("Problem reading the file", 100, 100);
}
g.drawImage(photo,0,0,800,800,null);
g.setColor(Color.BLACK);
g.fillRect(120,300,100,100 );
g.setColor(Color.GREEN);
g.fillOval(270,130,50,100 );
g.setColor(Color.BLUE );
g.fillRect(350,200,100,150 );
g.setColor(Color.PINK);
g.fillOval(460, 270, 50, 50);
g.setColor(Color.GRAY);
g.fillArc(500, 300, 110, 100, 5, 150);
g.setColor(Color.YELLOW);
g.fillRect(500,450,100,100);
g.setColor(Color.YELLOW);
g.fillOval(550,500,100,100);
int[] xpoints = {50,150,20,180};
int[] ypoints = {500,500,550,550};
g.setColor(Color.BLACK);
g.drawPolygon(xpoints,ypoints,4);
int[] xpoint = {250,220,380,350};
int[] ypoint = {500,550,550,500};
g.drawPolygon(xpoint,ypoint,4);
int[] x = {600,500,700};
int[] y = {20,100,100};
g.drawPolygon(x,y,3);
g.setColor(Color.ORANGE);
g.fillRect(10,50,220,30);
g.fillRect(115,80,20,100);
Scanner input = new Scanner(System.in);
String press;
boolean stop = false;
while(!stop)
{
//Scanner input = new Scanner(System.in);
press = input.next();
if (press != null)
{
g.clearRect(115,80,20,100);
g.clearRect(500,450,100,100);
stop = true;
}
}
}

Animation not working Java Graphics

Completing a graphics program in Java, I'm trying to animate rain falling using a timer. Right now I am testing my code with a big blue rectangle so I can see where it's going but the animation isn't working for me. I'm very new to Java graphics so I could be making mistakes that just aren't clear to me.
When I try to repaint the square to move, and the paint function is called the whole screen blinks, this may be because I was using recursive functions to draw fractal trees, but I'm not sure. Is there a way to keep everything I have drawn from being repainted and just call repaint on the rain? Any guidance or tips would be appreciated.
import java.awt.*;
import javax.swing.*;
import java.lang.Math;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class FractalTree extends JFrame {
private int frameWidth = 1440;
private int frameHeight = 850;
private int rainX = 0;
private int rainY = 0;
public FractalTree()
{
setBounds(1000, 1000, frameWidth, frameHeight ); //graphics window size
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ActionListener listener = new TimerListener();
final int DELAY = 1500;
Timer t = new Timer(DELAY, listener);
t.start();
setResizable(false);
}
public void setRain(int newRainX, int newRainY)
{
rainX = newRainX;
rainY = newRainY;
}
public void setSkyGround(Graphics g)
{
Color sky = new Color(180, 225, 255);
g.setColor(sky);
g.fillRect(0, 0, frameWidth, 550);
Color sun = new Color(225, 225, 150);
g.setColor(sun);
g.fillOval(1380, -40, 100, 100);
g.drawLine(frameWidth, 0, 1350, 550);
g.drawLine(frameWidth, 0, 1450, 550);
g.drawLine(1350, 550, 1450, 550);
int xpoints[] = {frameWidth, 1450, 1350};
int ypoints[] = {0, 550, 550};
int npoints = 3;
g.fillPolygon(xpoints, ypoints, npoints);
g.drawLine(frameWidth, 0, 1080, 550);
g.drawLine(frameWidth, 0, 880, 550);
g.drawLine(880, 550, 1080, 550);
int xpoints2[] = {frameWidth, 1080, 880};
int ypoints2[] = {0, 550, 550};
int npoints2 = 3;
g.fillPolygon(xpoints2, ypoints2, npoints2);
g.drawLine(frameWidth, 0, 480, 550);
g.drawLine(frameWidth, 0, 280, 550);
g.drawLine(480, 550, 280, 550);
int xpoints3[] = {frameWidth, 480, 280};
int ypoints3[] = {0, 550, 550};
int npoints3 = 3;
g.fillPolygon(xpoints3, ypoints3, npoints3);
g.drawLine(frameWidth, 0, 0, 430);
g.drawLine(frameWidth, 0, 0, 300);
g.drawLine(0, 430, 0, 300);
int xpoints4[] = {frameWidth, 0, 0};
int ypoints4[] = {0, 430, 300};
int npoints4 = 3;
g.fillPolygon(xpoints4, ypoints4, npoints4);
g.drawLine(frameWidth, 0, 0, 100);
g.drawLine(frameWidth, 0, 0, 0);
g.drawLine(0, 100, 0, 0);
int xpoints5[] = {frameWidth, 0, 0};
int ypoints5[] = {0, 0, 100};
int npoints5 = 3;
g.fillPolygon(xpoints5, ypoints5, npoints5);
Color grassBackground = new Color(150, 255, 170);
g.setColor(grassBackground);
g.fillRect(0, 550, frameWidth, frameHeight);
}
public void drawTree(Graphics g, int x1, int y1, double angle, int depth, int red, int green, int blue)
{
if (depth == 0)
{
Color doodle = new Color(red, green, blue);
g.setColor(doodle);
g.fillOval(x1, y1, 10, 10);
}
else
{
Graphics2D g2 = (Graphics2D) g;
g2.setStroke(new BasicStroke(depth));
Color brown = new Color(100, 25, 0);
g.setColor(brown);
int x2 = x1 + (int) (Math.cos(Math.toRadians(angle)) * depth * 10);
int y2 = y1 + (int) (Math.sin(Math.toRadians(angle)) * depth * 10);
g.drawLine(x1, y1, x2, y2);
drawTree(g, x2, y2, angle - 40, depth - 1, red, green, blue);
drawTree(g, x2, y2, angle + 20, depth - 1, red, green, blue);
}
}
public void realFlowers(Graphics g, int x, int y, int lenWid, int petals)
{
//calculates the increment
double inc = (2*Math.PI/petals);
g.setColor(Color.YELLOW);
//draws petals
for(int i = 0; i < petals; i++){
//keeps spacing consistent depandng on number of petals
double value = i * inc;
//draws petals with calculated spacing relative to number of petals
g.fillOval((int)((lenWid)*Math.cos(value)+x-lenWid/4),(int)((lenWid)*Math.sin(value)+y-lenWid/4), lenWid + lenWid/2, lenWid + lenWid/2);
}
//draws middle flower bud;
g.setColor(Color.ORANGE);
g.fillOval(x - lenWid/4, y - lenWid/4, lenWid + lenWid/2 , lenWid + lenWid/2);
}
public void drawGrass(Graphics g, int width, int height, int interval, int red, int green, int blue)
{
height = frameHeight - height;
Color grass = new Color(red, green, blue);
for(int i = 0; i < width; i= i + interval)
{
for(int j = frameHeight; j > height; j = j - interval)
{
g.setColor(grass);
g.fillRect(i, j, 3, 5);
}
}
}
public void rainDrops(Graphics g, int x, int y, int w, int h)
{
setRain(x, y);
Color rain = new Color(0, 76, 153);
g.setColor(rain);
g.fillRect(x, y, w, h);
}
public void moveRainBy(int dx, int dy)
{
rainX = rainX + dx;
rainY = rainY + dy;
repaint();
}
class TimerListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
moveRainBy(1, 1);
}
}
public void paint(Graphics g) {
setSkyGround(g);
drawGrass(g, 1440, 315, 5, 0, 255, 0);
drawGrass(g, 1430, 310, 10, 0, 204, 0);
drawTree(g, 1085, 730, -90, 10, 255, 102, 102);
drawTree(g, 250, 600, -90, 8, 255, 255, 255);
drawTree(g, 1110, 740, -90, 4, 255, 102, 102);
drawTree(g, 1060, 745, -90, 2, 255, 102, 102);
realFlowers(g, 700,700, 8, 8);
rainDrops(g, 200, 200, 30, 30);
}
public static void main(String[] args) {
new FractalTree().setVisible(true);
}
}
When I try to repaint the square to move, and the paint function is called the whole screen blinks
This is because you've override paint of the a top level container (JFrame) which is not double buffered.
As a general recommendation, you should be basing your core functionality around a JPanel and override it's paintComponent method. Take a look at Performing Custom Painting and Painting in AWT and Swing for more details
You might like to also have a look at How to get the EXACT middle of a screen, even when re-sized and How can I set in the midst? for more details why it's not recommended to extend directly from JFrame and try to paint to it.
Is there a way to keep everything I have drawn from being repainted and just call repaint on the rain?
Painting is destructive, that is, each time paint/paintComponent is called, you are expected to repaint the entire state of the component from scratch.
You could use a buffering technique, using something like BufferedImage to paint your state to and simply have the paint methods draw the image, but that would depend on how complex a solution you want. If you were to use buffering technique, I would consider which elements are "static" and which elements are "dynamic". Painting those static elements to the buffer and then, when paint is called, painting the dynamic elements over the top the buffer

How to move this eye applet or to make it blink?

Please help me how to make this eye move or to make it blink using repaint, thread and implements runnable. I don't know where to place the right codes to make it work. Please help me guys! Thank you!
Here is the code:
import java.awt.*;
import java.applet.*;
public class Pucca extends Applet {
public Pucca(){
setSize(700, 700); }
//paint method
public void paint(Graphics g){
Color white = new Color(255,255,255);
g.setColor(white);
g.fillOval(600, 100, 125, 125); //left white fill eye
g.setColor(Color.BLA­CK);
g.drawOval(600, 100, 125, 125); // left big black line eye
g.setColor(white);
g.fillOval(700, 100, 125, 125); //right white fill eye
g.setColor(Color.BLA­CK);
g.drawOval(700, 100, 125, 125); //right big black line eye
Color blue = new Color(0, 160, 198);
g.setColor(blue);
g.fillOval(635, 130, 51, 51); // left blue fill eye
g.setColor(Color.BLA­CK);
g.drawOval(635, 130, 50, 50); // left black small line eye
g.setColor(blue);
g.fillOval(735, 130, 51, 51); // right blue fill eye
g.setColor(Color.BLA­CK);
g.drawOval(735, 130, 50, 50); // right black small line eye
g.setColor(Color.BLA­CK);
g.fillOval(650, 145, 20, 20); // left black iris
g.setColor(Color.BLA­CK);
g.fillOval(750, 145, 20, 20); // right black iris
}
}
When it comes to animation, everything becomes variable. You also have a lot of repeated code (seriously, if you can paint one eye, you can paint lots).
The first thing you need to is make all the values of the eye as variable as possible.
The follow makes the eye size and position variable and the iris and pupil a scaled value of the eye size, which makes the whole process simpler to animate.
Next, you need an updated loop, which can update the state of the values you want to change. To keep it simple, I've set it up so that the pupil has a variable offset, which is changed over time.
import java.applet.Applet;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
public class Pucca extends Applet {
public Pucca() {
setSize(700, 700);
Thread t = new Thread(new Runnable() {
private int xDelta = -1;
private int yDelta = 0;
private int blinkCount = 0;
#Override
public void run() {
while (true) {
try {
Thread.sleep(40);
} catch (InterruptedException ex) {
}
xOffset += xDelta;
double irisSize = eyeSize.width * irisScale;
double range = ((eyeSize.width - irisSize) / 2);
if (xOffset <= -range) {
xOffset = -(int) range;
xDelta *= -1;
} else if (xOffset >= range) {
xOffset = (int) range;
xDelta *= -1;
}
blinkCount++;
if (blink && blinkCount > 10) {
blink = false;
blinkCount = 0;
} else if (blinkCount > 25) {
blink = true;
blinkCount = 0;
}
repaint();
}
}
});
t.setDaemon(true);
t.start();
}
private boolean blink = false;
private int xOffset, yOffset = 0;
private Dimension eyeSize = new Dimension(125, 125);
private Point left = new Point(20, 20);
private Point right = new Point(left.x + 100, left.y);
private double irisScale = 0.4;
private double pupilScale = 0.16;
//paint method
#Override
public void paint(Graphics g) {
super.paint(g);
paintEye(g, new Rectangle(left, eyeSize));
paintEye(g, new Rectangle(right, eyeSize));
}
protected void paintEye(Graphics g, Rectangle bounds) {
Color white = new Color(255, 255, 255);
if (blink) {
g.setColor(Color.YELLOW);
} else {
g.setColor(white);
}
g.fillOval(bounds.x, bounds.y, bounds.width, bounds.height); //left white fill eye
g.setColor(Color.BLACK);
g.drawOval(bounds.x, bounds.y, bounds.width, bounds.height); // left big black line eye
if (!blink) {
Color blue = new Color(0, 160, 198);
paintEyePartAt(g, bounds, irisScale, blue);
paintEyePartAt(g, bounds, pupilScale, Color.BLACK);
}
}
private void paintEyePartAt(Graphics g, Rectangle bounds, double delta, Color color) {
int width = (int) (bounds.width * delta);
int height = (int) (bounds.height * delta);
g.setColor(color);
g.fillOval(
xOffset + bounds.x + ((bounds.width - width) / 2),
yOffset + bounds.y + ((bounds.height - height) / 2),
width, height); // left blue fill eye
g.setColor(Color.BLACK);
g.drawOval(
xOffset + bounds.x + ((bounds.width - width) / 2),
yOffset + bounds.y + ((bounds.height - height) / 2),
width,
height); // left blue fill eye
}
}
This complicates things, as painting can occur for any number of reasons, many of which you don't have control over or will be notified about, so you should be very careful about where and when you change values.
You should also have a look at Java Plugin support deprecated and Moving to a Plugin-Free Web and Why CS teachers should stop teaching Java applets.
Applets are simply a dead technology and given the inherent complexities involved in using them, you should instead focus you should probably attention towards window based programs.
Personally, I'd start with having a look at Painting in AWT and Swing and Performing Custom Painting

Import EPS in PS - Tools for Adobe Postscript

I'm trying to create a section of a page in EPS and then have that portion of EPS be imported into my PS document at a specific location using Tools for Adobe Postscript: https://xmlgraphics.apache.org/commons/postscript.html
So far I've got a basic generation for the postscript file, and I want to add EPS to it. Here's a pseudo version of what I'd like to do.
OutputStream out = new java.io.FileOutputStream(outputFile);
out = new java.io.BufferedOutputStream(out);
try {
//Instantiate the PSDocumentGraphics2D instance
PSDocumentGraphics2D g2d = new PSDocumentGraphics2D(false);
g2d.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext());
EPSDocumentGraphics2D eg2d = new EPSDocumentGraphics2D(false);
eg2d.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext());
//Set up the document size
g2d.setupDocument(out, pageWidthPT, pageHeightPT);
eg2d.setupDocument(out, 400, 200); //400pt x 200pt
g2d.setFont(new Font(font, Font.PLAIN, fontSize));
//Paint a bounding box
eg2d.drawRect(0, 0, 400, 200);
//A few rectangles rotated and with different color
Graphics2D copy = (Graphics2D)eg2d.create();
int c = 12;
for (int i = 0; i < c; i++) {
float f = ((i + 1) / (float)c);
Color col = new Color(0.0f, 1 - f, 0.0f);
copy.setColor(col);
copy.fillRect(70, 90, 50, 50);
copy.rotate(-2 * Math.PI / (double)c, 70, 90);
}
copy.dispose();
//Some text
eg2d.rotate(-0.25);
eg2d.setColor(Color.RED);
eg2d.setFont(new Font("sans-serif", Font.PLAIN, 36));
eg2d.drawString("Hello world!", 140, 140);
eg2d.setColor(Color.RED.darker());
//Cleanup
eg2d.finish();
g2d.insertEPS(eg2d, 0,0); // something like this?
g2d.nextPage();
g2d.drawString("Hello World!", 10, 20);
g2d.finish();//Cleanup
} finally {
IOUtils.closeQuietly(out);
}
If you know how to accomplish this goal I would appreciate some enlightenment. Thanks.

How to alternate speed using an array of integers for javax swing timer

I am attempting to simulate rain falling using fixed line lengths with randomly generated x coordinates. I have got the random x coordinates working but I want lines to have different falling speeds as well once they are repainted onto the window. I am using the javax swing timer and the java Random to generate integers to pass into my "speed" array as indexes. The speed however does not change. It remains the same and is way too fast.
public class rain extends JPanel implements ActionListener {
int i = 0;
int[] speed = {5, 10, 15, 20, 25, 30, 35, 40, 45, 50};
double[] x = {10, 202, 330, 140, 250, 160, 470, 180, 290, 510};
double y1 = 10, y2 = 20;
double down = 1;
Random random = new Random();
//Timer t = new Timer(speed[i], this);
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D l = (Graphics2D) g;
Line2D line = new Line2D.Double(x[i], y1, x[i], y2);
l.setColor(Color.blue);
l.draw(line);
Timer t = new Timer(speed[i], this);
t.start();
}
public void actionPerformed(ActionEvent e) {
if (y2 < 380) {
y1 += down;
y2 += down;
}else{
y1 = 10;
y2 = 20;
i = random.nextInt(10);
}
repaint();
}
You start a new Timer each time your panel is repainted, and all the previous ones are still running. You should change your algorithm to use a unique timer, and compute the new y based on the previous one and on the current speed.
For example, the time would repaint every 40 milliseconds. If the speed is N, the new y would be the previous one + (N * down)

Categories

Resources