Java square not moving - java

I am creating a program in Java where you move a square. However, the square does not move. I have tried a lot of things, but none of them work. It seems to be a problem with repaint. How could I solve this?
package movingSquare;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.WindowConstants;
public class MovingSquare extends JComponent {
private static final long serialVersionUID = -3778627464016140311L;
public static JFrame f = new JFrame("Moving Square");
public static int x;
public static int y;
public static Rectangle r = new Rectangle(x, y, 20, 20);
public static MovingSquare mv = new MovingSquare();
public static KeyListener kl = new KeyListener() {
#Override
public void keyPressed(KeyEvent arg0) {
// TODO Auto-generated method stub
if(arg0.getKeyCode() == KeyEvent.VK_UP) {
y += 1;
r.setLocation(x, y);
mv.repaint(r);
}
if(arg0.getKeyCode() == KeyEvent.VK_DOWN) {
y -= 1;
r.setLocation(x, y);
mv.repaint();
}
if(arg0.getKeyCode() == KeyEvent.VK_LEFT) {
x -= 1;
r.setLocation(x, y);
mv.repaint();
}
if(arg0.getKeyCode() == KeyEvent.VK_RIGHT) {
x += 1;
r.setLocation(x, y);
mv.repaint();
}
}
#Override
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}};
public static void main(String[] args) {
// TODO Auto-generated method stub
f.setBackground(Color.BLUE);
f.setMinimumSize(new Dimension(720, 720));
f.setResizable(false);
f.setFocusable(true);
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.addKeyListener(kl);
f.add(new MovingSquare());
f.pack();
f.setVisible(true);
boolean e = true;
while(e) {
System.out.println("x: " + x + " y: " + y);
}
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g1 = (Graphics2D) g;
g1.setColor(Color.BLUE);
g1.fillRect(0, 0, 720, 720);
g1.setColor(Color.RED);
g1.fill(r);
}
}

First of all custom painting is done by overriding paintComponent() not paint().
Get rid of all the static variables. The reason you create custom class is so you can define variables that contains the properties of the class.
There is no need for the frame variable as part of the class. The component only needs to know about itself, not the frame it belongs to.
f.add(new MovingSquare());
First you create a MovingSquare component and add it to the frame.
public static MovingSquare mv = new MovingSquare();
But then you create another MovingSquare component, but never add it do the frame so you will never be able to paint it.
Get rid of the above statement it is not needed since your class is already a MovingSquare.
mv.repaint();
As I said above that statement does nothing since that component is never added to the frame.
Instead the code should be:
repaint();
That is all you need to cause a component to repaint itself.
If you do use a KeyListener, then the KeyListener should be added to the component itself, not the frame. The component should be responsible for managing its own state.
So basically your design is wrong and needs to be fixed.
However, even that may not solve the problem as only the component with focus will receive events and as suggested in the comment you should be using Key Bindings.
So check out Motion Using the Keyboard for working examples to demonstrated the difference between KeyEvents and Key Bindings.

Related

Keeping Shapes on Screen Help, can't figure out how to keep track of X,Y coordinates

I have tried and tried, I looked up many examples for keeping Shapes on the screen but can't seem to adapt to my code. In Summary, a left click prints a square, a right click prints a circle. I would like to fill the window with squares (rects) and circles. Any help and explanation so I can learn the concept would be great. I understand I have to keep track on the coordinates, perhaps in a loop but can seem to get it to work. Thanks again.
import java.awt.*;
import javax.swing.JFrame;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
public class MouseButtonTester extends JFrame implements MouseListener
{
private int mouseX, mouseY;
private int mouseButton;
private boolean isFirstRun;
private static final int WIDTH = 640;
private static final int HEIGHT = 480;
private static final long serialVersionUID = 0; //use this if you do not like warnings
public MouseButtonTester() //constructor
{
super("Mouse Button Tester");
//set up all variables
mouseX = mouseY = 0;
mouseButton = 0;
isFirstRun = true;
//set up the Frame
setSize(WIDTH,HEIGHT);
setBackground(Color.WHITE);
setVisible(true);
//start trapping for mouse clicks
addMouseListener(this);
}
public void mouseClicked(MouseEvent e)
{
mouseX=e.getX(); //Tracks x coordinates
mouseY=e.getY(); //Tracker y coordinates
mouseButton = e.getButton(); //gets button number
repaint();
}
public void paint( Graphics window ) // Draws the Window
{
if(isFirstRun)
{
window.setColor(Color.WHITE);
window.fillRect(0,0,WIDTH, HEIGHT);
//change isFirstRun
}
window.setFont(new Font("TAHOMA",Font.BOLD,12));
window.setColor(Color.BLUE);
window.drawString("MOUSE BUTTON TESTER", 420,55);
draw(window);
}
public void draw(Graphics window)
{
if(mouseButton==MouseEvent.BUTTON1) //left mouse button pressed
{
//window.drawString("BUTTON1", 50,200); //debug code
window.setColor(Color.RED);
window.drawRect(mouseX,mouseY,10,10);
}
//right mouse button pressed
{
if (mouseButton == MouseEvent.BUTTON2)
window.setColor(Color.BLUE);
window.drawOval(mouseX,mouseY,10,10);
}
//any other mouse button pressed
{
}
}
public void mouseEntered(MouseEvent e) { }
public void mouseExited(MouseEvent e) { }
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) { }
}
------ Main Method --------------
public class MouseButtonTesterRunner
{
public static void main(String[] args)
{ MouseButtonTester prog = new MouseButtonTester();
}
}
First, start by having a read through:
Performing Custom Painting
Painting in AWT and Swing
So you can get a understanding how painting in Swing works, how you can work with it and your responsibilities when doing so.
Next, have a read through:
How can I set in the midst?
Java JFrame .setSize(x, y) not working?
How to get the EXACT middle of a screen, even when re-sized
Graphics rendering in title bar
for reasons why you should avoid overriding paint of top level containers like JFrame
Finally...
Painting in Swing is destructive, that is, every time your component is painted, you are expected to completely repaint the component state from scratch.
In order to achieve your goal, you will need to maintain a cache of the items you want to paint.
The concept itself it's very difficult, but there might be some "gotchas" along the way
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private List<Point> circles;
private List<Point> squares;
public TestPane() {
circles = new ArrayList<>();
squares = new ArrayList<>();
addMouseListener(new MouseAdapter() {
#Override
public void mouseReleased(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
circles.add(e.getPoint());
} else if (SwingUtilities.isRightMouseButton(e)) {
squares.add(e.getPoint());
}
repaint();
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// I'm picky
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.RED);
for (Point p : circles) {
g2d.drawOval(p.x, p.y, 10, 10);
}
g2d.setColor(Color.BLUE);
for (Point p : squares) {
g2d.drawRect(p.x, p.y, 10, 10);
}
g2d.setFont(new Font("TAHOMA", Font.BOLD, 12));
g2d.setColor(Color.BLUE);
FontMetrics fm = g2d.getFontMetrics();
String text = "MOUSE BUTTON TESTER";
int x = getWidth() - fm.stringWidth(text) - 10;
int y = getHeight() - (fm.getAscent() - fm.getHeight()) - 10;
g2d.drawString(text, x, y);
g2d.dispose();
}
}
}
I suggest creating 2 classes.
1) Circle class
2) Square Class
Those classes will store info that you need, like X, y etc..
Initialize an array list that stores those objects & read from it in your paint method, proceed with painting them just like you do in your code.
(On a click event you simply create new object (circle/square) and add it into your array list)
So here's how i understand how your code works so far: The user left clicks, those coordinates are recorded, and a square is rendered on the screen at those coordinates.
When we click the coordinates are updated and on the next draw, the square is moved to a new position.
You were on the right track about needing a loop.
Here's the logic you need to implement:
Create an ArrayList as a member variable. The type can be a pair<int,int> object. So this arraylist will hold a list of X,Y coordinates. This arraylist will look something like this:
ArrayList<pair<int,int>> myRightClickCoords;
Once you make that list, every time the user clicks, record the click coordinates and insert them into the arraylist. That will look something like this:
myRightClickCoords.insert(new pair<int,int>(e.getX(),e.getY()));
Then, once that is added to your code, in your draw function, you can have a look that runs through the entire myRightClickCoords list and runs drawRect for each set of coordinates.
Once you get that working, you can do the same thing for left click and circles. Good luck!

Can't Create A Timer On Eclipse For Java

I am trying to make a simple game in Java in which many things are moving. I watched a video on moving graphics that said that I need a Timer() to move something on the screen. When I try to make a timer in the form of Timer t = new Timer(5, this); it won't work. It tells me that there should not be any parameters for the method Timer(). Can I please have some help? By the way, I have only been coding java for 2 weeks, so I am very much a beginner. Here is my code:
package FlappyDodgeGame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JFrame;
public class Game extends JFrame implements ActionListener{
static int width = 1000, height = width * 9 / 12;
public static int birdX = width * 1 / 5, birdY = height / 2, birdSize = 75;
public static double birdVel = 0, birdVelDelta = 0.1;
//error: The constructor Timer(int, Game) is undefined. quick fix: Remove arguments to match 'Timer()'.
Timer timer = new Timer(5, this);
public static void main(String args[]){
final JFrame jframe = new JFrame("Test");
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jframe.setSize(width, height);
jframe.setResizable(false);
jframe.setVisible(true);
jframe.setLocationRelativeTo(null);
final GUI gui = new GUI();
jframe.add(gui);
jframe.addMouseListener(new MouseListener(){
public void mouseClicked(MouseEvent arg0) {
// TODO Auto-generated method stub
}
public void mouseEntered(MouseEvent arg0) {
// TODO Auto-generated method stub
}
public void mouseExited(MouseEvent arg0) {
// TODO Auto-generated method stub
}
public void mousePressed(MouseEvent arg0) {
// TODO Auto-generated method stub
}
public void mouseReleased(MouseEvent arg0) {
// TODO Auto-generated method stub
}
});
}
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
}
You're using the wrong Timer class:
import java.util.Timer;
There's another Timer class, javax.swing.Timer, that has a two-arg constructor. The javadoc for this class is here.
For a Swing application, the big advantage of using a javax.swing.Timer instead of a java.util.Timer is that when the Swing timer calls your listener, it does so on the Swing event thread, which means you can immediately call methods on all your UI objects.
if you want to move something on screen, you need to use a class that extends JPanel, and then implement paintComponent(Graphics g)
class Game extends JPanel{
private int x_axis = 0;
private int y_axis = 0;
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// do your painting here
//e.g.
g.drawOval(x_axis, y_axis, 200, 150);
x_axis++;
y_axis++;
//
repaint();
}
}
after that you can add it to your JFrame
frame.add(new Game());

Java: My key isn't being adapted by KeyListener

I'm trying to get my minigame, (paint) to detect keyboard clicks, I.e, Up arrow key to continue the line of an oval. The problem is that when I run the program and enter the up arrow key, or down or left or right, the program doesn't do anything. Please help.
Here's all the code:
package MiniGame;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
public class GameTest extends JFrame{
int x;
int y;
//This class detects the keys pressed.
public class Actionlistener extends KeyAdapter{
public void KeyPressed(KeyEvent ke){
int Listen = ke.getKeyCode();
if(Listen == ke.VK_UP ) {y--;}
if(Listen == ke.VK_LEFT) {x--;}
if(Listen == ke.VK_DOWN) {y++;}
if(Listen == ke.VK_RIGHT){x++;}
}
public void KeyReleased() {
//There's no code here yet.
}
}
//The constructor that initialises some components.
public GameTest() {
addKeyListener(new Actionlistener());
setTitle("Game Test");
setSize(750, 750);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setResizable(false);
x = 150;
y = 150;
} //Paint method.
public void paint(Graphics g) {
g.fillOval(x, y, 20, 20);
repaint();
}
//Creating an object
public static void main(String[] args){
new GameTest();
}
}
Don't use a KeyListener! Swing was designed to be used with Key Bindings.
See Motion Using the Keyboard for more information why you should NOT use a KeyListener and working examples of Key Bindings to get you started.

Graphic Only Moves 1 Pixel to the Right With KeyListener

I'm fairly new to Java programming and I'm working on my first 2D game. I followed one of Oracle's tutorials on Key Listeners in order to figure out how to make my player move with the WASD keys. The example already had a mouse listener. I decided to remove the mouse listener and add a KeyListener. I added the a KeyListener for D which moves my graphic to the right. However, my graphic only moves 1 coordinate to the right rather than updating the new position of the square, and moving it in a continuous loop whenever the D key is pressed. I'm using paint component to draw my image.
Here is my class:
import javax.swing.SwingUtilities;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.BorderFactory;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseMotionAdapter;
public class PaintComponent {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
System.out.println("Created GUI on EDT? "
+ SwingUtilities.isEventDispatchThread());
JFrame f = new JFrame("Swing Paint Demo");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new MyPanel());
f.pack();
f.setVisible(true);
}
}
class MyPanel extends JPanel {
private int squareX = 50;
private int squareY = 50;
private int squareW = 20;
private int squareH = 20;
public int posX = squareX;
public int posY = squareY;
public MyPanel() {
setFocusable(true);
requestFocusInWindow();
setBorder(BorderFactory.createLineBorder(Color.black));
addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
int keyCode = e.getKeyCode();
if (keyCode == KeyEvent.VK_D) {
moveSquareRight(posX);
} else {
e.consume();
}
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
int keyCode = e.getKeyCode();
e.consume();
}
});
/*
* addMouseListener(new MouseAdapter() { public void
* mousePressed(MouseEvent e) { moveSquare(e.getX(),e.getY()); } });
*
* addMouseMotionListener(new MouseAdapter() { public void
* mouseDragged(MouseEvent e) { moveSquare(e.getX(),e.getY()); } });
*/
}
private void moveSquareRight(int x) {
int OFFSET = 1;
if (squareX == x) {
repaint(squareX, squareY, squareW + OFFSET, squareH + OFFSET);
squareX = x + 1;
repaint(squareX, squareY, squareW + OFFSET, squareH + OFFSET);
}
}
public Dimension getPreferredSize() {
return new Dimension(250, 200);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawString("This is my custom Panel!", 10, 20);
g.setColor(Color.RED);
g.fillRect(squareX, squareY, squareW, squareH);
g.setColor(Color.BLACK);
g.drawRect(squareX, squareY, squareW, squareH);
}
}
I'm thinking of turning posX into an array and adding a for loop to it,
No you don't need a loop.
moveSquareRight(posX);
There is no need to pass posX as a parameter since it is a class variable every method has access to it.
Although posX doesn't change and it therefore stays in the same spot.
So update posX.
if (squareX == x) {
repaint(squareX, squareY, squareW + OFFSET, squareH + OFFSET);
squareX = x + 1;
repaint(squareX, squareY, squareW + OFFSET, squareH + OFFSET);
}
You are making the above code too complicated. Try something like:
posX++;
repaint();
You don't want to specify the rectangle to repaint() because the old painting will not be cleared before the rectangle is painted in its new position.
You should also check out Motion Using the Keyboard for an approach the moves a component.

Mouse doesn't maintain it's position when frame is moved across the screen

Here is the code.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.PointerInfo;
import java.awt.Robot;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JPanel;
public class Paint extends JPanel implements MouseMotionListener, MouseListener {
public Paint() {
setBackground(Color.RED);
addMouseMotionListener(this);
addMouseListener(this);
}
private boolean clicked = false;
public void paintComponent (Graphics g) {
super.paintComponent(g);
PointerInfo a = MouseInfo.getPointerInfo();
Point b = a.getLocation();
int x = (int) b.getX() - 3;
int y = (int) b.getY() - 23;
if (clicked) {
g.drawLine(x, y-5000, x,y+5000);
g.drawLine(x+5000,y,x-5000,y);
g.setColor(Color.white);
}
g.drawLine(x, y-5000, x,y+5000);
g.drawLine(x+5000,y,x-5000,y);
g.setColor(Color.black);
// . . .
}
#Override
public void mouseDragged(MouseEvent e) {
repaint();
}
#Override
public void mouseMoved(MouseEvent e) {
repaint();
}
#Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(MouseEvent e) {
clicked = true;
repaint();
}
#Override
public void mouseReleased(MouseEvent e) {
clicked = false;
repaint();
}
}
public class Frame extends JFrame {
public Frame() {
this.setSize(500,500);
this.setTitle("Test painting");
this.setResizable(false);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
Paint panel = new Paint();
this.add(panel);
this.setVisible(true);
}
public static void main (String[] args) {
new Frame();
}
}
When I run the program, it looks like it works fine when the application is in the default position, but once I move the applet to where I like on the screen, the lines don't maintain the current mouse position on screen.
Can someone show me where I've gone wrong or how to fix this?
Painting is done from the context of the component. The Graphics context for any given component is translated so that the top, left corner is 0x0.
MouseInfo.getPointerInfo().getLocation() is returning the location of the mouse on the screen, not the position relative to the component.
While there is a way to fix it, a better solution would be to simply use a MouseMotionListener instead. The MouseEvent sent to this method has already been translated to the component coordinate space...
public void mouseMoved(MouseEvent me) {
myPoint = me.getPoint();
}
Then in you paintComponent method, simple refer to myPoint instead of trying to use MouseInfo
I think that you will be better off to change your class's state in the MouseAdapter, call repaint() and then have your paintComponent(...) method use this state to help it draw. This seems cleaner and safer to me than using MouseInfo in paintComponent(...).
Other than that, if you need more specific help, consider
telling us more about what it is exactly you're trying to do and how your program isn't working.
creating and posting an sscce, a small compilable and runnable program that demonstrates your problem for us.

Categories

Resources