I want to make a fruit basket game. The idea here is that I want to draw fruits from the top of screen to bottom and I also want to do that with timer.I tried several ways but I got no result. Here is what I did but it's totally doing wrong.
Timer timer = new Timer();
while (getY() != 1500) {
timer.schedule(new DrawFruit(frame, g, x) {
#Override
public void run() {
g.drawImage(Toolkit.getDefaultToolkit().getImage(Panel.class.getResource(Consts.ImageResource.APRICOT_DIR)), 500, getY(), frame);
frame.repaint();
setY(getY() + 30);
}
}, 0, 1000);
}
and the DrawFruit Class
abstract class DrawFruit extends TimerTask {
private JFrame jFrame;
private Graphics g;
private int x;
public JFrame getJFrame() {
return jFrame;
}
public void setJFrame(JFrame jFrame) {
this.jFrame = jFrame;
}
public Graphics getG() {
return g;
}
public void setG(Graphics g) {
this.g = g;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public DrawFruit(JFrame frame , Graphics g , int x){
setJFrame(frame);
setG(g);
setX(x);
}
#Override
public void run() {
}
}
You should NOT be using looping code. The point of a Timer is that it replaces the loop. All a Timer does is generate an event at your specified time interval. So when the event is generated you just adjust the "Y" value and repaint the component.
However, you should not be using a TimerTask for this.
Swing components should be updated on the Event Dispatch Thread (EDT). Therefore you should be using a Swing Timer. Read the tutorial for a working example to get you started.
Related
I decided I wanted to experiment with making a game and I like Java, so I started following a tutorial here. I did deviate from the video a few times when I felt it was cleaner while being synonymous with the tutorial's code, but not in any way I thought would affect how the code worked. For example, it made sense to me that there should only ever be one instance of the Renderer, and Object Registry so I made them Singletons.
The code I have so far is supposed to create a window with a black background, and a blue square in the middle of the window representing the player, that much is working. However, it should also be sliding around in response to the wasd keys, and even more slowly drifting in one direction regardless. Instead it's doing nothing.
I spent no less than an hour trying to figure out why it wasn't working. It seems to be ticking just fine and the data looks like it's updating properly, but even though my render methods are also being called, the screen just isn't changing.
This is all the code I have so far, since I'm out of ideas as to the problem. I apologize for listing a whole project.
public class Game implements Runnable {
private final Thread thread;
private boolean running = false;
Game() {
thread = new Thread(this);
}
public static void main(String[] args) {
Game game = new Game();
game.start();
new Player(600,450,0));
}
private void start() {
thread.start();
running = true;
}
#Override
public void run() {
double tps = 10.0;
double nsPerTick = 1000000000 / tps;
double delta = 0;
int frames = 0;
long timer = System.currentTimeMillis();
long lTime = System.nanoTime();
long now;
while (running) {
now = System.nanoTime();
delta += (now - lTime) / nsPerTick;
lTime = now;
while (delta >= 1) {
Registry.getInstance().tick();
delta--;
}
if (running) Renderer.getInstance().run();
frames++;
if (System.currentTimeMillis() - timer > 1000) {
timer += 1000;
System.out.println("FPS: " + frames);
frames = 0;
}
}
stop();
}
private void stop() {
try {
thread.join();
} catch (Exception e) {
e.printStackTrace();
}
running = false;
}
}
public class Renderer extends Canvas {
private static final Renderer renderer = new Renderer();
private final Window window;
private final BufferStrategy bs;
private final Graphics g;
boolean black = true;
private Renderer() {
window = new Window(1200, 900, "First Game", this);
this.createBufferStrategy(2);
bs = this.getBufferStrategy();
g = bs.getDrawGraphics();
addKeyListener(Controller.getInstance());
}
public static Renderer getInstance() {return renderer;}
public void run() {
g.setColor(Color.BLACK);
//this was to see if even the background would update, it wouldn't
//g.setColor(black ? Color.BLACK : Color.WHITE);
//black = !black;
g.fillRect(0,0,1200, 900);
Registry.getInstance().render();
g.dispose();
bs.show();
}
public Graphics getGraphics() {return g;}
private static class Window extends Canvas {
private Window(int width, int height, String title, Renderer renderer) {
JFrame frame = new JFrame(title);
frame.setPreferredSize(new Dimension(width, height));
frame.setMinimumSize(new Dimension(width, height));
frame.setMaximumSize(new Dimension(width, height));
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.add(renderer);
frame.setVisible(true);
}
}
}
public class Registry {
private static final Registry reg = new Registry();
private final LinkedList<GameObject> objects = new LinkedList<>();
private Registry() {
}
public static Registry getInstance() { return reg; }
public void tick() { //System.out.println("tick");
objects.forEach(GameObject::tick); }
public void render() { objects.forEach(GameObject::render); }
public void add(GameObject gameObject) { objects.add(gameObject); }
public void remove(GameObject gameObject) { objects.remove(gameObject);}
}
public class Controller extends KeyAdapter {
private static final Controller controller = new Controller();
private final HashMap<Character,Boolean> keyStates = new HashMap<>();
private Controller() {
}
public static Controller getInstance() {
return controller;
}
public void keyPressed(KeyEvent e) {
if (!keyStates.getOrDefault(e.getKeyChar(), true)) System.out.println(e.getKeyChar() + " down");
keyStates.put(e.getKeyChar(),true);
}
public void keyReleased(KeyEvent e) {
keyStates.put(e.getKeyChar(),false);
System.out.println(e.getKeyChar() + " up " + keyStates.size());
}
public boolean isKeyDown(char c) {return keyStates.getOrDefault(c,false);}
}
public abstract class GameObject {
protected Graphics graphics = Renderer.getInstance().getGraphics();
protected final ObjectType type;
protected float x,y,r;
protected GameObject(ObjectType objectType, float x, float y, float r) {
this.type = objectType;
this.x = x;
this.y = y;
this.r = r;
Registry.getInstance().add(this);
}
public abstract void tick();
public abstract void render();
public void destroy() { Registry.getInstance().remove(this); }
public float getX() { return x; }
public void setX(float x) { this.x = x; }
public float getY() { return y; }
public void setY(float y) { this.y = y; }
public float getR() { return r; }
public void setR(float r) { this.r = r; }
}
public class Player extends GameObject {
private final Controller controller;
public Player(float x, float y, float r) {
super(ObjectType.PLAYER, x, y, r);
controller = Controller.getInstance();
}
#Override
public void tick() {
this.x += 1;
if (controller.isKeyDown('w')) x += 2;
if (controller.isKeyDown('a')) y -= 2;
if (controller.isKeyDown('s')) x -= 2;
if (controller.isKeyDown('d')) y += 2;
}
#Override
public void render() {
graphics.setColor(Color.BLUE);
graphics.fillRect((int) (this.x-12),(int) (this.y-12), 24,24);
}
}
The problem lies in your handling of Graphics. There's only ONE active Graphics object you can effectively address.
Refactor your code, so that you pass the current Graphics object via parameter through the target methods (like here: Player.render() should become Player.render(Gpahics g). And get rid of the Gameobject.graphics member variable. That is the culprit.
Adding to that, the best way to do simple rendering is to override the paint(Graphics g) method or the paintComponents(Graphics g), and from outside call repaint() on the JPanel/Canvas. This way the UI instigates drawing itself, takes care of the actual frequency, and draws default components/design too if there is some.
I had tried to add the listener to the object of the Snake class , to the object of the Window class and object of JFrame class I created in the constructor of the Snake class, but it still does not work. Сharacters that must be written and the snake must turn, if i press any key, but it doesn't happen. Сan it be because of the snakeThread?
public class Main {
public static void main(String[] args) {
Window window = new Window();
System.out.print("k");
}
}
import javax.swing.*;
import java.awt.*;
public class Window extends JPanel {
private Snake snake;
public Window() {
super(true);
snake = Snake.getSnake(50, 50);
Thread snakeThread = new Thread(snake);
snakeThread.start();
}
#Override
public void paint(Graphics g) {
super.paint(g);
snake.paint(g);
}
}
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
public class Snake extends JPanel implements Runnable {
public static int length;
public static ArrayList<Point> parts;
public static Field field;
public static Food food;
public static int speedX=0;
public static int speedY=1;
private static Snake snake = null;
public static final int TIME_DELTA = 1000;
public static Snake getSnake(int w, int h)
{
if(snake == null) {
snake = new Snake(w, h);
snake.addKeyListener(new Turn(snake));
}
return snake;
}
private Snake(int Width, int Heigth) {
JFrame jf = new JFrame();
jf.setSize(500,500);
jf.add(this); //this - это Jpanel которым расширяется Snake
jf.setVisible(true);
food = new Food();field = Field.getField();
Point start = new Point((int)Width/2, (int)Heigth/2); //размеры поля, а не окна
parts = new ArrayList<>();parts.add(start);
Point p1 = new Point((int)start.getX(), ((int)start.getY())-1);parts.add(p1);
Point p2 = new Point((int)start.getX(), ((int)p1.getY())-1);
parts.add(p2);length = 3;
}
private boolean checkHead()
{
for (int i=1; i<parts.size(); ++i)
{
if(parts.get(parts.size()-1).getLocation() == parts.get(i).getLocation())
return false;
}
if(parts.get(parts.size()-1).getX() <=0 || parts.get(parts.size()-1).getX() >= field.sizeX ||
parts.get(parts.size()-1).getY() <=0 || parts.get(parts.size()-1).getY() >= field.sizeY )
return false;
return true;
}
public static void move()
{
for (Point i: parts)
{
i.y=i.y-1*speedY;
i.x-=1*speedX;
}
}
public static void eat()
{
Point np = new Point ((int)parts.get(length).getX(),(int)parts.get(length).getY()-1 );
parts.add(np);
++length;
food.respawn();
}
public static boolean checkFood()
{
if(parts.get(parts.size()-1).getX() == food.x && parts.get(parts.size()-1).getY()==food.y)
return true;
else
return false;
}
#Override
public void paint(Graphics g) {
super.paint(g);
for (Point i: parts)
g.fillRect((int) i.getX() * 10, (int) i.getY() * 10, 8, 8);
g.setColor(Color.RED);
g.fillRect(food.x * 10, food.y * 10, 8, 8);
g.setColor(Color.BLACK);
}
#Override
public void run() {
while (checkHead()) {
move();
repaint();
if(checkFood())
eat();
try {
Thread.sleep(TIME_DELTA);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void turn(char Key)
{
int delta = 0;
for(Point i: parts)
{
switch (Key) {
case 'a':
i.y=parts.get(parts.size()-1).y;
i.x=parts.get(parts.size()-1).x+delta;
break;
case'd':
i.y=parts.get(parts.size()-1).y;
i.x=parts.get(parts.size()-1).x-delta;
break;
case 'w':
i.x=parts.get(parts.size()-1).x;
i.y=parts.get(parts.size()-1).y-delta;
break;
case's':
i.x=parts.get(parts.size()-1).x;
i.y=parts.get(parts.size()-1).y+delta;
break;
}
++delta;
}
repaint();
}
}
import javax.swing.*;
import java.awt.*;
import java.util.Random;
public class Food extends JPanel {
public static int x;
public static int y;
private static Random random;
public Food()
{
super(true);
random = new Random();
x = random.nextInt(50);
y = random.nextInt(50);
}
#Override
public void paint(Graphics g) {
super.paint(g);
g.setColor(Color.RED);
g.fillRect(x * 10, y * 10, 8, 8);
g.setColor(Color.BLACK);
}
public void respawn()
{
x = random.nextInt(40);
y = random.nextInt(40);
repaint();
}
}
The listener is here:
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class Turn implements KeyListener {
private char key = 'O';
private Snake snake;
public Turn(Snake s)
{
this.snake = s;
}
#Override
public void keyTyped(KeyEvent e) {
System.out.println("0");//when I press a button, "0" must be written, but it doesn't
if(e.getKeyChar() == 'A')
{
System.out.println("a");//this character too
if(snake.speedX==0)
{
snake.speedX=-1;//speedX was not changed
snake.speedY=0;
key='a';
}
}
else if (e.getKeyChar() == 'W')
{
System.out.println("w");
if(snake.speedY==0)
{
snake.speedY=-1;
snake.speedX=0;
key='w';
}
}
else if (e.getKeyChar() == 'S')
{
System.out.println("s");
if(snake.speedY==0)
{
snake.speedY=1;
snake.speedX=0;
key='s';
}
}
else if (e.getKeyChar() == 'D')
{
System.out.println("d");
if(snake.speedX==0)
{
snake.speedX=1;
snake.speedY=0;
key='d';
}
}
if(key!='O')
snake.turn(key);
}
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
}
}
Never invoke paint(...) directly on a component. If you need to paint a component you invoke repaint() on that component. Swing will then paint(...) that component and invoke paint(...) on all the child components added to the panel.
So this means you need to add the Snake component to the parent game panel. It also means there is no reason to override the paint() method of the Window panel.
Don't use static variables and methods. This is an indication of poor design. Remove the static keyword from the variables and methods.
For animation you should be using a Swing Timer, not a Thread. Updates to Swing components should be done on the Event Dispatch Thread (EDT). The Timer will execute code on the EDT.
Don't use a KeyListener. Swing was designed to be used with Key Bindings. See: Motion Using the Keyboard for more information and examples.
Custom painting is done by overriding paintComponent(...) not paint(...).
The point of the main() method is to create the frame and add the game panel to the frame. The game panel should NOT create the frame.
I agree with everything in the answer from camickr. There are many things wrong in your code, and starting from scratch with those things in mind will help avoid many of the issues you are facing.
However, your actual issue is this line private static Snake snake = null; and this method:
public static Snake getSnake(int w, int h)
{
if(snake == null) {
snake = new Snake(w, h);
snake.addKeyListener(new Turn(snake));
}
return snake;
}
You should NEVER need to create a self reference inside a class like that. The Snake class is already a Snake object, so using private static Snake snake = null; inside the class simply creates a new reference to a completely new and different Snake within your Snake. Instead, you need to use the this keyword to refer to the Snake object, for example, this.addKeyListener(new Turn(this)); instead of snake.addKeyListener(new Turn(snake));
Delete/remove the getSnake method, you are trying to mix static and non static objects and it is not needed, we can move the keylistener part of the method to our constructor (see below). Note that if you want to update the width and height of your snake then you should make a different method that updates the parts and p1 and p2 separately.
Fixing the Snake class:
The fixed Snake class might look something like this:
public class Snake extends JPanel implements Runnable {
//None of the variables or methods should be static
//remove the static keyword from everywhere in the Snake class
public int length;
public ArrayList<Point> parts;
public Field field;
public Food food;
public int speedX=0;
public int speedY=1;
public final int TIME_DELTA = 1000;
//The constructor needs to be a public method (Not private)
public Snake(int Width, int Heigth) {
//Delete all the JFrame code,
//it should be done in the main method
//Add the key ilstener here (moved from the getSnake method)
this.addKeyListener(new Turn(this));
//Create the snake
food = new Food();
field = Field.getField();
Point start = new Point((int)Width/2, (int)Heigth/2); //размеры поля, а не окна
parts = new ArrayList<>();
parts.add(start);
Point p1 = new Point((int)start.getX(), ((int)start.getY())-1);parts.add(p1);
Point p2 = new Point((int)start.getX(), ((int)p1.getY())-1);
parts.add(p2);
length = 3;
}
//Rest of the code removed for clarity
...
}
Fix the main method and delete the Window class:
To use this updated Snake class you can completely delete the Window class and use something like this in your main class:
public class Main {
public static void main(String[] args) {
//Create JFrame
JFrame jf = new JFrame();
jf.setSize(500,500);
//Create Snake
Snake snake = new Snake(50, 50);
//Add Snake to JFrame and set the frame visible
jf.add(snake);
jf.setVisible(true);
//Finally start the Snake thread
Thread snakeThread = new Thread(snake);
snakeThread.start();
}
}
There are still a bunch of things that need fixing, but this should solve your key listener not working.
Other fixes:
Instead of key listeners a better solution is to use key bindings. We can create a key binding like this in you main method:
//Key binding to trigger when KeyEvent.VK_W ('w') is pressed
snake.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0), "NORTH");
snake.getActionMap().put("NORTH", new AbstractAction()
{
#Override
public void actionPerformed(ActionEvent e)
{
//Your code here to change the snake direction
//we can call the turn method from inside this snake object/class
snake.turn('w');
}
});
You should override protected void paintComponent(Graphics g) instead of public void paint(Graphics g), inside your Snake class like this:
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
for (Point i: parts)
g2d.fillRect((int) i.getX() * 10, (int) i.getY() * 10, 8, 8);
g2d.setColor(Color.RED);
g2d.fillRect(food.x * 10, food.y * 10, 8, 8);
g2d.setColor(Color.BLACK);
}
Lastly, instead of making your Snake class implement Runniable you should create a simple stand alone swing timer something like this inside your Snake class:
void startTimer(){
//Start timer to update snake location every 100ms
Timer timer = new Timer(100, new ActionListener(){
#Override
public void actionPerformed(ActionEvent ae){
//Your code here to update and repaint the snake location
snake.updateLocation();
}
});
timer.start();
}
And in your main method you can simple use snake.startTimer(); instead of Thread snakeThread = new Thread(snake); and snakeThread.start();
I am new to graphics and japplets, and I made a rectangle that goes across the screen. But for some reason, it just draws a line across, not removing the old instance of the rectangle once it moves.
Main:
public class Main extends JApplet implements Runnable {
private static final long serialVersionUID = 1L;
private static int width = 900;
private static int height = 600;
public static int fps = 60;
public Thread thread = new Thread(this);
public static Ailoid ailoid = new Ailoid();
public void init() {
setSize(width, height);
setBackground(Color.white);
ailoid.setLocation(new Location(100, 100));
AlienManager.registerAlien(ailoid);
}
public void paint(Graphics g) {
g.setColor(Color.green);
for (Alien alien : AlienManager.getAliens()) {
Location loc = alien.getLocation();
int x = loc.getX();
int y = loc.getY();
g.fillRect(x, y, 10, 20);
}
}
// Thread start
#Override
public void start() {
thread.start();
}
// Thread stop
#SuppressWarnings("deprecation")
#Override
public void destroy() {
thread.stop();
}
#Override
public void run() {
while (true) {
Updater.run();
repaint();
try {
// 1000 divided by fps to get frames per millisecond
Thread.sleep(1000 / fps);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Updater:
public class Updater {
public static void run() {
for (Alien alien : AlienManager.getAliens()) {
Location loc = alien.getLocation();
int x = loc.getX();
int y = loc.getY();
alien.setLocation(new Location(x, y));
}
}
}
Why doesn't it remove the old graphics? thank you!
Your main problem is that your paint(...) method does not call the super method, the method that allows the component to redraw its contents:
public void paint(Graphics g) {
super.paint(g);
//....
Having said that, you're far better off not drawing in a top level window but rather in the paintComponent method of a JPanel that is displayed by the applet. If you do this correction, then do the same thing -- call the super method.
class MyPanel extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
//....
As an aside, this code:
public class Updater {
public static void run() {
for (Alien alien : AlienManager.getAliens()) {
Location loc = alien.getLocation();
int x = loc.getX();
int y = loc.getY();
alien.setLocation(new Location(x, y));
}
}
}
Doesn't look like it's moving things all that much. In fact per this code, your aliens should stay completely still.
Edit
Also, this is never code, code you should never have in your application:
#SuppressWarnings("deprecation")
#Override
public void destroy() {
thread.stop();
}
There's a reason that thread's stop() method is deprecated and should never be called. If you're curious as to why, please check out the API.
I'm trying to write a Pong applet in Java. When the user holds down either up or down, their paddle should move smoothly, but this isn't the case. It moves, then pauses, then starts moving again. Is there a way to stop this short pause from happening?
Main Class:
public class Main extends JApplet {
public DrawPanel dp = new DrawPanel(400, 400);
public void init(){
add(dp);
setSize(400, 400);
requestFocusInWindow();
Action moveDown = new AbstractAction(){
public void actionPerformed(ActionEvent e){
dp.player.y += 10;
dp.repaint();
}
};
dp.getInputMap().put(KeyStroke.getKeyStroke("pressed DOWN"), "move down");
dp.getActionMap().put("move down", moveDown);
}
}
DrawPanel Class:
public class DrawPanel extends JPanel {
public Paddle player;
public Paddle opponent;
public DrawPanel(int height, int width){
int y = (height / 2) - (height / 10);
int w = 15;
int h = height / 5;
player = new Paddle(2, y, 15, h, Color.white);
opponent = new Paddle(width - (w+2), y, 15, h, Color.white);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
this.setBackground(Color.BLACK);
g.setColor(player.color);
g.fillRect(player.x, player.y, player.width, player.height);
g.setColor(opponent.color);
g.fillRect(opponent.x, opponent.y, opponent.width, opponent.height);
}
}
Paddle Class:
public class Paddle {
public int x, y, width, height;
public Color color;
public Paddle(int _x_, int _y_, int w, int h, Color c){
x = _x_;
y = _y_;
width = w;
height = h;
color = c;
}
}
The underlying issue is an impedance mismatch between the "instance" notion of a keyPressed and the "duration" notion of the movement.
Instead of trying to smooth that over in the view (which shouldn't have anything to do with the details of the game logic anyway), enhance the game model with api that's a better fit. F.i. add start/stop logic and bind those methods to keyPressed/keyReleased:
public class Paddle {
public void startMoveDown() {
// here goes the logic, f.i. starting a timer
// in the actionPerformed of that timer:
... moveUnitDown();
}
public void stopMoveDown() {
//...
}
protected void moveUnitDown() {
y+=unit;
// ideally, have listeners and notify them the change of y
}
}
// in the view:
Action startMoveDown = new AbstractAction(){
public void actionPerformed(ActionEvent e){
player.startMoveDown();
}
};
dp.getInputMap().put(KeyStroke.getKeyStroke("pressed DOWN"), "start move down");
dp.getActionMap().put("start move down", startMoveDown);
// in the view:
Action stopMoveDown = new AbstractAction(){
public void actionPerformed(ActionEvent e){
player.stopMoveDown();
}
};
dp.getInputMap().put(KeyStroke.getKeyStroke("released DOWN"), "stop move down");
dp.getActionMap().put("stop move down", stopMoveDown);
I want to see all the Points one after another but I see only able to see 1
point. What shold I change to see all the Points ?
In the System.out you can see 10 times "set" and then 2 times
"paintComponent". what should I change that after each time set is
called it change the "paintComponente" ?
==================================================================================
public class exampe extends JPanel
{
int x;
int y;
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.fillOval(x-2,y-2,4,4);
System.out.println("paintComponent");
}
public void set(int X, int Y)
{
x = X;
y = Y;
System.out.println("set");
super.repaint();
}
public static void main(String args[])
{
int e=1;
JFrame frame = new JFrame("TEST");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
exampe ex= new exampe();
JScrollPane scroll = new JScrollPane(ex);
frame.getContentPane().add(scroll);
frame.setSize(400, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
for(int i=0; i< 10; ++i)
ex.set(e+i,e+i);
}
}
*SIMPLE EXPLANATION AS TO WHY YOU COULD ONLY SEE THE LAST UPDATE : *
A quote taken from Filthy Rich Clients by Chet Haase and Romain Guy
It is important to note that repaint requests get “coalesced,” or combined.
So, for example, if you request a repaint and there is already one on the
queue that has not yet been serviced, then the second request is ignored
because your request for a repaint will already be fulfilled by the earlier
request. This behavior is particularly helpful in situations where many
repaint requests are being generated, perhaps by very different situations
and components, and Swing should avoid processing redundant requests and
wasting effort.
Try your hands on this, and ask what is not clear to you :
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class PointsExample
{
private CustomPanel contentPane;
private Timer timer;
private int x = 1;
private int y = 1;
private ActionListener timerAction = new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
contentPane.set(x, y);
x++;
y++;
if (x == 450)
timer.stop();
}
};
/*
* This is just JFrame, that we be
* using as the Base for our Application.
* Though here we are calling our
* JPanel (CustomPanel), whose
* paintComponent(...) method, we had
* override.
*/
private void createAndDisplayGUI()
{
JFrame frame = new JFrame("Locate Mouse Position");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
contentPane = new CustomPanel();
frame.setContentPane(contentPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
timer = new Timer(100, timerAction);
timer.start();
}
public static void main(String\u005B\u005D args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new PointsExample().createAndDisplayGUI();
}
});
}
}
class CustomPanel extends JComponent
{
private int x;
private int y;
public void set(int a, int b)
{
x = a;
y = b;
repaint();
}
#Override
public Dimension getPreferredSize()
{
return (new Dimension(500, 500));
}
#Override
public void paintComponent(Graphics g)
{
g.clearRect(0, 0, getWidth(), getHeight());
Graphics2D g2 =(Graphics2D) g;
g2.fillOval(x, y, 4, 4);
}
}
Here is the code, that will allow you to have a look at your points while iterating inside a for loop, though this approach is highly discouraged, for many cons associated with it. Though try your hands on this instead of calling repaint() call paintImmediately(int ...) or paintImmediately(Rectangle rect)
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class PointsExample
{
private CustomPanel contentPane;
private Timer timer;
private int x = 1;
private int y = 1;
/*
* This is just JFrame, that we be
* using as the Base for our Application.
* Though here we are calling our
* JPanel (CustomPanel), whose
* paintComponent(...) method, we had
* override.
*/
private void createAndDisplayGUI()
{
JFrame frame = new JFrame("Locate Mouse Position");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
contentPane = new CustomPanel();
frame.setContentPane(contentPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
for (int i = 0; i < 500; i++)
{
contentPane.set(x, y);
x++;
y++;
if (x == 450)
break;
}
}
public static void main(String\u005B\u005D args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new PointsExample().createAndDisplayGUI();
}
});
}
}
class CustomPanel extends JComponent
{
private int x;
private int y;
public void set(int a, int b)
{
x = a;
y = b;
paintImmediately(0, 0, getWidth(), getHeight());
}
#Override
public Dimension getPreferredSize()
{
return (new Dimension(500, 500));
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.fillOval(x, y, 4, 4);
}
}
1: first line of paintComponent() should be your super.paintComponent()
2: why are you calling super.repaint(), make it simply repaint()
Your Drow should be like this.
public class drow extends JPanel {
...........
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 =(Graphics2D) g;
}
public void set_list(LinkedList <point> p){
Points =p;
repaint();
}
try with this.
i hope this is simply a structure, your paintComponent() isn't drawing anything.
EDIT
public void set_list(LinkedList <point> p){
Points =p;
System.out.println("set_ist");// 1:First this line will be displayed then..
repaint();//2: Then this is called, which in turn calls your `paintComponent()`
}
Now when your paintComponent() is called it has
system.out.println("paintComponent");
//3: so now this will be displayed.
Where is the problem here?
EDIT- SWING TIMER
Your code was ok, but the function processing is way faster than GUI updation, thats why you were unable to see the changes in front of you. The way you were doing, of calling thread.sleep() between function calls to slow down it's call, was not a good approach. For any timing thing's in swing, use swing timer, i changed your code for swing timer.
Using Swing Timer:
public class exampe extends JPanel implements ActionListener {
int x;
int y;
int temp = 0;
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.fillOval(x - 2, y - 2, 4, 4);
}
public void set(int X, int Y) {
x = X;
y = Y;
}
public static void main(String args[]) {
JFrame frame = new JFrame("TEST");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
exampe ex = new exampe();
JScrollPane scroll = new JScrollPane(ex);
frame.getContentPane().add(scroll);
frame.setSize(400, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
Timer PointTimer = new Timer(1000, ex);
PointTimer.setInitialDelay(1000);
PointTimer.start();
System.out.println("started");
}
#Override
public void actionPerformed(ActionEvent e) {
// set(rand.nextInt(350), rand.nextInt(350));
set(temp+10,temp+10);
temp=temp+2;
repaint();
}
}