My repaint in JFrame is not working - java

I have a problem with repaint in JFrame i used repaint() earlier when i was making an animation and everything worked
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Draw extends JComponent implements KeyListener {
int x = 0;
int y = 0;
public void paint(Graphics g){
g.setColor(Color.BLUE);
g.fillRect(x, y, 50, 50);
}
public void keyPressed(KeyEvent k) {
if(k.getKeyCode() == KeyEvent.VK_UP){
y -= 2;
} else if(k.getKeyCode() == KeyEvent.VK_DOWN){
y += 2;
} else if(k.getKeyCode() == KeyEvent.VK_LEFT){
x -= 2;
} else if(k.getKeyCode() == KeyEvent.VK_RIGHT){
x += 2;
}
repaint();
}
public void keyReleased(KeyEvent k) {}
public void keyTyped(KeyEvent k) {}
}
This is my draw class which if i run as an applet everything works but i don't want an applet
My frame class
import javax.swing.*;
public class Frame {
Draw d = new Draw();
public Frame(){
JFrame f = new JFrame("Game");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(800, 600);
f.setVisible(true);
f.add(d);
f.addKeyListener(new Draw());
}
}
and my Main class
public class Main {
public static void main(String[] args) {
Frame f = new Frame();
}
}
The repaint() is the one not working i tested the key listener it works so why isn't the repaint() working?

The KeyListener shouldn't be working since a JComponent by default cannot get program focus, a necessary requirement for a KeyListener to work. One solution is to make it focusable via setFocusable(true) and then call requestFocusInWindow() on it. Better to use Key Bindings (tutorial link). Note that you should be overriding paintComponent, not paint and you should not forget to call the super's method within your override.
For example
Edit: I'm wrong since a JFrame can get focus and you're adding the KeyListener to the JFrame. But your problem is that you are creating a new Draw object to do this, not to the original displayed Draw object. Your code would actually work if you use the same Draw object for both displaying the image and for KeyListener:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Draw extends JComponent implements KeyListener {
int x = 0;
int y = 0;
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLUE);
g.fillRect(x, y, 50, 50);
}
public void keyPressed(KeyEvent k) {
if (k.getKeyCode() == KeyEvent.VK_UP) {
y -= 2;
} else if (k.getKeyCode() == KeyEvent.VK_DOWN) {
y += 2;
} else if (k.getKeyCode() == KeyEvent.VK_LEFT) {
x -= 2;
} else if (k.getKeyCode() == KeyEvent.VK_RIGHT) {
x += 2;
}
repaint();
}
public void keyReleased(KeyEvent k) {
}
public void keyTyped(KeyEvent k) {
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Draw d = new Draw();
JFrame f = new JFrame("Game");
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setSize(800, 600);
f.setVisible(true);
f.add(d);
f.addKeyListener(d);
}
});
}
}
Safer though is to use Key Bindings.

Related

Have a transparent background?

So, I'm trying to make this simple paint-like program, and it's been pretty successful until now, but I have this one problem. When I run the app, the background is transparent, and it renders the screen, except for that everything is working fine. Also, if I use super.paint(); , the screen starts blinking, flickering, and it ain't no good. I am currently using eclipse, following a tutorial, and the guy seems to be having everything work just fine. I am also an absolute beginner, so bear with me and explain everything please, as I have only been learning Java for 3 days by now.
package JavaMain;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
public class javamain extends JFrame {
int x, y;
private static final long serialVersionUID = 1L;
private class AL extends KeyAdapter {
private int keycode;
#SuppressWarnings("static-access")
public void keyPressed(KeyEvent event) {
keycode = event.getKeyCode();
if (keycode == event.VK_LEFT) {
x--;
}
if (keycode == event.VK_RIGHT) {
x++;
}
if (keycode == event.VK_UP) {
y--;
}
if (keycode == event.VK_DOWN) {
y++;
}
}
public void keyReleased(KeyEvent e) {}
}
public javamain() {
addKeyListener(new AL());
setTitle("Statistic");
setSize(600, 800);
setResizable(false);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
x = 200;
y = 200;
}
public void paint(Graphics g) {
g.fillRect(x, y, 2, 2);
repaint();
}
public static void main(String[] args) {
new javamain();
}
}
First...
You are breaking the paint chain...
public void paint (Graphics g)
{
// You MUST call super.paint here...
g.drawString("Hello World!", 250, 250);
}
Second
You should avoid, at all cost, overriding paint of a top level container like JFrame. Lots of reasons, one of which you just found, but also because top level containers are not double buffered, which will introduce flickering when the are painted and JFrame contains a bunch of other components, the JRootPane, the content pane, the glass pane...all of which could paint over what you are trying to paint.
Also, painting directly to the frame allows you to paint under the frame's decorations, which isn't really what you want to do...
For example (of why it's bad)...
How to get the EXACT middle of a screen, even when re-sized
How can I set in the midst?
Java AWT drawString() does not display on window
The solution...
Create a custom class extending from something like JPanel and override it's paintComponent method and perform your custom painting there. You gain double buffering support for free and no longer have to worry about the frame's borders, as the content pane will ensure that it's maintained with inside the frame decorations.
See Painting in AWT and Swing and Performing Custom Painting for more details
Also, call setResizable before setting the size of the frame, this changes the size of the frames decorations and can produce unexpected additional spacing within the frames content area...
third....
Then finally i will share a code that would really helps you to get some better ideas about what you are asking
public class Main extends JPanel implements KeyListener
{
private Point startPoint = new Point(0, 0);
private Point endPoint = new Point(0, 0);
public Main()
{
addKeyListener(this);
}
public void keyPressed(KeyEvent evt)
{
int keyCode = evt.getKeyCode();
int d;
if (evt.isShiftDown())
d = 5;
else
d = 1;
if (keyCode == KeyEvent.VK_LEFT)
add(-d, 0);
else if (keyCode == KeyEvent.VK_RIGHT)
add(d, 0);
else if (keyCode == KeyEvent.VK_UP)
add(0, -d);
else if (keyCode == KeyEvent.VK_DOWN)
add(0, d);
}
public void keyReleased(KeyEvent evt)
{
}
public void keyTyped(KeyEvent evt)
{
}
public boolean isFocusTraversable()
{
return true;
}
public void add(int dx, int dy)
{
endPoint.x += dx;
endPoint.y += dy;
Graphics g = getGraphics();
g.drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y);
g.dispose();
startPoint.x = endPoint.x;
startPoint.y = endPoint.y;
}
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setTitle("Sketch");
frame.setSize(300, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container contentPane = frame.getContentPane();
contentPane.add(new Main());
frame.setVisible(true);
}
}

Difference between implementing JFrame and JPanel

I was trying to understand the difference between JFrame and JPanel. I tend to use subclasses of JFrame instead of JPanel, but people always tell me that it's better to use a subclass of JPanel instead. Here is an example of me using JFrame:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
public class Game extends JFrame implements Runnable {
int x, y, xCoord, yCoord;
private Image dbImage;
private Graphics dbg;
public void move() {
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 class AL extends KeyAdapter {
#Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == e.VK_LEFT) {
setXCoord(-1);
}
if (keyCode == e.VK_RIGHT) {
setXCoord(+1);
}
if (keyCode == e.VK_UP) {
setYCoord(-1);
}
if (keyCode == e.VK_DOWN) {
setYCoord(+1);
}
Game.this.repaint();
}
#Override
public void keyReleased(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == e.VK_LEFT) {
setXCoord(0);
}
if (keyCode == e.VK_RIGHT) {
setXCoord(0);
}
if (keyCode == e.VK_UP) {
setYCoord(0);
}
if (keyCode == e.VK_DOWN) {
setYCoord(0);
}
Game.this.repaint();
}
}
public static void main(String[] args) {
Game game = new Game();
Thread t = new Thread(game);
t.start();
}
public Game() {
addKeyListener(new AL());
setTitle("Game");
setSize(500, 500);
setResizable(true);
setVisible(true);
setBackground(Color.BLACK);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
x = 250;
y = 250;
}
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) {
move();
Thread.sleep(30);
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
This works fine (except for there being a small delay when I hold down one of the buttons), but when I try to change my code by implementing JPanel instead of JFrame, nothing shows up... Here's the code for the JPanel subclass:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
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 move() {
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 class AL extends KeyAdapter {
#Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == e.VK_LEFT) {
setXCoord(-1);
}
if (keyCode == e.VK_RIGHT) {
setXCoord(+1);
}
if (keyCode == e.VK_UP) {
setYCoord(-1);
}
if (keyCode == e.VK_DOWN) {
setYCoord(+1);
}
Game.this.repaint();
}
#Override
public void keyReleased(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == e.VK_LEFT) {
setXCoord(0);
}
if (keyCode == e.VK_RIGHT) {
setXCoord(0);
}
if (keyCode == e.VK_UP) {
setYCoord(0);
}
if (keyCode == e.VK_DOWN) {
setYCoord(0);
}
Game.this.repaint();
}
}
public static void main(String[] args) {
Game game = new Game();
Thread t = new Thread(game);
t.start();
}
public Game() {
frame = new JFrame();
frame.addKeyListener(new AL());
frame.setTitle("Game");
frame.setSize(500, 500);
frame.setResizable(true);
frame.setVisible(true);
frame.setBackground(Color.BLACK);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
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) {
move();
Thread.sleep(30);
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
As the code shows, you need a custom JPanel, because you want to change the behavior of some methods like paintComponent.
However, you don't need a custom JFrame, so no need to create a class extending it.
Finally, your main class has no need to be your panel class.
Here is an example class, I moved the frame stuff from Game's constructor to this main class.
public class MainClass {
public static void main(String[] args) {
Game game = new Game();
JFrame frame = new JFrame();
frame.addKeyListener(new AL());
frame.setTitle("Game");
frame.setSize(500, 500);
frame.setResizable(true);
frame.getContentPane().add(game);
frame.setBackground(Color.BLACK);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
Thread t = new Thread(game);
t.start();
}
}
A JFrame is a far more complex component then you might think, for starters, it has a JRootPane as it's primary container, which contains the contentPane, JMenuBar and controls the glassPane
see How to Use Root Panes for more details.
The JFrame also has decorations (borders), these borders are painted within the confines of the window itself, the contents are then laid out within these, so the borders don't paint over then.
When you override paint of a top level container, like JFrame, there are a number of issues which you run into:
It's not double buffered, which can cause flickering as the window is updated
The other components can be painted independently of the frame (so the frame's paint method is not called), which can cause no end of issues
You can now paint beneath the frame's decorations, see Java graphic image, How to get the EXACT middle of a screen, even when re-sized and How can I set in the midst? for more details.
You're locking your self into a single use case, you can't add windows to other containers, which reduces your components re-use value
Generally speaking, from a OOP point of view, you're not actually adding any new functionality to the class (or least none which can't be generated through better approaches).
When you use something like JPanel, all other the above are no longer of concern:
They are double buffered by default
If you use a layout manager (on the content pane), the component will be laid out within the frame's decorations
The width and height of the component represent the whole viewable area
You can add this component to what ever container you want
You should also override the JPanel's getPreferredSize method and return the preferred size you want your panel to generally be, then you can use JFrame#pack to "pack" the window around it, this will make the window larger then the content area, but means you're not scratching your head wondering why you set the window to a certain size, but your component is smaller

Repaint taking up too much CPU

I'm writing a simple drawing program that uses keyListeners. It works, but every time it needs to draw another circle, I have to use the repaint() method or it won't automatically repaint the screen after using one of the arrow keys. It would be fine except that it uses up way too much CPU (around 50%) for such a simple program. Any ideas on how to NOT use the repaint() method so that it can do whatever it needs without eating up all my CPU? Here is the source code:
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JComboBox;
import javax.swing.JFrame;
public class Game extends JFrame {
int x, y;
public class AL extends KeyAdapter {
#Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == e.VK_LEFT) {
x--;
}
if (keyCode == e.VK_RIGHT) {
x++;
}
if (keyCode == e.VK_UP) {
y--;
}
if (keyCode == e.VK_DOWN) {
y++;
}
}
#Override
public void keyReleased(KeyEvent e) {
}
}
public static void main(String[] args) {
Game game = new Game();
}
public Game() {
addKeyListener(new AL());
setTitle("Game");
setSize(500, 500);
setResizable(false);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
x = 150;
y = 150;
}
#Override
public void paint(Graphics g) {
g.fillOval(x, y, 15, 15);
repaint();
}
}
You are doing a few things wrong when it comes to painting:
Don't paint on a top level component like JFrame, instead add a JPanel to it and paint on it instead.
Don't override paint, override paintComponent instead.
Don't call repaint inside methods that paint (like paint and paintComponent), it will cause a recursion.
Also, use key bindings instead of key listeners. Here is an example of everything coming together:
class Example extends JPanel {
int x = 0;
int y = 0;
Example() {
getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("RIGHT"), "right");
getActionMap().put("right", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
x++;
repaint();
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
public void paintComponent(Graphics g) {
g.clearRect(0, 0, getWidth(), getHeight());
g.drawRect(x, y, 30, 30);
}
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new Example());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
});
}
}
Don't call repaint(); inside paint(). Repaint schedules a paint(), so no wonder your CPU is having a hard time.
Like Kayaman said you should never call repaint() from within paint().
You can call the Frames repaint() Method in keyPressed() so the Frame will be repainted every time you press a key.
#Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == e.VK_LEFT) {
x--;
}
if (keyCode == e.VK_RIGHT) {
x++;
}
if (keyCode == e.VK_UP) {
y--;
}
if (keyCode == e.VK_DOWN) {
y++;
}
Game.this.repaint();
}
/*...*/
#Override
public void paint(Graphics g) {
g.fillOval(x, y, 15, 15);
}
Call to repaint() will cause RepaintManager to call paint() method. So if you call repaint() inside paint() it will loop infinitely. Instead you can repaint your JFrame once the key-pressed action performed.
#Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == KeyEvent.VK_LEFT) {
x--;
}
if (keyCode == KeyEvent.VK_RIGHT) {
x++;
}
if (keyCode == KeyEvent.VK_UP) {
y--;
}
if (keyCode == KeyEvent.VK_DOWN) {
y++;
}
repaint();
}
Remove repaint() call from paint() method and add it as above.
But if there are different places which you want the JFrame to be repainted and you choose the above method, it will be messy again. So, you can use a Timer to call repaint().
private final javax.swing.Timer timer;
private final int REFRESH_TIME = 100;
public Game() {
addKeyListener(new AL());
setTitle("Game");
setSize(500, 500);
setResizable(false);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
x = 150;
y = 150;
timer = new javax.swing.Timer(REFRESH_TIME, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
repaint();
}
});
timer.start();
}
If you want, you can use another way to call repaint() once in a period. The calling Thread need not to be an EDT.

Java KeyListener for class not extending jpanel or something

I'm trying to make a KeyListener in a new data type called Player which implements KeyListner. How could I make Player its own KeyListener (i.e. this.addKeyListner(this)) without implementing or extending anything further? If this is not posssible, what would I want Player to extend/implement to avoid extraneous methods in the class?
Edit: To clarify, I'm not asking how to implement a KeyListener without the the keyReleased, keyPressed, and keyTyped methods. I'm asking how I can make Player add itself as a KeyListener without it being a JPanel, for example.
If you implement KeyListener (assuming there is no instance of Abstract), then you must implement the 3 methods. They are not extraneous for the interface, as these are the 3 things that can happen to a key, they may not all be relevant to you but it's only a couple of lines of code to implement them.
void keyPressed(KeyEvent e)
Invoked when a key has been pressed.
void keyReleased(KeyEvent e)
Invoked when a key has been released.
void keyTyped(KeyEvent e)
Invoked when a key has been typed.
There's only the 3 and this is the nature of interfaces.
Steps:
Create a class which extends JPanel, say MyJPanel.
The JPanel class should provide methods to modify it's attributes.
Create a separate class which implements KeyListener, say Player.
Add an object of Player to the JPanel class.
Call the JPanel methods from the Player class on key events, and then repaint.
Code:
The Panel class:
public class MyJPanel extends JPanel {
private int x = 0;
private int y = 0;
public MyJPanel() {
addKeyListener(new Player(this));
setFocusable(true);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.GREEN);
g.fillRect(x, y, 100, 100);
}
public static void main(String[] args) {
MyJPanel player = new MyJPanel();
player.setSize(200, 200);
JFrame frame = new JFrame();
frame.add(player);
frame.setLayout(null);
frame.setTitle("Key listener example");
frame.setSize(500, 500);
frame.setVisible(true);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
void incrementX() {
x++;
if (x > 500)
x = 500;
}
void decrementX() {
x--;
if (x < 0)
x = 0;
}
void incrementY() {
y++;
if (y > 500)
y = 500;
}
void decrementY() {
y--;
if (y < 0)
y = 0;
}
}
The Player class which implements KeyListener
public class Player implements KeyListener {
MyJPanel panel;
public Player(MyJPanel myJPanel) {
this.panel = myJPanel;
}
#Override
public void keyPressed(KeyEvent pKeyEvent) {
int key = pKeyEvent.getKeyCode();
if (key == KeyEvent.VK_LEFT) {
panel.decrementX();
} else if (key == KeyEvent.VK_RIGHT) {
panel.incrementX();
} else if (key == KeyEvent.VK_UP) {
panel.decrementY();
} else if (key == KeyEvent.VK_DOWN) {
panel.incrementY();
}
panel.repaint();
}
#Override
public void keyReleased(KeyEvent pKeyEvent) {
}
#Override
public void keyTyped(KeyEvent pKeyEvent) {
}
}

I need a little help implementing player movement on java grid

I need a little help with java, I am new to the language hence I have no idea on how to implement such.
I have already made a basic 15;40 grid JLabel Image, thanks to this site as well, what I need help with is about how to make a player(Supposed to be an Image, also shown on the grid) move around using either WASD(I don't know if Ascii-approach works on java) or Arrow Keys.
Here's my code for the Grid
public class GUI {
static Scanner cns = new Scanner(System.in);
JFrame frame = new JFrame();
ImageIcon ImageIcon = new ImageIcon("Grass.png");
JLabel[][] grid;
public GUI(int width, int length) {
Container pane = frame.getContentPane();
frame.setLayout(new GridLayout(width,length));
grid = new JLabel[width][length];
for(int y = 0; y < length; y++) {
for(int x = 0; x < width; x++) {
grid[x][y] = new JLabel();
grid[x][y].setBorder(BorderFactory.createLineBorder(Color.black));
grid[x][y].setBorder(BorderFactory.createEmptyBorder());
}
}
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
for(int y = 0; y < length; y++) {
for(int x = 0; x < width; x++) {
pane.add(grid[x][y]= new JLabel(new ImageIcon("Grass.png")));
grid[x][y].setBorder(BorderFactory.createLineBorder(Color.black));
grid[x][y].setBorder(BorderFactory.createEmptyBorder());
frame.add(grid[x][y]);
}
}
}
public static void main(String[] args) {
new GUI(15, 40);
}
}
Couple of suggestions here:
1 - Make GUI extend JFrame and implement KeyListener.
You have to override KeyListener methods (keyPressed, keyReleased, and keyTyped) and you should override repaint() from JFrame.
The repaint method should call super.repaint() at the end to update frames.
2 - Have the fields of GUI store data about the things that need to be drawn.
You probably should store the grid, or what's in the grid as fields.
3 - The constructor should initialize, not render.
Rendering should be done in repaint(). The constructor should do something like this:
super();
JPanel frame = new JPanel();
add(frame);
pack();
addKeyListener(this);
repaint();
This answer is kinda unfinished but I'll look more into it and update this. Particularly, the JPanel is an element in the JFrame.
UPDATE: Here is a small working example. Use WASD to move the rectangle around the screen.
This is the JFrame.
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
public class MyJFrame extends JFrame implements KeyListener {
private MyJPanel frame;
public MyJFrame() {
super();
frame = new MyJPanel();
add(frame);
pack();
addKeyListener(this);
repaint();
}
public static void main(String[] args) {
MyJFrame window = new MyJFrame();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
window.setTitle("Test");
}
#Override
public void repaint() {
super.repaint();
}
#Override
public void keyPressed(KeyEvent e) {
frame.keyPressed(e);
repaint();
}
#Override
public void keyTyped(KeyEvent e) { }
#Override
public void keyReleased(KeyEvent e) { }
}
This is the JPanel.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import javax.swing.JPanel;
public class MyJPanel extends JPanel {
private int x = 0;
private int y = 0;
public MyJPanel() {
setPreferredSize(new Dimension(200,200));
}
#Override
public void update(Graphics g) {
paint(g);
}
#Override
public void paint(Graphics g) {
g.setColor(Color.red);
g.drawRect(x,y,20,20);
}
public void keyPressed(KeyEvent e) {
int k = e.getKeyCode();
switch (k) {
case KeyEvent.VK_D:
x++;
break;
case KeyEvent.VK_A:
x--;
break;
case KeyEvent.VK_W:
y--;
break;
case KeyEvent.VK_S:
y++;
break;
}
}
}
Good luck!

Categories