I have a problem with the paddle for moving left and right, here is the code.
the repaint method also doesn't work properly. I have revised the code many times but in no vain.
I don't want to use PaintComponent for now.
I would love to know what is the exact problem in the code.
Appreciate your help.
package com.zharawa;
public class Main {
public static void main(String[] args) {
new GameFrame("Brick Breaker", 800, 700);
}
}
package com.zharawa;
import java.awt.Color;
import javax.swing.JFrame;
public class GameFrame extends JFrame{
private String title;
private int width, height;
GamePanel gamePanel;
public GameFrame(String title, int width, int height) {
this.title = title;
this.width = width;
this.height = height;
gamePanel = new GamePanel();
this.setSize(width, height);
this.setBackground(Color.black);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
this.setResizable(false);
this.setLocationRelativeTo(null);
this.add(gamePanel);
}
}
package com.zharawa;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JPanel;
import javax.swing.Timer;
public class GamePanel extends JPanel implements KeyListener, ActionListener{
private int paddleXdir=350;
private int paddleYdir=600;
private int paddleWidth=150;
private int paddleHeight=10;
public GamePanel() {
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
repaint();
}
public void paint(Graphics g) {
//draw borders
g.setColor(Color.blue);
g.fillRect(0, 0, 785, 5);
g.fillRect(0, 5, 5, 655);
g.fillRect(780, 5, 5, 655);
g.setColor(Color.red);
g.fillRect(5, 655, 775, 5);
//draw ball
g.setColor(Color.green);
g.fillOval(300, 450, 20, 20);
//draw bricks
// g.setColor(Color.blue);
// for(int i=0;i<20;i++) {
// g.fillRect(50, 50, 30, 30);
//}
//draw paddle
g.setColor(Color.green);
g.fillRect(paddleXdir, paddleYdir, paddleWidth, paddleHeight);
g.dispose();
}
#Override
public void actionPerformed(ActionEvent e) {
repaint();
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_RIGHT) {
paddleXdir+=25;
}
if(e.getKeyCode()==KeyEvent.VK_LEFT)
paddleXdir-=25;
}
#Override
public void keyReleased(KeyEvent e) {
}
}
The main problem is that your keyListener isn't attached to the main panel. Your keyboard events aren't being recorded. This answer only responds to the paddle's immobility:
GameFrame class
import java.awt.Color;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.*;
public class GameFrame extends JFrame {
private String title;
private int width, height;
GamePanel gamePanel;
public GameFrame(String title, int width, int height) {
this.title = title;
this.width = width;
this.height = height;
gamePanel = new GamePanel();
this.setSize(width, height);
this.setBackground(Color.black);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
this.setResizable(false);
this.setLocationRelativeTo(null);
this.add(gamePanel);
this.addKeyListener( new CustomActionListener() );
}
class CustomActionListener implements KeyListener {
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_RIGHT) {
gamePanel.moveRight();
}
if(e.getKeyCode()==KeyEvent.VK_LEFT)
gamePanel.moveLeft();
// Required after any change:
repaint();
}
#Override
public void keyReleased(KeyEvent e) {
}
}
}
GamePanel class
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.*;
public class GamePanel extends JPanel {
private int paddleXdir=350;
private int paddleYdir=600;
private int paddleWidth=150;
private int paddleHeight=10;
protected void moveRight() {
paddleXdir+=25;
}
protected void moveLeft() {
paddleXdir-=25;
}
public GamePanel() {
setFocusable(true);
setFocusTraversalKeysEnabled(false);
repaint();
}
public void paint(Graphics g) {
//draw borders
g.setColor(Color.blue);
g.fillRect(0, 0, 785, 5);
g.fillRect(0, 5, 5, 655);
g.fillRect(780, 5, 5, 655);
g.setColor(Color.red);
g.fillRect(5, 655, 775, 5);
//draw ball
g.setColor(Color.green);
g.fillOval(300, 450, 20, 20);
//draw bricks
// g.setColor(Color.blue);
// for(int i=0;i<20;i++) {
// g.fillRect(50, 50, 30, 30);
//}
//draw paddle
g.setColor(Color.green);
g.fillRect(paddleXdir, paddleYdir, paddleWidth, paddleHeight);
}
}
I think you didn't understand camickr's comment. You need to change the name of method paint to paintComponent. You also need to call the superclass method. As well you need to add a call to method repaint() in your keyPressed() method.
I made the necessary changes to your GamePanel class. I also added a main() method just to make the below code an application that you can run. You can safely remove the main() method from the below code.
package com.zharawa;
import java.awt.Color;
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.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
public class GamePanel extends JPanel implements KeyListener, ActionListener{
private int paddleXdir=350;
private int paddleYdir=600;
private int paddleWidth=150;
private int paddleHeight=10;
public GamePanel() {
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
repaint();
}
public void paintComponent(Graphics g) { // CHANGE METHOD NAME (from 'paint')
super.paintComponent(g); // ADDED THIS LINE
//draw borders
g.setColor(Color.blue);
g.fillRect(0, 0, 785, 5);
g.fillRect(0, 5, 5, 655);
g.fillRect(780, 5, 5, 655);
g.setColor(Color.red);
g.fillRect(5, 655, 775, 5);
//draw ball
g.setColor(Color.green);
g.fillOval(300, 450, 20, 20);
//draw bricks
// g.setColor(Color.blue);
// for(int i=0;i<20;i++) {
// g.fillRect(50, 50, 30, 30);
//}
//draw paddle
g.setColor(Color.green);
g.fillRect(paddleXdir, paddleYdir, paddleWidth, paddleHeight);
g.dispose();
}
#Override
public void actionPerformed(ActionEvent e) {
repaint();
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_RIGHT) {
paddleXdir+=25;
}
if(e.getKeyCode()==KeyEvent.VK_LEFT) {
paddleXdir-=25;
}
repaint(); // ADDED THIS LINE
}
#Override
public void keyReleased(KeyEvent e) {
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setSize(800, 700);
frame.add(new GamePanel());
frame.setLocationByPlatform(true);
frame.setVisible(true);
});
}
}
The actionPerformed() method will be required when you add animation, i.e. make the "ball" move across the screen. In order to add animation you will need to use a Swing timer
I changed the paint(Graphics g) method to painting or other name but all the graphics are gone.
The problem is with the paddle, it has a weird behavior when try to move its direction.
Help Please-------------
1- I used super.paint(g);
and the problem of updating the paddle fixed, but why I have to use this.addKeyListener(gamePanel); in the GameFrame class?
If I dont use this.addKeyListener(gamePanel); sometimes the paddle move sometimes doesn't. I mean why is it necessary to use this line of code this.addKeyListener(gamePanel); in the GameFrame class while I have this addKeyListener(this); line in the GameFrame class?
2- what are the differences between public void paint(Graphics g)
super.paint(g);
and
public void paintComponent(Graphics g)
super.paintComponent(g);? Because I get the same result for this specific example of mine.
3- Why the background of the game is not black though I have this line this.setBackground(Color.black); in GameFrame class?
4- Why only If I remove super.paint(g); the background of the game gets its color which is black and then the paddle doesn't get updated properly?
public class Main {
public static void main(String[] args) {
new GameFrame("SnakeGame", 800, 700);
}
}
public class GameFrame extends JFrame{
private String title;
private int width, height;
GamePanel gamePanel;
public GameFrame(String title, int width, int height) {
this.title = title;
this.width = width;
this.height = height;
gamePanel = new GamePanel();
this.setSize(width, height);
this.setTitle("Brick Breaker");
this.setBackground(Color.black);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
this.setResizable(false);
this.setLocationRelativeTo(null);
this.add(gamePanel);
this.addKeyListener(gamePanel);
}
}
public class GamePanel extends JPanel implements KeyListener, ActionListener{
private int paddleXdir=350;
private int paddleYdir=600;
private int paddleWidth=150;
private int paddleHeight=10;
public GamePanel() {
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
public void paint(Graphics g) {
super.paint(g);
//draw borders
g.setColor(Color.blue);
g.fillRect(0, 0, 785, 5);
g.fillRect(0, 5, 5, 655);
g.fillRect(780, 5, 5, 655);
g.setColor(Color.red);
g.fillRect(5, 655, 775, 5);
//draw ball
g.setColor(Color.green);
g.fillOval(300, 450, 20, 20);
//draw bricks
// g.setColor(Color.blue);
// for(int i=0;i<20;i++) {
// g.fillRect(50, 50, 30, 30);
//}
//draw paddle
g.setColor(Color.green);
g.fillRect(paddleXdir, paddleYdir, paddleWidth, paddleHeight);
}
#Override
public void actionPerformed(ActionEvent e) {
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_RIGHT)
paddleXdir+=25;
if(e.getKeyCode()==KeyEvent.VK_LEFT)
paddleXdir-=25;
repaint();
}
#Override
public void keyReleased(KeyEvent e) {
}
}
1- I used super.paint(g);
and the problem of updating the paddle fixed, but why I have to use this.addKeyListener(gamePanel); in the GameFrame class?
If I dont use this.addKeyListener(gamePanel); sometimes the paddle move sometimes doesn't. I mean why is it necessary to use this line of code this.addKeyListener(gamePanel); in the GameFrame class while I have this addKeyListener(this); line in the GameFrame class?
2- what are the differences between public void paint(Graphics g)
super.paint(g);
and
public void paintComponent(Graphics g)
super.paintComponent(g);? Because I get the same result for this specific example of mine.
3- Why the background of the game is not black though I have this line this.setBackground(Color.black); in GameFrame class?
4- Why only If I remove super.paint(g); the background of the game gets its color which is black and then the paddle doesn't get updated properly?
public class Main {
public static void main(String[] args) {
new GameFrame("SnakeGame", 800, 700);
}
}
public class GameFrame extends JFrame{
private String title;
private int width, height;
GamePanel gamePanel;
public GameFrame(String title, int width, int height) {
this.title = title;
this.width = width;
this.height = height;
gamePanel = new GamePanel();
this.setSize(width, height);
this.setTitle("Brick Breaker");
this.setBackground(Color.black);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
this.setResizable(false);
this.setLocationRelativeTo(null);
this.add(gamePanel);
this.addKeyListener(gamePanel);
}
}
public class GamePanel extends JPanel implements KeyListener, ActionListener{
private int paddleXdir=350;
private int paddleYdir=600;
private int paddleWidth=150;
private int paddleHeight=10;
public GamePanel() {
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
public void paint(Graphics g) {
super.paint(g);
//draw borders
g.setColor(Color.blue);
g.fillRect(0, 0, 785, 5);
g.fillRect(0, 5, 5, 655);
g.fillRect(780, 5, 5, 655);
g.setColor(Color.red);
g.fillRect(5, 655, 775, 5);
//draw ball
g.setColor(Color.green);
g.fillOval(300, 450, 20, 20);
//draw bricks
// g.setColor(Color.blue);
// for(int i=0;i<20;i++) {
// g.fillRect(50, 50, 30, 30);
//}
//draw paddle
g.setColor(Color.green);
g.fillRect(paddleXdir, paddleYdir, paddleWidth, paddleHeight);
}
#Override
public void actionPerformed(ActionEvent e) {
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_RIGHT)
paddleXdir+=25;
if(e.getKeyCode()==KeyEvent.VK_LEFT)
paddleXdir-=25;
repaint();
}
#Override
public void keyReleased(KeyEvent e) {
}
}
</code>
I have a JPanel in my java code and I want to set its size, I have used JPanel.setSize(500,500); and JPanel.setSize(new Dimension(500,500)); but both are not working. Please tell how I can set the size of JPanel?
Most Swing layout managers respect a component's preferredSize and not its size. You could call setPreferredSize(new Dimension(500, 500)), but this can be overridden later in your code, and can lead to an inflexible GUI. Better to override the JPanel's getPreferredSize() method and return a calculated Dimension that works best in all situations.
For example:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.*;
public class PrefSizePanel extends JPanel {
private static final int PREF_W = 500;
private static final int PREF_H = PREF_W;
public Dimension getPreferredSize() {
// update as per Marco:
if (super.isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
// just for fun
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(new GradientPaint(0, 0, Color.red, 20, 20, Color.blue, true));
g2.fillOval(0, 0, 2 * getWidth(), 2 * getHeight());
}
private static void createAndShowGUI() {
PrefSizePanel paintEg = new PrefSizePanel();
JFrame frame = new JFrame("PrefSizePanel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(paintEg);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Which displays as
public class Rec extends JFrame {
public Rec (){
JFrame jframe = new JFrame();
jframe.setSize(500, 500);
jframe.setVisible(true);
}
public void render (Graphics g){
g.setColor(Color.red);
g.fillRect(0,0,50,50);
}
public static void main(String[] args) {
Rec frame = new Rec();
frame.render(g);
}
}
Why does this not work? I am aware I may need a paintComponent, if so how would I go about doing this? Any help would be great, Thank You!
The thing is that painting in a JFrame is not what you should be doing. It is better (in this instance) to set the contentpane as a JPanel, and paint inside the JPanel.
Take this short snippet as an example:
import java.awt.*;
import javax.swing.*;
public class Rec {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame rec = new JFrame();
rec.setSize(50, 150);
rec.setContentPane(new JPanel() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.red);
g.fillRect(0, 0, 50, 50);
}
});
rec.setVisible(true);
}
});
}
}
Result:
//May be this is what you are looking for.
public void paintComponent(Graphics g) {
// Create a copy of the passed in Graphics object
Graphics gCopy = g.create();
// Change the properties of gCopy and use it for drawing here
// Dispose the copy of the Graphics object
gCopy.dispose();
}
//or might be this
import javax.swing.JPanel;
import java.awt.Graphics;
import java.awt.Dimension;
import javax.swing.JFrame;
public class DrawingCanvas extends JPanel {
public DrawingCanvas() {
this.setPreferredSize(new Dimension(600, 75));
}
#Override
public void paintComponent(Graphics g) {
// Draw a rectangle
g.fillRect(100, 100, 100, 100);
}
public static void main(String[] args) {
JFrame frame =new JFrame("Drawing");
frame.getContentPane().add(new DrawingCanvas());
frame.pack();
frame.setVisible(true);
}
}
I have a JPanel in my java code and I want to set its size, I have used JPanel.setSize(500,500); and JPanel.setSize(new Dimension(500,500)); but both are not working. Please tell how I can set the size of JPanel?
Most Swing layout managers respect a component's preferredSize and not its size. You could call setPreferredSize(new Dimension(500, 500)), but this can be overridden later in your code, and can lead to an inflexible GUI. Better to override the JPanel's getPreferredSize() method and return a calculated Dimension that works best in all situations.
For example:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.*;
public class PrefSizePanel extends JPanel {
private static final int PREF_W = 500;
private static final int PREF_H = PREF_W;
public Dimension getPreferredSize() {
// update as per Marco:
if (super.isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
// just for fun
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(new GradientPaint(0, 0, Color.red, 20, 20, Color.blue, true));
g2.fillOval(0, 0, 2 * getWidth(), 2 * getHeight());
}
private static void createAndShowGUI() {
PrefSizePanel paintEg = new PrefSizePanel();
JFrame frame = new JFrame("PrefSizePanel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(paintEg);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Which displays as
I want to set up a mathematical (where y grows up not down) coordinate space from (-1, -1) to (+1, +1) and have it fit in the window regardless of the window size.
I am using an anonymous JComponent subclass in Java SE 7 and casting the incoming Graphics in paintComponent to Graphics2D and then drawing on the Graphics2D
But the Graphics2D is set to a computer coordinate space that changes with the size of the window. How to get it to rescale according to window size and have Y go upwards? The following program should show a dark square in upper right quadrant.
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class G {
public static void main (String [] args) {
JFrame frame = new JFrame(G.class.getCanonicalName());
frame.setUndecorated(true);
JComponent component = new JComponent() {
private static final long serialVersionUID = 1L;
#Override
protected void paintComponent (Graphics g) {
super.paintComponent(g);
paint2D((Graphics2D)g);
}
protected void paint2D (Graphics2D g2) {
g2.draw(new Rectangle2D.Double(0.1, 0.1, 0.9, 0.9));
}
};
frame.add(component);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.setVisible(true);
}
}
Setup the coordinate system how you want, using transform() and translate(). So:
you want the origin to be at (0, height); bottom left.
then you want to flip the Y axis.
Example code:
AffineTransform tform = AffineTransform.getTranslateInstance( 0, height);
tform.scale( 1, -1);
g2.setTransform( tform);
[My edited version]:
public static void main (String [] args) {
JFrame frame = new JFrame( G2dTransform_Question.class.getCanonicalName());
JComponent component = new JComponent() {
private static final long serialVersionUID = 1L;
#Override
protected void paintComponent (Graphics g) {
super.paintComponent(g);
paint2D((Graphics2D)g);
}
protected void paint2D (Graphics2D g2) {
AffineTransform tform = AffineTransform.getTranslateInstance( 0, getHeight());
tform.scale( getWidth(), -getHeight()); // NOTE -- to make 1.0 'full width'.
g2.setTransform( tform);
g2.setColor( Color.BLUE); // NOTE -- so we can *see* something.
g2.fill( new Rectangle2D.Double(0.1, 0.1, 0.8, 0.8)); // NOTE -- 'fill' works better than 'draw'.
}
};
frame.setLayout( new BorderLayout()); // NOTE -- make the component size to frame.
frame.add( component, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.setVisible(true);
}
[Hovercraft's version]: Thanks Hover!
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class G {
public static final int PREF_W = 400;
public static final int PREF_H = PREF_W;
public static void main (String [] args) {
JFrame frame = new JFrame(G.class.getCanonicalName());
frame.setUndecorated(true);
JComponent component = new JComponent() {
private static final long serialVersionUID = 1L;
#Override
protected void paintComponent (Graphics g) {
super.paintComponent(g);
AffineTransform tform = AffineTransform.getTranslateInstance( 0, getHeight());
tform.scale( 1, -1);
Graphics2D g2 = (Graphics2D) g.create();
g2.setTransform( tform);
paint2D(g2);
g2.dispose();
}
protected void paint2D (Graphics2D g2) {
g2.draw(new Rectangle2D.Double(10, 10, 20, 30));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
};
frame.add(component);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}