Java: Moving an object at an angle and changing angle with KeyPress - java

Ok, so what i want is the rectangle to always be moving, but when you press the left and right arrow is changes the direction by either increasing or decreasing the angle. With this code the sqaure moves as it should in the correct direction, but when i press the keys the direction does not change.
import java.awt.*;
import java.awt.Color;
import javax.swing.Timer;
import javax.swing.*;
import java.awt.Graphics;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyAdapter;
public class Fields extends JPanel implements ActionListener, KeyListener{
Timer tm = new Timer(5, this);
double x = 250, y = 250, vel = 0.2, angle = 90;
public void paintComponent(Graphics g)
{
super.paintComponent(g);
this.setBackground(Color.BLACK);
g.setColor(Color.GREEN);
g.fillRect((int)x, (int)y, 5, 5);
tm.start();
}
public void keyTyped(KeyEvent e)
{
if (e.getKeyCode() == 37) {angle--;}
if (e.getKeyCode() == 39) {angle++;}
}
public void keyReleased(KeyEvent e)
{
if (e.getKeyCode() == 37) {angle--;}
if (e.getKeyCode() == 39) {angle++;}
}
public void keyPressed(KeyEvent e)
{
if (e.getKeyCode() == 37) {angle--;}
if (e.getKeyCode() == 39) {angle++;}
}
public void actionPerformed(ActionEvent e)
{
x += (velX * (float)Math.cos(Math.toRadians(angle - 90)));
y += (velX * (float)Math.sin(Math.toRadians(angle - 90)));
repaint();
}
public Fields()
{
this.addKeyListener(this);
}
public static void main(String[] args)
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(500, 500);
Fields fi = new Fields();
f.add(fi);
f.setVisible(true);
}
}

As started in my comments...
Don't start the timer in paintComponent, this method gets called repeatedly and can be called often in quick succession.
Use key bindings
.
public class TestAnimation01 {
public static void main(String[] args) {
new TestAnimation01();
}
public TestAnimation01() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new Fields());
frame.setSize(400, 400);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class Fields extends JPanel implements ActionListener {
Timer tm = new Timer(125, this);
double x = 250, y = 250, vel = 0.2, angle = 90;
private int velX = 4;
private int velY = 4;
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
this.setBackground(Color.BLACK);
g.setColor(Color.GREEN);
g.fillRect((int) x, (int) y, 5, 5);
}
public void actionPerformed(ActionEvent e) {
x += (velX * (float) Math.cos(Math.toRadians(angle - 90)));
y += (velX * (float) Math.sin(Math.toRadians(angle - 90)));
repaint();
}
public Fields() {
setFocusable(true);
InputMap im = getInputMap(WHEN_FOCUSED);
ActionMap am = getActionMap();
// left 37
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "goLeft");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "goRight");
am.put("goLeft", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
angle--;
repaint();
}
});
am.put("goRight", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
angle++;
repaint();
}
});
tm.setRepeats(true);
tm.setCoalesce(true);
tm.start();
requestFocusInWindow();
}
}
}
There's a bunch of other things you've not covered, such as edge conditions (what happens when it leaves the screen) and individual x/y speeds, but I'm sure you'll work it out

Related

How to: clear the JPanel before repainting and the run another class and move the object

I want to run the snake class after the start button its pressed the programg works until i press the start button and try to move the rectangle around the window, there is the problem the rectangle wont move at all. Please help. Thanks.
public class Main {
public static void main(String [] args) {
MenuScreen MenuScreen = new MenuScreen();
MenuScreen.menuscreen();
}
}
The Screen Menu class
import java.awt.Color;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class MenuScreen {
Snake Snake = new Snake();
public void menuscreen () {
//Window
final JFrame window = new JFrame();
window.setVisible(true);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(800, 600);
window.setLocationRelativeTo(null);
//Panel
JPanel panel = new JPanel();
window.getContentPane().add(panel);
panel.setBackground(Color.BLACK);
panel.setVisible(true);
panel.setLayout(null);
//Title
JLabel label = new JLabel("SNAKE");
panel.add(label);
label.setBounds(290, 5, 204, 73);
label.setFont(new Font("Tahoma", Font.BOLD, 60));
label.setHorizontalAlignment(SwingConstants.CENTER);
label.setForeground(Color.RED);
label.setBackground(Color.red);
//Buttons
//start button
JButton bstart = new JButton ("Start");
panel.add(bstart);
bstart.setBounds(424, 200, 70, 60);
bstart.setVisible(true);
//start button - run snake on click
bstart.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
window.getContentPane().removeAll();
Snake Snake = new Snake();
window.add(Snake);
window.repaint();
window.revalidate();
}
});
//exit button
JButton bexit = new JButton ("Exit");
panel.add(bexit);
bexit.setBounds(290, 200, 70, 60);
bexit.setVisible(true);
//exit button - close on click
bexit.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
});
}
}
The Snake class, when I click start the frame gets cleared and shows the rect but when I try to move the rect aroud the screen it wont move.
public class Snake extends JPanel implements ActionListener, KeyListener {
public void thicks () {}
public Snake () {
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
private static final long serialVersionUID = 1L;
Timer FPS = new Timer( 5, this);
double x =0 , y = 0, SpeedX = 0, SpeedY = 0;
public void paint(Graphics g) {
FPS.start();
super.paintComponent(g);
g.setColor(Color.blue);
Graphics2D graphics = (Graphics2D) g;
Rectangle2D rect = new Rectangle2D.Double(x, y, 40, 40);
graphics.fill(rect);
}
public void actionPerformed(ActionEvent e) {
if(x < 0 || x > 740 ) {
SpeedX= -SpeedX;
}
if(y < 0 || y > 520) {
SpeedY = -SpeedY;
}
x += SpeedX;
y += SpeedY;
repaint();
}
public void down() {
SpeedY = 2;
SpeedX = 0;
}
public void up() {
SpeedY = -2;
SpeedX = 0;
}
public void right() {
SpeedY = 0;
SpeedX = 2;
}
public void left() {
SpeedY = 0;
SpeedX = -2;
}
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == KeyEvent.VK_DOWN) {
down();
}
if(keyCode == KeyEvent.VK_UP) {
up();
}
if(keyCode == KeyEvent.VK_RIGHT) {
right();
}
if(keyCode == KeyEvent.VK_LEFT) {
left();
}
}
public void keyReleased(KeyEvent e) {}
public void keyTyped(KeyEvent e) {}
}

Can't repaint my JFrame/JPanel

I have created a program that just moves a ball across a screen. I used to have it all in one class, but decided that it looked too messy so I split it up into three different classes: Main... initializes everything, Game... which paints everything and is a JPanel, and AL which is a KeyListener (which is also where the problem is). The problem is that I can't get the program to repaint from my AL class no matter what I try to pass into it. Can anyone help with this? Here are my three classes:
import java.awt.Color;
import javax.swing.JFrame;
public class Main {
static Game game;
static JFrame frame;
public static void main(String[] args) {
game = new Game();
frame = new JFrame();
frame.getContentPane().add(game);
frame.addKeyListener(new AL(game, frame));
frame.setTitle("Game");
frame.setSize(500, 500);
frame.setResizable(true);
frame.setVisible(true);
frame.setBackground(Color.BLACK);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
-
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Game extends JPanel implements Runnable {
int x, y, xCoord, yCoord;
private Image dbImage;
private Graphics dbg;
JFrame frame;
public void changeCoord() {
x += xCoord;
y += yCoord;
if (x <= 20) {
x = 20;
}
if (x >= 480) {
x = 480;
}
if (y <= 40) {
y = 40;
}
if (y >= 480) {
y = 480;
}
}
public void setXCoord(int xcoord) {
xCoord = xcoord;
}
public void setYCoord(int ycoord) {
yCoord = ycoord;
}
public static void main(String[] args) {
Game game = new Game();
Thread t = new Thread(game);
t.start();
}
public Game() {
x = 250;
y = 250;
}
#Override
public void paintComponent(Graphics g) {
g.setColor(Color.GREEN);
g.fillOval(x, y, 15, 15);
}
#Override
public void paint(Graphics g) {
dbImage = createImage(getWidth(), getHeight());
dbg = dbImage.getGraphics();
paintComponent(dbg);
g.drawImage(dbImage, 0, 0, this);
}
#Override
public void run() {
try {
while (true) {
changeCoord();
Thread.sleep(30);
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
-
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
public class AL extends KeyAdapter {
Game game;
JFrame frame;
public AL(Game game, JFrame frame) {
this.game = game;
this.frame = frame;
}
#Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == e.VK_LEFT) {
game.setXCoord(-1);
}
if (keyCode == e.VK_RIGHT) {
game.setXCoord(+1);
}
if (keyCode == e.VK_UP) {
game.setYCoord(-1);
}
if (keyCode == e.VK_DOWN) {
game.setYCoord(+1);
}
game.repaint();
}
#Override
public void keyReleased(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == e.VK_LEFT) {
game.setXCoord(0);
}
if (keyCode == e.VK_RIGHT) {
game.setXCoord(0);
}
if (keyCode == e.VK_UP) {
game.setYCoord(0);
}
if (keyCode == e.VK_DOWN) {
game.setYCoord(0);
}
game.repaint();
}
}
Let's start with the obvious....
This is problematic...
#Override
public void paintComponent(Graphics g) {
g.setColor(Color.GREEN);
g.fillOval(x, y, 15, 15);
}
#Override
public void paint(Graphics g) {
dbImage = createImage(getWidth(), getHeight());
dbg = dbImage.getGraphics();
paintComponent(dbg);
g.drawImage(dbImage, 0, 0, this);
}
There's no need to implement double buffering in Swing components, they already are. Also, you're breaking the painting contract, by not call the paint methods super methods
The whole thing should be...
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.GREEN);
g.fillOval(x, y, 15, 15);
}
See Painting in AWT and Swing and Performing Custom Painting for more details
KeyListener is well known for been problematic. It will only raise key events if the component it registered to is focuable AND has keyboard focus. A JPanel by default, is not focusable. Before you run of and try and make it focusable (and get bitterly disappointed), you should be using the Key Bindings API instead, which was designed to over come the limitations of KeyListener
As a basic example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
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 Game());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class Game extends JPanel {
int x, y, xCoord, yCoord;
public Game() {
x = 250;
y = 250;
addKeyBinding(KeyEvent.VK_LEFT, "move.left", new MoveAction(this, -1, 0));
addKeyBinding(KeyEvent.VK_RIGHT, "move.right", new MoveAction(this, 1, 0));
addKeyBinding(KeyEvent.VK_UP, "move.up", new MoveAction(this, 0, -1));
addKeyBinding(KeyEvent.VK_DOWN, "move.down", new MoveAction(this, 0, 1));
}
protected void addKeyBinding(int keyCode, String name, Action action) {
addKeyBinding(KeyStroke.getKeyStroke(keyCode, 0), name, action);
}
protected void addKeyBinding(KeyStroke keyStroke, String name, Action action) {
InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap actionMap = getActionMap();
inputMap.put(keyStroke, name);
actionMap.put(name, action);
}
public void changeCoord() {
x += xCoord;
y += yCoord;
if (x <= 20) {
x = 20;
}
if (x >= 480) {
x = 480;
}
if (y <= 40) {
y = 40;
}
if (y >= 480) {
y = 480;
}
repaint();
}
public void setXCoord(int xcoord) {
xCoord = xcoord;
changeCoord();
}
public void setYCoord(int ycoord) {
yCoord = ycoord;
changeCoord();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(480, 480);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.GREEN);
g.fillOval(x, y, 15, 15);
}
}
public class MoveAction extends AbstractAction {
private int xDelta;
private int yDelta;
// I'd prefer an interface with just the "move" methods, but
// that's more time I don't have
private Game game;
public MoveAction(Game game, int xDelta, int yDelta) {
this.xDelta = xDelta;
this.yDelta = yDelta;
this.game = game;
}
#Override
public void actionPerformed(ActionEvent e) {
game.setXCoord(xDelta);
game.setYCoord(yDelta);
}
}
}
But, wait, that isn't exactly what you want (trust me, I'm an anoymouse person on the Internet ;)), a better example might be...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.HashSet;
import java.util.Set;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
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 Game());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public enum Direction {
UP,
LEFT,
DOWN,
RIGHT;
}
public class Game extends JPanel {
int x, y, xCoord, yCoord;
private Set<Direction> movement;
public Game() {
x = 250;
y = 250;
movement = new HashSet<>(4);
addKeyPressedBinding(KeyEvent.VK_LEFT, "left.pressed", new MoveAction(movement, Direction.LEFT, true));
addKeyReleasedBinding(KeyEvent.VK_LEFT, "left.released", new MoveAction(movement, Direction.LEFT, false));
addKeyPressedBinding(KeyEvent.VK_RIGHT, "right.pressed", new MoveAction(movement, Direction.RIGHT, true));
addKeyReleasedBinding(KeyEvent.VK_RIGHT, "right.released", new MoveAction(movement, Direction.RIGHT, false));
addKeyPressedBinding(KeyEvent.VK_UP, "up.pressed", new MoveAction(movement, Direction.UP, true));
addKeyReleasedBinding(KeyEvent.VK_UP, "up.released", new MoveAction(movement, Direction.UP, false));
addKeyPressedBinding(KeyEvent.VK_DOWN, "down.pressed", new MoveAction(movement, Direction.DOWN, true));
addKeyReleasedBinding(KeyEvent.VK_DOWN, "down.released", new MoveAction(movement, Direction.DOWN, false));
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
changeCoord();
}
});
timer.start();
}
protected void addKeyBinding(int keyCode, String name, Action action) {
addKeyBinding(KeyStroke.getKeyStroke(keyCode, 0), name, action);
}
protected void addKeyPressedBinding(int keyCode, String name, Action action) {
addKeyBinding(KeyStroke.getKeyStroke(keyCode, 0, false), name, action);
}
protected void addKeyReleasedBinding(int keyCode, String name, Action action) {
addKeyBinding(KeyStroke.getKeyStroke(keyCode, 0, true), name, action);
}
protected void addKeyBinding(KeyStroke keyStroke, String name, Action action) {
InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap actionMap = getActionMap();
inputMap.put(keyStroke, name);
actionMap.put(name, action);
}
public void changeCoord() {
if (movement.contains(Direction.UP)) {
y--;
} else if (movement.contains(Direction.DOWN)) {
y++;
}
if (movement.contains(Direction.LEFT)) {
x--;
} else if (movement.contains(Direction.RIGHT)) {
x++;
}
x += xCoord;
y += yCoord;
if (x <= 20) {
x = 20;
}
if (x >= 480) {
x = 480;
}
if (y <= 40) {
y = 40;
}
if (y >= 480) {
y = 480;
}
repaint();
}
public void setXCoord(int xcoord) {
xCoord = xcoord;
changeCoord();
}
public void setYCoord(int ycoord) {
yCoord = ycoord;
changeCoord();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(480, 480);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.GREEN);
g.fillOval(x, y, 15, 15);
}
}
public class MoveAction extends AbstractAction {
private Set<Direction> movement;
private Direction direction;
private boolean pressed;
public MoveAction(Set<Direction> movement, Direction direction, boolean pressed) {
this.movement = movement;
this.direction = direction;
this.pressed = pressed;
}
#Override
public void actionPerformed(ActionEvent e) {
if (pressed) {
movement.add(direction);
} else {
movement.remove(direction);
}
}
}
}
What this does is simply activates a flag when a key is pressed (and deactivates it when it's released), then in a Swing Timer, we check which keys are "active" and update the location of the ball.
What this does is, eliminates the key "stutter" which is caused by the OS when a key is first pressed and held. A delay is inserted between the first key and the repeated key events. Instead, we just turn the flag on and off as we like.
It also allows you to move in two directions at the same time (horizontally and vertically)
Have a look at Concurrency in Swing and How to use Swing Timers for more details

Call paintComponent method

I am trying to paint a line when my variable readyToDraw is TRUE by using an if... statement in class's Paint method paintComponent() . I guess I'm doing something wrong because the line never gets painted. How do I fix this? Is there a way to call paintComponent() from another method?
Full code:
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Rectangle2D;
import java.awt.Graphics2D;
import java.util.Iterator;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.SwingWorker;
import javax.swing.border.LineBorder;
import javax.swing.AbstractAction;
import javax.swing.Action;
public class MainFrame {
public int x1, x2, y1, y2;
private boolean readyToDraw = false;
private int clickCount = 0;
private JFrame frame;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MainFrame window = new MainFrame();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public MainFrame() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 800, 600);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
JPanel buttonPanel = new JPanel();
buttonPanel.setBackground(Color.WHITE);
buttonPanel.setBorder(new LineBorder(new Color(0, 0, 0), 2, true));
buttonPanel.setBounds(10, 11, 100, 85);
frame.getContentPane().add(buttonPanel);
buttonPanel.setLayout(null);
JPanel paint = new Paint();
frame.getContentPane().add(paint);
JButton btnLine = new JButton("Line");
btnLine.setBackground(Color.LIGHT_GRAY);
btnLine.setBounds(4, 4, 92, 25);
btnLine.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Execute when button is pressed
if (readyToDraw == true) {
System.out.println("Let's draw!");
}
else {
}
System.out.println("Line");
}
});
JButton btnRectangle = new JButton("Rectangle");
btnRectangle.setBackground(Color.LIGHT_GRAY);
btnRectangle.setBounds(4, 30, 92, 25);
btnRectangle.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Execute when button is pressed
if (readyToDraw == true) {
System.out.println("Let's draw!");
}
else {
}
System.out.println("Rectangle");
}
});
JButton btnCircle = new JButton("Circle");
btnCircle.setBackground(Color.LIGHT_GRAY);
btnCircle.setBounds(4, 56, 92, 25);
btnCircle.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Execute when button is pressed
if (readyToDraw == true) {
System.out.println("Let's draw!");
}
else {
}
System.out.println("Circle");
}
});
buttonPanel.add(btnLine);
buttonPanel.add(btnRectangle);
buttonPanel.add(btnCircle);
}
private class Paint extends JPanel implements MouseListener {
public Paint() {
this.setBackground(Color.WHITE);
this.setBounds(120, 11, 664, 550);
this.addMouseListener(this);
}
#Override
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
super.paintComponent(g);
//if (readyToDraw) {
g2.setStroke(new BasicStroke(4));
g2.setColor(Color.BLACK);
g2.drawLine(x1, y1, x2, y2);
//}
}
#Override
public void mouseEntered(MouseEvent arg0) {
Toolkit toolkit = Toolkit.getDefaultToolkit();
Image image = toolkit.getImage("cursor.png");
Point hotSpot = new Point(15, 15);
Cursor cursor = toolkit.createCustomCursor(image, hotSpot, "Dot");
this.setCursor(cursor);
}
#Override
public void mouseExited(MouseEvent arg0) {
Cursor dotCursor = new Cursor(Cursor.DEFAULT_CURSOR);
this.setCursor(dotCursor);
}
public void mouseClicked(MouseEvent e) {
int x1 = 0;
int y1 = 0;
int x2 = 0;
int y2 = 0;
if (clickCount == 0) {
x1 = e.getX();
y1 = e.getY();
clickCount++;
} else if (clickCount == 1) {
x2 = e.getX();
y2 = e.getY();
clickCount++;
readyToDraw = true;
} else {
clickCount = 0;
readyToDraw = false;
repaint();
}
System.out.println(x1 + " " + y1 + " " + clickCount + " " + x2
+ " " + y2 + readyToDraw);
}
public void mousePressed(MouseEvent arg0) {
// TODO Auto-generated method stub
}
public void mouseReleased(MouseEvent arg0) {
// TODO Auto-generated method stub
}
}
}

Java repaint doesn't update

I encountered a problem when I was coding, When I call repaint anywhere, it doesn't update the image but the program still keeps running:
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.ImageObserver;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class mainMenu extends JPanel implements MouseListener{
Graphics g;
Image playButton = Toolkit.getDefaultToolkit().getImage("game sprites/play_button.png");
private int part = 0;
public static void main(String[] a) {
mainMenu mm = new mainMenu();
mm.makeJFrame();
}
public void makeJFrame(){
JFrame f = new JFrame();
f.setSize(1000, 600);
f.add(new mainMenu());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
f.addMouseListener(this);
f.setTitle("MAIN MENU");
}
public void paintComponent(Graphics g) {
if(part == 0)
System.out.println("0");
g.drawImage( playButton, 330, 200, 294, 102, this);
if(part == 1)
{
System.out.println("1");
g.setColor(Color.RED);
g.fillRect(0, 0, 40, 40);
}
}
public void mouseClicked(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mousePressed(MouseEvent e) {
int x = e.getX();
int y = e.getY();
if(part == 0)
{
if(x > 330 && x < 624 && y > 232 && y < 334)
{
System.out.println("a");
part = 1;
repaint();
}
}
}
public void mouseReleased(MouseEvent e) {}
}
I tested lots of times, and the problem is with the repaint, the program works, but the image stays the same when it shouldn't. It prints out:
0
0
0
a (when I click on the button)
and doesn't print out "a" again even if I click on the button, which it shouldn't since part is set to 1.
Does the image load? This looks suspicious: Image playButton = Toolkit.getDefaultToolkit().getImage("game sprites/play_button.png");. Where are the images stored?
This looks suspicious...
if (part == 0)
System.out.println("0");
g.drawImage(playButton, 330, 200, 294, 102, this);
And is probably meant to be...
if (part == 0) {
System.out.println("0");
g.drawImage(playButton, 330, 200, 294, 102, this);
}
You've broken the paint chain, you MUST call super.paintComponent before you do any custom painting...
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
And finally, you have two instances of mainMenu...
The first is the one you have on the screen...
f.add(new MainMenu());
The second is the one that is responding to the mouse events and updating the state of part
f.addMouseListener(this);
Which has nothing to do with the first.
You should avoid making a windows within components (like JPanel) and instead create an instance of MainMenu and add it to an instance of JFrame, for example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class MainMenu extends JPanel implements MouseListener {
Image playButton = Toolkit.getDefaultToolkit().getImage("...");
private int part = 0;
public static void main(String[] a) {
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 MainMenu());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public MainMenu() {
addMouseListener(this);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(800, 600);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
System.out.println(part);
if (part == 0) {
System.out.println("0");
g.drawImage(playButton, 0, 0, this);
} else if (part == 1) {
System.out.println("1");
g.setColor(Color.RED);
g.fillRect(0, 0, 40, 40);
}
}
public void mouseClicked(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
int x = e.getX();
int y = e.getY();
if (part == 0) {
System.out.println("a");
part = 1;
repaint();
}
}
public void mouseReleased(MouseEvent e) {
}
}
In Java an if statement only affects one statement after the head of the statement. So you need to put the entire body in {}.
if(part == 0){
System.out.println("0");
g.drawImage( playButton, 330, 200, 294, 102, this);
}

Mouse pressed and released in java applet

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
}

Categories

Resources