Moving an image across a GUI in java - java

So I have to move my (multiple) images across a GUI, but for whatever reason my paint method is only being called twice, even though my x variable and my timer, which I am using to try and move the image, are incrementing correctly. Any help would be appriciated! Thanks
import javax.swing.*;
import java.awt.*;
import java.lang.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Random;
public class Races extends JFrame
{
public int threadCount = 5;
public int x = 0;
public ImageIcon picture = new ImageIcon("races.jpeg");
public int height = picture.getIconHeight();
public int width = picture.getIconHeight();
public Races(int _threadCount)
{
threadCount = _threadCount;
int counter = 0;
while(counter<threadCount)
{
(new Thread(new RacesInner(threadCount))).start();
counter++;
}
initialize();
}
public static void main(String[] args)
{
if(args.length == 0)
{
JFrame f = new Races(5);
}
else
{
JFrame f = new Races(Integer.parseInt(args[0]));
}
}
public void initialize()
{
this.setVisible(true);
this.setTitle("Off to the Races - By ");
RacesInner inner = new RacesInner(threadCount);
this.add(inner);
this.setSize((width*20),(height*3)*threadCount);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.repaint();
}
protected class RacesInner extends JPanel implements Runnable
{
public int j = (int)(Math.random() * 50) + 20;
public void timer()
{
Timer timer1 = new Timer(j, new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
x += 2;
repaint();
}
});
timer1.start();
}
public void run()
{
timer();
}
#Override
public void paint(Graphics g)
{
super.paintComponent(g);
//drawing the correct amount of icons based on input(or lack of input, default 5)
//Get the current size of this component
Dimension d = this.getSize();
//draw in black
g.setColor(Color.BLACK);
//calculating where finish line should be and drawing the line
int finishLine;
finishLine = (width*20)-(width*2);
g.drawLine(finishLine,0,finishLine,2000);
for(int i =0; i<threadCount; i++)
{
picture.paintIcon(this,g,1+x,(50*i));
}
}
public RacesInner(int _threadCount)
{
threadCount = _threadCount;
System.out.println(threadCount);
//JPanel
this.setVisible(true);
this.setLayout(new GridLayout(threadCount,1));
}
}//closes RacesInner class
}//closes races class

Related

Loop drawing rectangles

I am trying to make a basic tetris game, first I am looking to draw a grid to make sure that I am creating blocks as I want to, however I can't get my program to access my paintComponent method.
package tetris;
import javax.swing.*;
import java.awt.*;
public class TetrisMain extends JFrame {
final int BoardWidth = 10;
final int BoardHeight = 20;
public static int HEIGHT = 400;
public static int WIDTH = 200;
Timer timer;
boolean isFallingFinished = false;
boolean isStarted = false;
boolean isPaused = false;
int score = 0;
int curX = 0;
int curY = 0;
int[][] grid = new int[BoardWidth][BoardHeight];
public static void main(String[] args) {
JFrame frame = new JFrame("Charles Walker - 1504185");
frame.setSize(WIDTH, HEIGHT);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setVisible(true);
frame.repaint();
}
public void paintComponent(Graphics g) {
super.paintComponents(g);
g.setColor(Color.BLACK);
for (int i = 0; i < BoardWidth; i++) {
for (int j = 0; j < BoardHeight; j++) {
curX = grid[i][curY];
curY = grid[curX][j];
g.fillRect(WIDTH / BoardWidth, HEIGHT / BoardHeight, curX, curY);
}
}
}
}
Here is a basic code to do what you want :
import javax.swing.JFrame;
import java.awt.Graphics;
import javax.swing.JPanel;
import javax.swing.*;
public class Name extends JFrame {
public Name() {
super("Name");
setTitle("Application");
setContentPane(new Pane());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400,400);
setResizable(true);
setVisible(true);
while (true){
try { //Update screen every 33 miliseconds = 25 FPS
Thread.sleep(33);
} catch(InterruptedException bug) {
Thread.currentThread().interrupt();
System.out.println(bug);
}
repaint();
}
}
class Pane extends JPanel {
public void paintComponent(Graphics g) { //Here is were you can draw your stuff
g.drawString("Hello World",0,20); //Display text
}
}
public static void main(String[] args){
new Name();
}
}
I think you forgot that line to set the content pane :
setContentPane(new Pane());
and, important, you need a while loop to redraw :
while (true){
try { //Update screen every 33 miliseconds = 25 FPS
Thread.sleep(33);
} catch(InterruptedException bug) {
Thread.currentThread().interrupt();
System.out.println(bug);
}
repaint();
}

how do i make a JPanel background that won't update?

I'm trying to make an animated screensaver with some changing colors and moving shapes and I also want it to have a sort of trail effect (like how the most recent color on each pixel is continually drawn there if you don't set your background color). I achieved this effect once before, but I don't know how I did it. Currently the result is a moving square with that changes colors across a grey background.
ScreenSaver.java
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JPanel;
import javax.swing.Timer;
public class ScreenSaver extends JPanel
{
public static Component sc;
public int delay = 1000/2;
public int state = 0;
public int re = 255;
public int gr = 0;
public int bl = 0;
public int d = 1;
ScreenSaver()
{
ActionListener counter = new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
updateUI();
repaint();
}
};
new Timer(delay, counter).start();
System.out.println("this is the secret screensaver that appears after 30 seconds of no mouse activity");//i have this line here so it doesn't print every time the screen updates
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
this.setBackground(null);
if (state == 0)
{
gr++;
if(gr == 255)
state = 1;
}
if (state == 1)
{
re--;
if(re == 0)
state = 2;
}
if (state == 2)
{
bl++;
if(bl == 255)
state = 3;
}
if (state == 3)
{
gr--;
if(gr == 0)
state = 4;
}
if (state == 4)
{
re++;
if(re == 255)
state = 5;
}
if (state == 5)
{
bl--;
if(bl == 0)
state = 0;
}
g.setColor(new Color(re, gr, bl));
d++;
g.fillRect(d, 50, 50, 50);
}
public static void main(String[] args)
{
//ScreenSaver sc = new ScreenSaver();
}
}
Main.java: (ScreenSaver.java is called as an object through this file)
import java.awt.Color;
import java.awt.Graphics;
//import java.util.Random;
//import javax.swing.AbstractAction;
//import javax.swing.Action;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import javax.swing.Timer;
public class FinalProject extends JPanel implements MouseMotionListener
{
public int delay = 1000/2;
public boolean screenActive = true;
public int why = 1;
FinalProject()
{
ActionListener counter = new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
updateUI();
repaint();
}
};
new Timer(delay, counter).start();
}
static JFrame jf = new JFrame();
public void paintComponent(Graphics g)
{
super.paintComponent(g);
this.setBackground(Color.BLACK);
if (screenActive)
{
why++;
}
if (why == 6)
{
why = 0;
System.out.println("inactivity detected");
screenActive = false;
ScreenSaver sc = new ScreenSaver();
jf.add(sc);
}
}
public static void main(String[] args) throws InterruptedException
{
System.out.println("Welcome to Computer Simulator 0.1");
System.out.println("this is the main screen");
FinalProject e = new FinalProject();
//ScreenSaver sc = new ScreenSaver();
jf.setTitle("game");
jf.setSize(500,500);
//jf.setUndecorated(true);
//jf.setBackground(new Color(1.0f,1.0f,1.0f,0.5f));
jf.setVisible(true);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//jf.add(new ScreenSaver());
jf.add(e);
}
#Override
public void mouseDragged(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseMoved(MouseEvent MOUSE_MOVED)
{
}
}
Don't invoke updateUI(). All you need is the repaint() to cause the component to repaint itself.
One way it to do the drawing to a BufferedImage and then use the BufferedImage to create an ImageIcon which you add to a JLabel.
The other way is to keep a list of object that you want to paint and then just iterate through the list each time the component is repainted.
Check out Custom Painting Approches for working examples and an analysis of when you might use either approach.

Attempting to animate multiple images in Java using JFrame & JPanel

So I'm attempting to rotate an image using animation by having it change images to a new one that has been rotated 22.5 degrees. I'm doing this by having 1 class inheriting from a JFrame and the other class from a JPanel However it is not doing anything. Here is the code..
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.Graphics;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.Timer;
import java.awt.event.*;
public class LogoAnimatorJPanel extends JPanel implements ActionListener
{
protected ImageIcon[] images = new ImageIcon[16] ;
private int currentImage = 0;
private Timer animationTimer;
public LogoAnimatorJPanel()
{
for ( int count = 0; count < images.length; count++ ){
images [count] = new ImageIcon("car/yellowCar" + count + ".jpg");
}
startAnimation();
}
public void paintComponent( Graphics g )
{
super.paintComponent( g );
images[ currentImage ].paintIcon( this, g, 50 , 50 );
currentImage = ( currentImage + 1 ) % images.length;
}
public void startAnimation()
{
animationTimer = new Timer(20, this);
animationTimer.start();
}
public void actionPerformed( ActionEvent actionEvent )
{
repaint();
}
}
displayAnimator
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class displayAnimator extends JFrame
{
private LogoAnimatorJPanel fp;
public displayAnimator()
{
setTitle("car");
setBounds(200,200,200,200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container cp = getContentPane();
cp.setLayout(null);
fp = new LogoAnimatorJPanel();
fp.setBounds(180, 25, 100, 100);
cp.add(fp);
}
public static void main(String[] args)
{
displayAnimator testRun = new displayAnimator();
testRun.setVisible(true);
}
}
Any Ideas?
Here is a working demo. of the things I was discussing above, along with a few more tweaks. Read code carefully for changes, do some research on the new/different method calls, and ask if you don't understand (from that research) why I included them. Note that this class includes a main method.
import java.awt.Image;
import java.awt.event.*;
import java.net.*;
import javax.imageio.ImageIO;
import javax.swing.*;
public class LogoAnimator {
private int currentImage = 0;
private JLabel animationDisplayLabel = new JLabel();
private Timer animationTimer;
private String prefix = "http://i.stack.imgur.com/";
private String suffix = ".png";
private String[] imageNames = {"gJmeJ", "L5DGx", "in9g1", "IucNt", "yoKxT"};
protected ImageIcon[] images = new ImageIcon[imageNames.length];
public LogoAnimator() {
for (int count = 0; count < images.length; count++) {
try {
URL url = new URL(prefix + imageNames[count] + suffix);
Image image = ImageIO.read(url);
images[count] = new ImageIcon(image);
} catch (Exception ex) { // TODO! Better exception handling!
ex.printStackTrace();
}
}
startAnimation();
}
public void startAnimation() {
ActionListener listener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
currentImage = (currentImage + 1) % images.length;
animationDisplayLabel.setIcon(images[currentImage]);
}
};
animationDisplayLabel.setIcon(images[0]);
animationTimer = new Timer(200, listener);
animationTimer.start();
}
public JComponent getAnimationComponent() {
return animationDisplayLabel;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
LogoAnimator fp = new LogoAnimator();
JFrame f = new JFrame("car");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(fp.getAnimationComponent());
f.pack();
f.setLocationByPlatform(true);
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}

Pause Graphics?

So I have this JPanel Graphics code:
public void paint(Graphics g){
super.paint(g);
for(int y=0 ;y < 50; y++){
for(int x = 0; x < 50; x++){
if(m.getMaze(x, y).equals("g")){
g.drawImage(m.getGround(), x * 16, y * 16,null);
}
if(m.getMaze(x, y).equals("w")){
g.drawImage(m.getWall(), x * 16, y * 16,null);
}
if(m.getMaze(x, y).equals("S")){
g.drawImage(m.getStart(), x * 16, y * 16,null);
}
if(m.getMaze(x, y).equals("E")){
g.drawImage(m.getEnd(), x * 16, y * 16,null);
}
}
}
}
And inside the for loop (the second one) I would like to pause it for half a second, so you can see it drawing each tile. The thing is, is when I use
Thread.sleep(500);
After the second for loop, it just stops the whole thing forever. If I use
g.wait(500);
it keeps spamming
java.lang.IllegalMonitorStateException
in the console. And yes, it is surrounded with try/catch. How can I pause this?
On a swing Timer call repaint(50L, x*16, y*16, 16, 16);. Use fields for the current state (x, y),
and on every paintComponent draw only that state/tile.
1) use paintComponent() method for custom paintings intead of paint(). Read about custom paintings in java
2) Don't block EDT with Thread.sleep(500); or g.wait(500);.
Seems you need to use swing Timer for loading. Here is simple example:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class TestFrame extends JFrame {
private Timer timer;
public TestFrame() {
init();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setLocationRelativeTo(null);
setVisible(true);
}
private void init() {
final DrawPanel p = new DrawPanel();
timer = new Timer(500, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(p.drawingTiles < 16){
p.addDrawingTile();
p.repaint();
} else {
timer.stop();
System.out.println("done");
}
}
});
timer.start();
add(p);
}
public static void main(String args[]) {
new TestFrame();
}
private class DrawPanel extends JPanel{
protected int drawingTiles = 0;
private int tiles[][] = new int[4][4];
public DrawPanel(){
Random r = new Random();
for(int i=0;i<tiles.length;i++){
for(int j=0;j<tiles.length;j++){
tiles[i][j] = r.nextInt(5);
}
}
}
public void addDrawingTile() {
drawingTiles++;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int curTiles = 0;
for(int i=0;i<tiles.length;i++){
for(int j=0;j<tiles.length;j++){
if(curTiles <drawingTiles){
curTiles++;
g.drawString(tiles[i][j]+"", (j+1)*10, (i+1)*10);
}
}
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(50,50);
}
}
}

Java applet repaint a moving circle

I've just moved over from Pygame so Java 2D in an applet is a little new to me, especially when it comes to repainting the screen. In pygame you can simply do display.fill([1,1,1]) but how do I do this in an applet in Java? I understand the use of repaint() but that doesn't clear the screen - any moving object is not 'removed' from the screen so you just get a long line of painted circles.
Here's my code that I've been testing with:
package circles;
import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.Random;
public class circles extends Applet implements Runnable {
private static final long serialVersionUID = -6945236773451552299L;
static Random r = new Random();
String msg = "Click to play!";
static int w = 800, h = 800;
int[] txtPos = { (w/2)-50,(h/2)-50 };
int[] radiusRange = { 5,25 };
int[] circles;
static int[] posRange;
int x = 0, y = 0;
int radius = 0;
int cursorRadius = 10;
boolean game = false;
public static int[] pos() {
int side = r.nextInt(5-1)+1;
switch(side) {
case 1:
posRange = new int[]{ 1,r.nextInt(w),r.nextInt((h+40)-h)+h,r.nextInt(270-90)+90 };
break;
case 2:
posRange = new int[]{ 2,r.nextInt((w+40)-w)+w,r.nextInt(h),r.nextInt(270-90)+90 };
break;
case 3:
posRange = new int[]{ 3,r.nextInt(w),r.nextInt(40)-40,r.nextInt(180) };
break;
case 4:
posRange = new int[]{ 4,r.nextInt(40)-40,r.nextInt(h),r.nextInt(180) };
break;
}
System.out.println(side);
return posRange;
}
public void start() {
setSize(500,500);
setBackground(Color.BLACK);
new Thread(this).start();
}
public void run() {
}
public void update(Graphics g) {
paint(g);
}
public void paint(Graphics e) {
Graphics2D g = (Graphics2D) e;
if(System.currentTimeMillis()%113==0) {
x+=1;
y+=1;
}
g.setColor(Color.BLUE);
g.fillOval(x,y,20,20);
repaint();
}
}
You need to call super.paint(g); in your paint method, as to not leave paint artifacts.
Never call repaint() from inside the paint method
Don't explicitly call paint, as you do in update(), when you mean to call reapaint()
just update the x and y values from inside the update() method, then call repaint()
You don't need to take a Graphics argument in update()
You need to call update() somewhere repeatedly in a loop, as it updates the x and y and reapint()s
If your class is going to be a Runnable, then you should put some code in the run() method. That's probably where you should have your loop
import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
public class circles extends Applet implements Runnable {
int x = 0, y = 0;
public void start() {
setSize(500, 500);
setBackground(Color.BLACK);
new Thread(this).start();
}
public void run() {
while (true) {
try {
update();
Thread.sleep(50);
} catch (InterruptedException ex) {
}
}
}
public void update() {
x += 5;
y += 6;
repaint();
}
public void paint(Graphics e) {
super.paint(e);
Graphics2D g = (Graphics2D) e;
g.setColor(Color.BLUE);
g.fillOval(x, y, 20, 20);
}
}
Side Notes
Why use Applets in the first place. If you must, why use AWT Applet and not Swing JApplet? Time for an upgrade.
Here's how I'd redo the whole thing in Swing, using a Swing Timer instead of a loop and Thread.sleep, as you should be doing.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class Circle extends JPanel{
private static final int D_W = 500;
private static final int D_H = 500;
int x = 0;
int y = 0;
public Circle() {
setBackground(Color.BLACK);
Timer timer = new Timer(50, new ActionListener(){
public void actionPerformed(ActionEvent e) {
x += 5;
y += 5;
repaint();
}
});
timer.start();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLUE);
g.fillOval(x, y, 20, 20);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(D_W, D_H);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
frame.add(new Circle());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
See How to use Swing Timers
See Create GUIs with Swing
Here's more advanced example for you to look at and ponder.
UPDATE
"Problem is, that's a JPANEL application. I specifically want to make an applet easily usable on a web page. "
You can still use it. Just use the JPanel. Take out the main method, and instead of Applet, use a JApplet and just add the JPanel to your applet. Easy as that.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JApplet;
import javax.swing.JPanel;
import javax.swing.Timer;
public class CircleApplet extends JApplet {
#Override
public void init() {
add(new Circle());
}
public class Circle extends JPanel {
private static final int D_W = 500;
private static final int D_H = 500;
int x = 0;
int y = 0;
public Circle() {
setBackground(Color.BLACK);
Timer timer = new Timer(50, new ActionListener() {
public void actionPerformed(ActionEvent e) {
x += 5;
y += 5;
repaint();
}
});
timer.start();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLUE);
g.fillOval(x, y, 20, 20);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(D_W, D_H);
}
}
}

Categories

Resources