How can I create basic animation in Java?
Currently i am trying to implement a basic animation program using swing in Java.
But i am not getting whether my logic for program in correct or not.
My program implements Runnable, ActionListener interfaces and also extends JApplet.
I want to know that, is it necessary to differentiate start method of JApplet and Runnable?
And if yes then why..?
My program is basic balloon program, when I click on start button balloons start moving upward and comes to floor again. This will be continue till i press stop button.
Here is my code.
public class Balls extends JApplet implements Runnable{
private static final long serialVersionUID = 1L;
JPanel btnPanel=new JPanel();
static boolean flag1=true;
static boolean flag2=true;
static boolean flag3=false;
static int h;
static int temp=10;
Thread t=new Thread(this);
JButton start;
JButton stop;
public void init()
{
try
{
SwingUtilities.invokeAndWait(
new Runnable()
{
public void run()
{
makeGUI();
}
});
}
catch(Exception e)
{
JOptionPane.showMessageDialog(null,"Can't create GUI because of exception");
System.exit(0);
}
}
private void makeGUI() {
start=new JButton("start");
stop=new JButton("stop");
btnPanel.add(start);
btnPanel.add(stop);
add(btnPanel,BorderLayout.NORTH);
}
public void run()
{
while(true)
{
if(flag1)
{
repaint();
flag1=false;
}
else
{
try
{
wait();
flag3=true;
}
catch(InterruptedException e)
{
JOptionPane.showMessageDialog(null,"Error ocuured !!\n Exiting..");
System.exit(0);
}
}
}
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
int h=Integer.parseInt(getParameter("height"));
if (flag1)
{
g.setColor(Color.RED);
g.fillOval(10,h,50,50);
g.setColor(Color.YELLOW);
g.fillOval(50,h,20,20);
g.setColor(Color.CYAN);
g.fillOval(70,h,80,30);
g.setColor(Color.BLUE);
g.fillOval(120,h,50,60);
g.setColor(Color.GRAY);
g.fillOval(160,h,70,50);
g.setColor(Color.GREEN);
g.fillOval(200,h,80,80);
g.setColor(Color.MAGENTA);
g.fillOval(260,h,80,30);
g.setColor(Color.DARK_GRAY);
g.fillOval(320,h,60,40);
g.setColor(Color.pink);
g.fillOval(370,h,65,45);
flag1=false;
}
else
{
g.setColor(Color.RED);
g.fillOval(10,h-temp,50,50);
g.setColor(Color.YELLOW);
g.fillOval(50,h-temp,20,20);
g.setColor(Color.CYAN);
g.fillOval(70,h-temp,80,30);
g.setColor(Color.BLUE);
g.fillOval(120,355,50,60);
g.setColor(Color.GRAY);
g.fillOval(160,h-temp,70,50);
g.setColor(Color.GREEN);
g.fillOval(200,h-temp,80,80);
g.setColor(Color.MAGENTA);
g.fillOval(260,h-temp,80,30);
g.setColor(Color.DARK_GRAY);
g.fillOval(320,h-temp,60,40);
g.setColor(Color.pink);
g.fillOval(370,h-temp,65,45);
if(flag2 && temp<=400)
{
temp+=10;
if(temp==400)
{
flag2=false;
}
}
else if(!flag2)
{
temp-=10;
if(temp==10)
{
flag2=true;
}
}
else
{
}
}
}
public void start()
{
start.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
t.start();
if(flag3)
{
notify();
}
}
});
stop.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
flag1=false;
try
{
Thread.sleep(5000);
}
catch(InterruptedException e)
{
repaint();
t=null;
}
}
});
}
}
1) Use SwingTimer as recommended instead of your Runnable implementation.
2) Read about custom painting , and here
3) draw at the JPanel instead of on JFrame
I have changed your code, examine it. I think, that it does what you want.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class Balls extends JApplet {
private static final long serialVersionUID = 1L;
JPanel btnPanel = new JPanel();
static boolean flag1 = true;
static boolean flag2 = true;
static boolean flag3 = false;
static int h;
static int temp = 10;
JButton start;
JButton stop;
private Timer timer;
public void init() {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
makeGUI();
}
});
}
private void makeGUI() {
timer = new Timer(10, new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
repaint();
}
});
start = new JButton("start");
stop = new JButton("stop");
start.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
timer.start();
}
});
stop.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
timer.stop();
}
});
btnPanel.add(start);
btnPanel.add(stop);
add(new MyPanel(), BorderLayout.CENTER);
add(btnPanel, BorderLayout.NORTH);
}
class MyPanel extends JPanel{
public void paintComponent(Graphics g) {
super.paintComponent(g);
int h = Integer.parseInt(getParameter("height"));
if (flag1) {
g.setColor(Color.RED);
g.fillOval(10, h, 50, 50);
g.setColor(Color.YELLOW);
g.fillOval(50, h, 20, 20);
g.setColor(Color.CYAN);
g.fillOval(70, h, 80, 30);
g.setColor(Color.BLUE);
g.fillOval(120, h, 50, 60);
g.setColor(Color.GRAY);
g.fillOval(160, h, 70, 50);
g.setColor(Color.GREEN);
g.fillOval(200, h, 80, 80);
g.setColor(Color.MAGENTA);
g.fillOval(260, h, 80, 30);
g.setColor(Color.DARK_GRAY);
g.fillOval(320, h, 60, 40);
g.setColor(Color.pink);
g.fillOval(370, h, 65, 45);
flag1 = false;
} else {
g.setColor(Color.RED);
g.fillOval(10, h - temp, 50, 50);
g.setColor(Color.YELLOW);
g.fillOval(50, h - temp, 20, 20);
g.setColor(Color.CYAN);
g.fillOval(70, h - temp, 80, 30);
g.setColor(Color.BLUE);
g.fillOval(120, 355, 50, 60);
g.setColor(Color.GRAY);
g.fillOval(160, h - temp, 70, 50);
g.setColor(Color.GREEN);
g.fillOval(200, h - temp, 80, 80);
g.setColor(Color.MAGENTA);
g.fillOval(260, h - temp, 80, 30);
g.setColor(Color.DARK_GRAY);
g.fillOval(320, h - temp, 60, 40);
g.setColor(Color.pink);
g.fillOval(370, h - temp, 65, 45);
if (flag2 && temp <= 400) {
temp += 10;
if (temp == 400) {
flag2 = false;
}
} else if (!flag2) {
temp -= 10;
if (temp == 10) {
flag2 = true;
}
} else {
}
}
}
}
}
Related
Cannot put my game into the GUI without there being issues. When starting the GUI, it shows the game. It glitches out and only fixes after pressing on of the buttons. However the buttons are hidden unless you put your mouse over it. Here is the code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.util.*;
public class BBSays extends JFrame implements ActionListener, MouseListener
{
private BufferedImage image;
public static BBSays bbsays;
public Renderer renderer;
public static final int WIDTH = 800, HEIGHT = 800;
public int flashed = 0, glowTime, dark, ticks, indexPattern;
public boolean creatingPattern = true;
public ArrayList<Integer> pattern;
public Random random;
private boolean gameOver;
private JPanel game;
JFrame frame = new JFrame("BB8 Says");
private JPanel menu;
private JPanel credits;
ImageIcon bbegif = new ImageIcon("tumblr_o0c57n9gfv1tha1vgo1_r3_250.gif");
public BBSays()
{
Timer timer = new Timer(20, this);
renderer = new Renderer();
frame.setSize(WIDTH +7, HEIGHT +30);
frame.setVisible(true);
frame.addMouseListener(this);
frame.add(renderer);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE );
start();
timer.start();
menu = new JPanel();
credits = new JPanel();
game = new JPanel();
menu.setBackground(Color.yellow);
credits.setBackground(Color.yellow);
game.setBackground(Color.yellow);
JButton button = new JButton("Start");
JButton button2 = new JButton("Exit");
JButton button4 = new JButton("Start");
JLabel greet = new JLabel(" Welcome to BB8 Says");
JLabel jif = new JLabel(bbegif);
JLabel jif2 = new JLabel(bbegif);
JLabel saus = new JLabel("BB8 Image: https://49.media.tumblr.com/7ba3be87bff2efc009e9cfa889d46b4e/tumblr_o0c57n9gfv1tha1vgo1_r3_250.gif");
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
frame.setContentPane(game);
frame.invalidate();
frame.validate();
};
});
button2.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
System.exit(0);
};
});
menu.setLayout(new GridLayout(2,2));
menu.add(jif2);
menu.add(greet);
menu.add(jif);
menu.add(button);
menu.add(button6);
menu.add(button2);
frame.setVisible(true);
}
private class MenuAction implements ActionListener {
private JPanel panel;
private MenuAction(JPanel pnl) {
this.panel = pnl;
}
#Override
public void actionPerformed(ActionEvent e) {
changePanel(panel);
}
}
private void changePanel(JPanel panel) {
getContentPane().removeAll();
getContentPane().add(panel, BorderLayout.CENTER);
getContentPane().doLayout();
update(getGraphics());
}
public void start()
{
random = new Random();
pattern = new ArrayList<Integer>();
indexPattern = 0;
dark = 2;
flashed = 0;
ticks = 0;
}
public static void main(String[] args)
{
bbsays = new BBSays();
}
#Override
public void actionPerformed(ActionEvent e)
{
ticks++;
if (ticks % 20 == 0)
{
flashed = 0;
if (dark >= 0)
{
dark--;
}
}
if (creatingPattern)
{
if (dark <= 0)
{
if (indexPattern >= pattern.size())
{
flashed = random.nextInt(40) % 4 + 1;
pattern.add(flashed);
indexPattern = 0;
creatingPattern = false;
}
else
{
flashed = pattern.get(indexPattern);
indexPattern++;
}
dark = 2;
}
}
else if (indexPattern == pattern.size())
{
creatingPattern = true;
indexPattern = 0;
dark = 2;
}
renderer.repaint();
}
public void paint(Graphics2D g)
{
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(Color.yellow);
g.fillRect(0, 0, WIDTH, HEIGHT);
if (flashed == 1)
{
g.setColor(Color.blue);
}
else
{
g.setColor(Color.blue.darker());
}
g.fillRect(0, 0, WIDTH/2, HEIGHT/2);
if (flashed == 2)
{
g.setColor(Color.green);
}
else
{
g.setColor(Color.green.darker());
}
g.fillRect(WIDTH/2, 0, WIDTH/2, HEIGHT/2);
if (flashed == 3)
{
g.setColor(Color.orange);
}
else
{
g.setColor(Color.orange.darker());
}
g.fillRect(0, HEIGHT/2, WIDTH/2, HEIGHT/2);
if (flashed == 4)
{
g.setColor(Color.gray);
}
else
{
g.setColor(Color.gray.darker());
}
g.fillRect(WIDTH/2, HEIGHT/2, WIDTH/2, HEIGHT/2);
g.setColor(Color.BLACK);
g.fillRoundRect(220, 220, 350, 350, 300, 300);
g.fillRect(WIDTH/2 - WIDTH/14, 0, WIDTH/7, HEIGHT);
g.fillRect(0, WIDTH/2 - WIDTH/12, WIDTH, HEIGHT/7);
g.setColor(Color.yellow);
g.setStroke(new BasicStroke(200));
g.drawOval(-100, -100, WIDTH+200, HEIGHT+200);
g.setColor(Color.black);
g.setStroke(new BasicStroke(5));
g.drawOval(0, 0, WIDTH, HEIGHT);
if (gameOver)
{
g.setColor(Color.WHITE);
g.setFont(new Font("Comic Sans", 1, 80));
g.drawString("You let", WIDTH / 2 - 140, HEIGHT / 2 - 70);
g.drawString("down BB8 :(", WIDTH / 2 - 220, HEIGHT / 2 );
g.drawString("Try again!", WIDTH / 2 - 195, HEIGHT / 2 + 80);
}
else
{
g.setColor(Color.WHITE);
g.setFont(new Font("Ariel", 1, 144));
g.drawString(indexPattern + "/" + pattern.size(), WIDTH / 2 - 100, HEIGHT / 2 + 42);
}
}
#Override
public void mousePressed(MouseEvent e)
{
int x = e.getX(), y = e.getY();
if (!creatingPattern && !gameOver)
{
if (x>0 && x<WIDTH/2 && y>0 && y<HEIGHT/2)
{
flashed = 1;
ticks = 1;
}
else if (x>WIDTH/2 && x<WIDTH && y>0 && y<HEIGHT/2)
{
flashed = 2;
ticks = 1;
}
else if (x>0 && x<WIDTH/2 && y>HEIGHT/2 && y<HEIGHT)
{
flashed = 3;
ticks = 1;
}
else if (x>WIDTH/2 && x<WIDTH && y>HEIGHT/2 && y<HEIGHT)
{
flashed = 4;
ticks = 1;
}
if (flashed != 0)
{
if (pattern.get(indexPattern)==flashed)
{
indexPattern++;
}
else
{
gameOver = true;
}
}
else
{
start();
gameOver = true;
}
}
else if (gameOver)
{
start();
gameOver = false;
}
}
Here is the code for the renderer class:
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;
public class Renderer extends JPanel
{
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
if (BBSays.bbsays != null)
{
BBSays.bbsays.paint((Graphics2D) g);
}
}
}
I think that the issue is here as I use the super. method and want to put the graphics on the game JPanel in the main code. I have tried many ways of doing this but I am not able to put the game on a JPanel.
If you can help it is greatly appreciated.
So the answer to this might be completely obvious, but I just can't see it. Why is my Graphics object not displaying what I tell it to? I'm fairly certain I'm honoring Swing concurrency and such but perhaps not. Here's my JPanel code:
package com.kraken.towerdefense.graphics;
import com.kraken.towerdefense.TowerDefense;
import com.kraken.towerdefense.listener.KeyHandler;
import com.kraken.towerdefense.listener.MouseMotionHandler;
import com.kraken.towerdefense.scene.Scene;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
public class Screen extends JPanel implements Runnable {
Thread thread = new Thread(this);
private int FPS = 0;
public Scene scene;
TowerDefense tD;
private boolean running = false;
public RoundRectangle2D.Float playGame, quitGame;
public boolean playGameHighlighted, quitGameHighlighted;
#Override
public void run() {
long lastFrame = System.currentTimeMillis();
int frames = 0;
running = true;
while (running) {
repaint();
frames++;
if (System.currentTimeMillis() - 1000 >= lastFrame) {
FPS = frames;
frames = 0;
lastFrame = System.currentTimeMillis();
}
}
System.exit(0);
}
public Screen(TowerDefense tD) {
thread.start();
addKeyListener(new KeyHandler(this));
addMouseMotionListener(new MouseMotionHandler(this));
this.tD = tD;
scene = Scene.MENU;
}
#Override
public void paintComponent(Graphics g2) {
super.paintComponent(g2);
playGame = new RoundRectangle2D.Float((getWidth() / 2) - 200, (getHeight() / 2) - 100, 400, 100, 10, 10);
quitGame = new RoundRectangle2D.Float((getWidth() / 2) - 200, (getHeight() / 2) + 20, 400, 100, 10, 10);
Graphics2D g = (Graphics2D) g2.create();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.clearRect(0, 0, getWidth(), getHeight());
g.drawString("FPS: " + FPS, 10, 10);
if (scene == Scene.MENU) {
if (playGameHighlighted) {
g.setColor(new Color(255, 152, 56));
} else {
g.setColor(new Color(4, 47, 61));
}
g.fill(playGame);
if (quitGameHighlighted) {
g.setColor(new Color(255, 152, 56));
} else {
g.setColor(new Color(4, 47, 61));
}
g.fill(quitGame);
g.setColor(Color.WHITE);
g.setFont(new Font("Gisha", Font.PLAIN, 20));
g.drawString("Play", (getWidth() / 2) - (g.getFontMetrics().stringWidth("Play") / 2), (getHeight() / 2) - 45);
g.drawString("Quit", (getWidth() / 2) - (g.getFontMetrics().stringWidth("Quit") / 2), (getHeight() / 2) + 75);
}
}
public class KeyTyped {
public void keyESC() {
running = false;
}
}
}
And here's my Scene Enum:
package com.kraken.towerdefense.scene;
public enum Scene {
MENU,
GAME
}
I'm pretty sure I don't need to supply the JFrame code, but if necessary I will. Any other solutions to problems in my code you could give would be greatly appreciated. Thanks!
EDIT 1
Here's my MouseMotionListener class:
package com.kraken.towerdefense.listener;
import com.kraken.towerdefense.graphics.Screen;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
public class MouseMotionHandler implements MouseMotionListener {
Screen screen;
public MouseMotionHandler(Screen screen) {
this.screen = screen;
}
#Override
public void mouseDragged(MouseEvent e) {
}
#Override
public void mouseMoved(MouseEvent e) {
if (screen.playGame.contains(e.getPoint())) {
screen.playGameHighlighted = true;
} else {
screen.playGameHighlighted = false;
}
if (screen.quitGame.contains(e.getPoint())) {
screen.quitGameHighlighted = true;
} else {
screen.playGameHighlighted = false;
}
}
}
Here's my JFrame code:
package com.kraken.towerdefense;
import com.kraken.towerdefense.graphics.Screen;
import javax.swing.*;
public class TowerDefense extends JFrame {
public static void main(String[] args) {
new TowerDefense();
}
public TowerDefense() {
setExtendedState(MAXIMIZED_BOTH);
setUndecorated(true);
setTitle("Tower Defense");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setResizable(false);
Screen screen = new Screen(this);
this.add(screen);
setVisible(true);
}
}
And here's my KeyListener code:
package com.kraken.towerdefense.listener;
import com.kraken.towerdefense.graphics.Screen;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class KeyHandler implements KeyListener {
private Screen screen;
private Screen.KeyTyped keyTyped;
public KeyHandler(Screen screen) {
this.screen = screen;
keyTyped = screen.new KeyTyped();
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == 27) {
keyTyped.keyESC();
}
}
#Override
public void keyReleased(KeyEvent e) {
}
}
So those are all my classes, I hope that helps
So, I gutted your code to make it run and was capable of displaying...
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class GraphicsTest {
public static void main(String[] args) {
new GraphicsTest();
}
public GraphicsTest() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Screen());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public enum Scene {
MENU,
GAME
}
public class Screen extends JPanel implements Runnable {
Thread thread = new Thread(this);
private int FPS = 0;
public Scene scene;
private boolean running = false;
#Override
public void run() {
long lastFrame = System.currentTimeMillis();
int frames = 0;
running = true;
scene = Scene.MENU;
while (running) {
repaint();
frames++;
if (System.currentTimeMillis() - 1000 >= lastFrame) {
FPS = frames;
frames = 0;
lastFrame = System.currentTimeMillis();
}
}
System.exit(0);
}
public Screen() {
thread.start();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.clearRect(0, 0, getWidth(), getHeight());
g.drawString("FPS: " + FPS, 10, 10);
if (scene == Scene.MENU) {
g.setColor(Color.BLACK);
g.fillRoundRect((getWidth() / 2) - 100, (getHeight() / 2) - 50, 200, 100, 25, 25);
}
}
}
}
So that suggests that the problem you're describing is some where else.
To me this;
g.clearRect(0, 0, tD.getWidth(), tD.getHeight());
looks suspicious, as you're relying on the TowerDefense properties when you should relying on the components own width/height properties (apart from clearRect actually not been required in this context).
This further makes me suspicious that you're not actually adding the Screen component to anything that is displayable
The other possible problem is you're making use of an appropriate layout manager, but since your Screen class doesn't supply any preferredSize hints, this would be an additional issue which you're not demonstrating
Updated based on changes to the original question
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import static java.awt.Frame.MAXIMIZED_BOTH;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.RoundRectangle2D;
import javafx.scene.Scene;
import javax.swing.JFrame;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import javax.swing.JPanel;
public class TowerDefense extends JFrame {
public static void main(String[] args) {
new TowerDefense();
}
public TowerDefense() {
// setExtendedState(MAXIMIZED_BOTH);
// setUndecorated(true);
setTitle("Tower Defense");
setDefaultCloseOperation(EXIT_ON_CLOSE);
// setResizable(false);
Screen screen = new Screen(this);
this.add(screen);
pack();
setVisible(true);
}
public enum Scene {
MENU,
GAME
}
public class Screen extends JPanel implements Runnable {
Thread thread = new Thread(this);
private int FPS = 0;
public Scene scene;
TowerDefense tD;
private boolean running = false;
public RoundRectangle2D.Float playGame, quitGame;
public boolean playGameHighlighted, quitGameHighlighted;
#Override
public void run() {
// long lastFrame = System.currentTimeMillis();
// int frames = 0;
//
// running = true;
//
// while (running) {
// repaint();
//
// frames++;
//
// if (System.currentTimeMillis() - 1000 >= lastFrame) {
// FPS = frames;
// frames = 0;
//
// lastFrame = System.currentTimeMillis();
// }
// }
//
// System.exit(0);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
public Screen(TowerDefense tD) {
thread.start();
addKeyListener(new KeyHandler(this));
addMouseMotionListener(
new MouseAdapter() {
#Override
public void mouseMoved(MouseEvent e) {
playGameHighlighted = playGame.contains(e.getPoint());
quitGameHighlighted = quitGame.contains(e.getPoint());
repaint();
}
});
this.tD = tD;
scene = Scene.MENU;
}
#Override
public void paintComponent(Graphics g2) {
super.paintComponent(g2);
playGame = new RoundRectangle2D.Float((getWidth() / 2) - 200, (getHeight() / 2) - 100, 400, 100, 10, 10);
quitGame = new RoundRectangle2D.Float((getWidth() / 2) - 200, (getHeight() / 2) + 20, 400, 100, 10, 10);
Graphics2D g = (Graphics2D) g2.create();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.clearRect(0, 0, getWidth(), getHeight());
g.drawString("FPS: " + FPS, 10, 10);
if (scene == Scene.MENU) {
if (playGameHighlighted) {
g.setColor(new Color(255, 152, 56));
} else {
g.setColor(new Color(4, 47, 61));
}
g.draw(playGame);
if (quitGameHighlighted) {
g.setColor(new Color(255, 152, 56));
} else {
g.setColor(new Color(4, 47, 61));
}
g.draw(quitGame);
g.setColor(Color.WHITE);
g.setFont(new Font("Gisha", Font.PLAIN, 20));
g.drawString("Play", (getWidth() / 2) - (g.getFontMetrics().stringWidth("Play") / 2), (getHeight() / 2) - 45);
g.drawString("Quit", (getWidth() / 2) - (g.getFontMetrics().stringWidth("Quit") / 2), (getHeight() / 2) + 75);
}
}
public class KeyTyped {
public void keyESC() {
running = false;
}
}
}
public class KeyHandler implements KeyListener {
private Screen screen;
private Screen.KeyTyped keyTyped;
public KeyHandler(Screen screen) {
this.screen = screen;
keyTyped = screen.new KeyTyped();
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == 27) {
keyTyped.keyESC();
}
}
#Override
public void keyReleased(KeyEvent e) {
}
}
}
I have a "car" made with various objects using graphics g and I want to move it when a button is pressed. With that, I had no problem, but I have a problem with its path. When the car is moved, the old position is not cleared out.
Code of the car (to move when button is pressed):
static void gPostavi2(Graphics g){
Graphics2D g2d = (Graphics2D) g;
for(int x=500; x>89; x--){
//risanje
g2d.setColor(Color.blue);
g2d.fillRect(x+10, 351, 118, 23);
g2d.fillRect(x+12, 321, 30, 40);
g2d.fillRect(x+45, 330, 83, 20);
g2d.setColor(Color.black);
g2d.fillOval(x+19, 362, 20, 20);
g2d.fillOval(x+90, 362, 20, 20);
g2d.drawString("2t", x+70, 344);
try {
Thread.sleep(5);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
In this class are only methods for moving things around, the class extends another that has non-moving objects, buttons, labels,... and the paintComponent method.
How can I clear the old position, every time the for statement goes around ?
EDIT: some more code down here. In the main class I have only this code:
public static void main(String[] args) {
staticnaGrafika.dodajGumbe();
}
In staticnaGrafika I have a ton of code, but this is the beginning of paintComponent:
public class staticnaGrafika extends JPanel{
staticnaGrafika(){
setBorder(BorderFactory.createLineBorder(Color.black));
}
public Dimension getPreferredSize(){
return new Dimension(1100, 740);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.RED);
//opticno stikalo
//preveri, ce ga plosca prekriva pri max. dvigu
g2d.setColor(Color.black);
g2d.fillOval(21, 148, 33, 33);
g2d.setColor(Color.yellow);
g2d.fillOval(22, 149, 31, 31);
g2d.setColor(Color.black);
g2d.fillRect(13, 159, 11, 1); //el. prikljucnice
g2d.fillRect(13, 166, 10, 1);
g2d.drawOval(7, 157, 5, 5);
g2d.drawOval(7, 164, 5, 5);
//naslon; spodnji omejevalec hoda bata
g2d.setColor(Color.black);
g2d.fillRect(5, 350, 13, 43);
g2d.fillRect(5, 380, 63, 13);
g2d.fillRect(262, 350, 408, 13);
g2d.fillRect(262, 350, 13, 43);
g2d.fillRect(212, 380, 63, 13);
there is just painting in here. Below I have another method, which adds buttons, actionListeners:
public static void dodajGumbe() {
final JFrame f = new JFrame();
//dvig, stop, spust
JButton dvig = new JButton("DVIGNI");
dvig.setBackground(Color.WHITE);
dvig.setFocusPainted(false);
dvig.setBounds(850,15,120,30);
JButton stop = new JButton("STOP");
stop.setBackground(Color.WHITE);
stop.setFocusPainted(false);
stop.setBounds(850,50,120,30);
JButton spust = new JButton("SPUSTI");
spust.setBackground(Color.WHITE);
spust.setFocusPainted(false);
spust.setBounds(850,85,120,30);
//komande bremen
JButton postavi2 = new JButton("nalozi breme");
postavi2.setBackground(Color.WHITE);
postavi2.setFocusPainted(false);
postavi2.setBounds(760,240,120,30);
JButton odvzemi2 = new JButton("razlozi breme");
odvzemi2.setBackground(Color.WHITE);
odvzemi2.setFocusPainted(false);
odvzemi2.setBounds(760,275,120,30);
JButton postavi5 = new JButton("nalozi breme");
postavi5.setBackground(Color.WHITE);
postavi5.setFocusPainted(false);
postavi5.setBounds(760,330,120,30);
JButton odvzemi5 = new JButton("razlozi breme");
odvzemi5.setBackground(Color.WHITE);
odvzemi5.setFocusPainted(false);
odvzemi5.setBounds(760,365,120,30);
Container gumbi = f.getContentPane();
spust.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
dinamicnaGrafika.gSpusti(f.getGraphics());
}});
dvig.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
dinamicnaGrafika.gDvigni(f.getGraphics());
}});
stop.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
dinamicnaGrafika.gStop(f.getGraphics());
}});
postavi2.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
dinamicnaGrafika.gPostavi2(f.getGraphics());
}});
odvzemi2.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
dinamicnaGrafika.gOdvzemi2(f.getGraphics());
}});
postavi5.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
dinamicnaGrafika.gPostavi5(f.getGraphics());
}});
odvzemi5.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
dinamicnaGrafika.gOdvzemi5(f.getGraphics());
}});
gumbi.add(dvig);
gumbi.add(stop);
gumbi.add(spust);
gumbi.add(postavi2);
gumbi.add(odvzemi2);
gumbi.add(postavi5);
gumbi.add(odvzemi5);
f.getContentPane();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new staticnaGrafika());
f.pack();
f.setVisible(true);
}
You probably forgot to call
super.paintComponent(g);
in your paintComponent() method
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g); //Clear screen before redraw
//Your codes for painting..
}
You should never be calling sleep() on the UI thread. Instead, I highly recommend that you use javax.swing.Timer and an ActionListener. Something like:
void paintCar(Graphics2D g2d, int x) {
g2d.setColor(Color.blue);
g2d.fillRect(x+10, 351, 118, 23);
g2d.fillRect(x+12, 321, 30, 40);
g2d.fillRect(x+45, 330, 83, 20);
g2d.setColor(Color.black);
g2d.fillOval(x+19, 362, 20, 20);
g2d.fillOval(x+90, 362, 20, 20);
g2d.drawString("2t", x+70, 344);
}
int x = 0;
public MyConstructor() {
new Timer(5, this).start();
}
public void actionPerformed(ActionEvent ae) {
x++;
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
paintCar(g2d, x);
}
It looks like the problem lies with your implementation. You could create a class for your Car objects and each car object keep track of their own coordinates.
For your case, if you are only moving the cars only when the button is clicked, you don't even need a Timer. Just update the car's position in the ActionListener for every button click.
OUTPUT:
class Car
{
private Color carColor;
private int x, y;
private int speed;
private static int carWidth = 100;
private static int carHeight = 30;
public Car(Color carColor, int speed){
this.carColor = carColor;
this.speed = speed;
x = 0;
y = 0;
}
public void moveTo(int x, int y){
this.x = x;
this.y = y;
}
public void draw(Graphics g){
//Draw a car object
g.setColor(carColor);
g.fillRect(x, y, carWidth, carHeight);
g.setColor(Color.BLACK);
//Draw Wheels
g.fillOval(x, y+carHeight, 30, 30);
g.fillOval(x+carWidth-30, y+carHeight, 30, 30);
}
public int getX(){return x;}
public int getY(){return y;}
public int getSpeed(){return speed;}
}
So when you move your car(s), just update their positions and that's all you need to do. Pay special attention to my paintComponent() method. You should keep that method simple and clutter free. It is only responsible for painting. All the movements of cars is done else where.
class DrawingSpace extends JPanel implements ActionListener{
Car c1, c2, c3;
public DrawingSpace(){
setPreferredSize(new Dimension(800, 400));
c1 = new Car(Color.RED, 5);
c2 = new Car(Color.GREEN, 8);
c3 = new Car(Color.BLUE, 10);
c1.moveTo(10, 50);
c2.moveTo(10, 180);
c3.moveTo(10, 280);
}
public void moveCars(){
}
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
c1.draw(g);
c2.draw(g);
c3.draw(g);
}
#Override
public void actionPerformed(ActionEvent e){
//Used for timer (to animate moving cars)
c1.moveTo((c1.getX()+c1.getSpeed()), c1.getY());
c2.moveTo(c2.getX()+c2.getSpeed(), c2.getY());
c3.moveTo(c3.getX()+c3.getSpeed(), c3.getY());
if(c1.getX() > 800)
c1.moveTo(0, c1.getY());
if(c2.getX() > 800)
c2.moveTo(0, c2.getY());
if(c3.getX() > 800)
c3.moveTo(0, c3.getY());
repaint();
}
}
For a task like this, it will be better and easier to use javax.swing.timer instead of implementing your own loop with Thread.sleep().
class MovingCars{
public static void main(String[] args){
javax.swing.SwingUtilities.invokeLater(new Runnable(){
public void run() {
JFrame f = new JFrame("Moving Cars");
DrawingSpace ds = new DrawingSpace();
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(ds);
f.pack();
f.setLocationRelativeTo(null);
Timer t = new Timer(50, ds); //Delay of 50 milliseconds
t.start();
}
});
}
}
public class BelishaBeacon {
public class Design extends JPanel {
private boolean alternateColors = false;
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
//creating the shapes
Rectangle box1 = new Rectangle(163, 180, 16, 45);
Rectangle box2 = new Rectangle(163, 225, 16, 45);
Rectangle box3 = new Rectangle(163, 270, 16, 45);
Rectangle box4 = new Rectangle(163, 315, 16, 45);
Rectangle box5 = new Rectangle(163, 360, 16, 45);
Rectangle box6 = new Rectangle(163, 405, 16, 45);
//drawing the shapes
Ellipse2D.Double ball = new Ellipse2D.Double(a, b, 100, 100);
g2.draw(ball);
g2.draw(box1);
g2.draw(box2);
g2.draw(box3);
g2.draw(box4);
g2.draw(box5);
g2.draw(box6);
//coloring the shapes
g2.setColor(Color.BLACK);
g2.fill(box1);
g2.fill(box3);
g2.fill(box5);
g2.setColor(Color.YELLOW);
g2.fill(ball);
if (alternateColors) {
g2.setColor(Color.ORANGE);
g2.fill(new Ellipse2D.Double(a, b, 100, 100));
}
alternateColors = false;
}
public void alternateColors() {
alternateColors = true;
repaint();
}
}
public BelishaBeacon() {
//frame
JFrame frame = new JFrame();
frame.setSize(330, 550);
frame.setTitle("Belisha Beacon");
frame.setLayout(new BorderLayout(0, 0));
final Design shapes = new Design();
JButton jbtFlash = new JButton("Flash");
jbtFlash.addActionListener(
new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Runnable r = new Runnable(){
#Override
public void run(){
while(/* user stops / toggleButton state*/ true)
{
swapColors(); // some method using static boolean
try{
Thread.sleep(500);
}catch(Exception e){}
}
}
private void swapColors() {
boolean swapColors;
Graphics g2;
if (swapColors) {
g2.setColor(Color.ORANGE);
g2.fill(new Ellipse2D.Double(a, b, 100, 100));
} else {
g2.setColor(Color.YELLOW);
g2.fill(new Ellipse2D.Double(a, b, 100, 100));
}
}
};
Thread t = new Thread(r);
t.start();
}});
JButton jbtSteady = new JButton("Steady");
jbtSteady.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
shapes.alternateColors();
}
});
I have created an action listener for my jbutton steady and flash, I am just trying to created a method for swapColors for it to be initialised in the jbutton flash. The swapcolos method initially should alternate between the colours orange and grey
You wrote that you want it to flash every 0.5 seconds.
To do so you need to start new thread for example
jbtFlash.addActionListener(
new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Runnable r = new Runnable(){
#Override
public void run(){
while(/* user stops / toggleButton state*/ true)
{
swapColors(); // some method using static boolean
try{
Thread.sleep(500);
}catch(Exception e){}
}
}
};
Thread t = new Thread(r);
t.start();
}});
if (alternateColors) {
g2.setColor(Color.ORANGE);
g2.fill(new Ellipse2D.Double(a, b, 100, 100));
}
alternateColors = false;
Should be:
if (alternateColors) {
g2.setColor(Color.ORANGE);
g2.fill(new Ellipse2D.Double(a, b, 100, 100));
} else {
g2.setColor(Color.YELLOW);
g2.fill(new Ellipse2D.Double(a, b, 100, 100));
}
AND
public void alternateColors() {
alternateColors = true;
repaint();
}
Should be:
public void alternateColors() {
//Flip boolean alternateColors
alternateColors = !alternateColors;
repaint();
}
My code below is for a checkers program. If the user either clicks on a stop button or holds the mouse, it stops, and the go button or mouse release moves the checkers from the beginning.
I am not able to figure out how to move the checkers from the same position that they were stopped at. Help Please!
import java.awt.Button;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
public class Checkers extends java.applet.Applet implements Runnable,
ActionListener {
Thread runner;
int xpos;
Image offscreenImg;
Graphics offscreenG;
Button goButton, stopButton, exitButton;
private ExitButtonHandler ebHandler;
public void init() {
// offscreenImg = createImage(getWidth(), getHeight());
offscreenImg = createImage(this.size().width, this.size().height);
offscreenG = offscreenImg.getGraphics();
setSize(200, 250);
addMouseListener(new Mouse());
goButton = new Button("Go");
goButton.setBounds(10, 200, 90, 20);
setLayout(null);
stopButton = new Button("Stop");
stopButton.setBounds(100, 200, 90, 20);
setLayout(null);
exitButton = new Button("Exit");
ebHandler = new ExitButtonHandler();
exitButton.addActionListener(ebHandler);
exitButton.setBounds(55, 220, 90, 20);
setLayout(null);
add(goButton);
add(stopButton);
add(exitButton);
stopButton.addActionListener(this);
goButton.addActionListener(this);
}
public void start() {
if (runner == null) {
runner = new Thread(this);
runner.start();
}
}
public void stop() {
if (runner != null) {
runner.stop();
runner = null;
}
}
public void run() {
while (true) {
for (xpos = 5; xpos <= 105; xpos += 4) {
repaint();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
}
xpos = 5;
for (xpos = 105; xpos >= 5; xpos -= 4) {
repaint();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
}
xpos = 5;
}
}
public void update(Graphics g) {
paint(g);
}
public void paint(Graphics g) {
// Draw background onto the buffer area
offscreenG.setColor(Color.blue);
offscreenG.fillRect(0, 0, 100, 100);
offscreenG.setColor(Color.red);
offscreenG.fillRect(0, 100, 100, 100);
offscreenG.setColor(Color.red);
offscreenG.fillRect(100, 0, 100, 100);
offscreenG.setColor(Color.blue);
offscreenG.fillRect(100, 100, 100, 100);
// Draw checker
offscreenG.setColor(Color.green);
offscreenG.fillOval(xpos, 5, 90, 90);
offscreenG.setColor(Color.yellow);
offscreenG.fillOval(-xpos + 110, 105, 90, 90);
// Now, transfer the entire buffer onto the screen
g.drawImage(offscreenImg, 0, 0, this);
}
public void destroy() {
offscreenG.dispose();
}
// Mouse events
public class Mouse extends MouseAdapter {
public void mousePressed(MouseEvent e) {
stop();
}
public void mouseReleased(MouseEvent e) {
start();
}
}
// Button events
public void actionPerformed(ActionEvent e) {
if (e.getSource() == stopButton) {
stop();
} else if (e.getSource() == goButton) {
start();
}
}
// exit button
public class ExitButtonHandler implements ActionListener {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
}
You are recreating a new Thread which starts from the beginning every time you call the start function. Also, after you call stop you will not be able to "resume" where you left off.
You will want to change your Thread to use a flag of some type (boolean stopped;) and then change that flag when you call stop and start, so the Thread doesn't actually end but just "pauses." (stops moving, but is actually still running)
if (stopped) {
//dont do stuff
}
else {
//do stuff
}