Hello I am currently making a small game in java, and I am running into problems trying to making the gamepanel. I am using a JPanel as the basis and JPanel to the top to put in a HUD, and a gamepanel for the playable protion of the game. I can add the two panels the HUD and gamepanel fine. However the objects which are JComponents will not show up at all. I know they are created I'm not sure how to make them visible though.
Here are my classes:
This is my window class that holds the panels:
public class Window extends JFrame {
public static final int ScreenWidth = 1000;
public static final int ScreenHeight = 700;
public static JFrame frame;
private StatesHandler statesHandler;
public Window(JFrame frame) throws IOException {
this.frame = frame;
this.statesHandler = new StatesHandler();
displaywindow();
}
public void paint(Graphics g) {
super.paint(g);
}
public void displaywindow() {
this.frame.setLayout(new FlowLayout());
this.frame.setPreferredSize(new Dimension(ScreenWidth,ScreenHeight));
this.frame.setMaximumSize(new Dimension(ScreenWidth,ScreenHeight));
this.frame.setMinimumSize(new Dimension(ScreenWidth,ScreenHeight));
this.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.frame.setResizable(false);
this.frame.setBackground(Color.pink);
this.frame.setLocationRelativeTo(null);
this.frame.pack();
this.frame.setVisible(true);
}
public JFrame getFrame() {
return this.frame;
}
This is this the level class:
it holds the hud and the gamepanel
private Window win;
Level(Window win) {
this.setPreferredSize(new Dimension(gw,gh));
this.win = win;
this.setFocusable(true);
this.requestFocus();
Hud hud = new Hud();
getwinframe().getContentPane().add(hud);
getwinframe().getContentPane().validate();
gamepanel gmp = new gamepanel();
getwinframe().getContentPane().add(gmp);
getwinframe().getContentPane().revalidate();
Ball ball = new Ball(600, 200, 3, 3);
System.out.println(this);
gmp.add(ball);
gmp.revalidate();
}
Here is the Ball which I am trying to add to gamepanel
public Ball(int xpos, int ypos,int vx, int vy) {
this.xpos =xpos;
this.ypos = ypos;
this.vx = vx;
this.vy = vy;
this.collsionbox = new Rectangle(xpos, ypos, bwidth, bheight);
}
This is the gamepanel which I'm trying to add the ball to
public gamepanel(){
this.setPreferredSize(new Dimension(Window.ScreenWidth, Window.ScreenHeight -Window.ScreenHeight/6));
this.setLayout(new FlowLayout());
System.out.println(Window.ScreenWidth +" " + Window.ScreenHeight/6);
this.setBackground(Color.pink);
Ball ball2 = new Ball(500, 100, 3, 3);
System.out.println(ball2);
add(ball2);
validate();
}
Related
I am trying to write simple code in java for a moving ball program. im new to java, i mean I know the basics one so here it is my code, in case you can help me.I cant move the ball object. I created the class frame which have the gui component and also the ball class with the features of he ball
public class Frame extends JFrame{
private static final int width= 500;
private static final int height=500;
private static final Color cbw= Color.BLACK;
private Ball ball; // the moving object
private DrawCanvas canvas; // the custom drawing canvas
private JPanel btnpanel; // the panel of the buttons
private JPanel mainpanel; // the mainpanel
private JButton button_ML; // move_Left button
private JButton button_MR;// move_Right button
public Frame (){
setProperties();
init();
setUI();
}
private void setProperties() {
setSize(width, height);
setTitle("MOVE THE BALL");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
private void init(){
btnpanel = new JPanel(new FlowLayout());
mainpanel= new JPanel(new BorderLayout());
button_ML = new JButton("Move left");
button_MR = new JButton("Move right");
//creating the ball with its features
ball= new Ball (30,30,width/2-2,height/2-10,Color.red);
canvas = new DrawCanvas();
// it makes possible the ball to be seen though we have a main panel.
canvas.setPreferredSize(new Dimension(width,height));
button_ML.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
move_Left();
}
});
button_MR.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
move_Right();
}
});
}
private void setUI(){
mainpanel.add(btnpanel, BorderLayout.SOUTH);// adds the button panels to the main panel
btnpanel.add(button_ML);// adds the button to the panel of buttons
btnpanel.add(button_MR);
mainpanel.add(canvas, BorderLayout.CENTER); // adds the canvas to mainpanel
add(mainpanel); // adds the panel in the frame
}
class DrawCanvas extends JPanel {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
setBackground(cbw); // puts color to the background
ball.paint(g); // the ball paints itself
}
}
private void move_Left(){
int savedX = ball.x;
ball.x -=10;
canvas.repaint(savedX, ball.y, ball.WIDTH, ball.HEIGHT);
canvas.repaint(ball.x,ball.y,ball.WIDTH,ball.HEIGHT);
}
private void move_Right(){
int savedX = ball.x;
ball.x += 10;
canvas.repaint(savedX, ball.y, ball.WIDTH, ball.HEIGHT);
canvas.repaint(ball.x,ball.y,ball.WIDTH,ball.HEIGHT);
}
}
// the ball class
public class Ball extends JFrame {
//variables for the construction of the circle
int x, y; // actual position of the ball
int WIDTH, HEIGHT;// parameters for the size of the rectangle where the circle is posited.
Color color = Color.RED;// the color of the ball
// the constructor of the class
public Ball(int x, int y, int WIDTH, int HEIGHT,Color color) {
this.x = x;//
this.y = y;
this.WIDTH = WIDTH;
this.HEIGHT = HEIGHT;
this.color=color;
}
// method for the color and drawing the ball
public void paint(Graphics g) {
g.setColor(Color.red);
g.fillOval(80,70, 350,350);
}
}
Start by using the values of Ball in it paint methods instead of :
// method for the color and drawing the ball
public void paint(Graphics g) {
g.setColor(Color.red);
g.fillOval(80,70, 350,350);
}
It should look like
// method for the color and drawing the ball
public void paint(Graphics g) {
g.setColor(Color.red);
g.fillOval(x,y, WIDTH, HEIGHT);
}
PaintComponent doest paint figures. Just nothing is happening, clean Jframe appear.
I think something is wrong with list or with the way i called method
List is in class with Paint Component
public class Paint extends JPanel implements ActionListener {
List<Figures> figuresList = new ArrayList<Figures>();
Timer t = new Timer(5, this);
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (Figures figure : figuresList) {
figure.drawItself(g, figure.getLocationX(), figure.getLocationY());
}
t.start();
}
#Override
public void actionPerformed(ActionEvent e) {
{
for (Figures figure : figuresList) {
if (figure.getLocationX() < 0 || figure.getLocationX() > 540) {
figure.setVelocityX(-figure.getVelocityX());
}
if (figure.getLocationY() < 0 || figure.getLocationX() > 220) {
figure.setVelocityY(-figure.getVelocityY());
}
figure.setLocationX(figure.getLocationX()
+ figure.getVelocityX());
figure.setLocationY(figure.getLocationY()
+ figure.getVelocityY());
}
}
repaint();
}
And drawitself:
public class Circle implements Figures {
public int locationX = 12;
public int locationY = 12;
public int velocityX =1;
public int velocityY =1;
public void drawItself(Graphics g, int locationX, int locationY){
this.locationX = locationX;
this.locationY = locationY;
g.drawOval(locationX, locationY, 40, 40);
g.fillOval(locationX, locationY, 40, 40);
}
Main:
public static void main(String[] args) {
Circle c = new Circle();
Quadrat q = new Quadrat();
Paint p = new Paint();
p.figuresList.add(c);
p.figuresList.add(q);
GUI.Configuration();
}
GUI
public class GUI {
public static void Configuration(){
JFrame frame = new JFrame("Figures Animation");
frame.setSize(600,300);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new Paint();
frame.getContentPane().add(BorderLayout.CENTER, panel);
}
You create and add a Paint instance here:
public class GUI {
public static void Configuration(){
JFrame frame = new JFrame("Figures Animation");
frame.setSize(600,300);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new Paint(); // *** new Paint is here, but nothing is added
frame.getContentPane().add(BorderLayout.CENTER, panel);
}
But nothing of use has been added to it. All the important stuff is added to a completely different Paint JPanel, one that is never displayed:
public static void main(String[] args) {
Circle c = new Circle();
Quadrat q = new Quadrat();
Paint p = new Paint(); // **** ANOTHER new Paint is here, and it gets goodies
p.figuresList.add(c);
p.figuresList.add(q);
// but is never added to a JFrame and is never displayed.
GUI.Configuration();
}
Don't do this. Create one Paint JPanel, one only, add the important components to it, and then only add that one to the JFrame. Most important, don't just type in code, think and plan your program before committing it to code, and you won't see errors like this.
Also, and again, do not start a Timer from within paintComponent and don't create Circle there. You can draw your Circle instance in paintComponent, but create it and start your Timer within the Paint constructor.
I am trying to draw a circle in the center of a window, and I can't seem to get it right, should be really easy! My understanding is that if you set a JPanel as the content pane of a JFrame, the default layout is a flowLayout and that drawing should start from the top left of the screen as 0,0. To try and figure out what's going on I drew a blue background filling the JPanel, but it seems to have a margin like so:
When the window gets smaller than the blue rectangle, the drawing starts to get clipped from the opposite side:
What's going on! Here is my code:
import javax.swing.*;
import java.awt.*;
public class Test extends JFrame {
public static void main(String args[])
{
Test test = new Test();
test.Start();
}
public void Start()
{
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(500, 500);
CirclePanel circlePanel = new CirclePanel();
this.setContentPane(circlePanel);
this.setVisible(true);
}
public class CirclePanel extends JPanel
{
private int radius = 200;
public void paintComponent(Graphics g) {
g.setColor(Color.blue);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
g.setColor(Color.red);
int diameter = radius * 2;
g.fillOval(getX(), getY(), diameter, diameter);
}
public int getX()
{
return (this.getWidth()/2) - radius;
}
public int getY()
{
return (this.getHeight()/2) - radius;
}
}
}
One big issue, you're unknowingly overriding two critical methods used by the layout managers to position components, the getX() and getY() methods, and thereby you're messing with the JPanel's placement.
So first and foremost, rename these methods so you don't accidentally move the JPanel.
Also, don't forget to call the super's paintComponent method, and avoid calling setSize(). Instead override getPreferredSize on your JPanel, and pack your JFrame.
e.g.,
public int getMyX() {
return myX;
}
public int getMyY() {
return myY;
}
For example
import javax.swing.*;
import java.awt.*;
public class Test extends JFrame {
public static void main(String args[]) {
//!!
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Test test = new Test();
test.Start();
}
});
}
public void Start() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// this.setSize(500, 500);
CirclePanel circlePanel = new CirclePanel();
setContentPane(circlePanel);
pack();
setVisible(true);
}
public class CirclePanel extends JPanel {
private static final int PREF_W = 500;
private static final int PREF_H = PREF_W;
private int radius = 200;
public void paintComponent(Graphics g) {
super.paintComponent(g); //!!
g.setColor(Color.blue);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
g.setColor(Color.red);
int diameter = radius * 2;
g.fillOval(getMyX(), getMyY(), diameter, diameter);
}
//!!
public int getMyX() {
return (this.getWidth() / 2) - radius;
}
//!!
public int getMyY() {
return (this.getHeight() / 2) - radius;
}
//!!
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
}
}
The problem is that you're overriding getX() and getY(). Rename those to something else, and your code will work as expected. Also, it's a good idea to turn on compiler warnings for missing #Override annotations, and heed those warnings. (That would have notified the methods override superclass methods).
Try using this.add(circlePanel) instead if this.setContentPane(circlePanel) and set the size of the JPanel to be the same size as the JFrame
I created a program that is supposed to draw a circle with each click(Random size and random color), and each circle is going to be an object. I don't know what is going on but my code doesn't work and I am pretty sure I am almost there.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
public class Circle
{
private JFrame frame;
CircleObj circleObj;
Random rand;
int rColor;
int gColor;
int bColor;
int radius;
public static void main (String [] arg)
{
frame = new JFrame("Circles");
frame.setBounds(200, 100, 600, 480);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
JPanel top = new JPanel();
rand = new Random();
top.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
int xstart = e.getX();
int ystart = e.getY();
rColor = rand.nextInt(256);
gColor = rand.nextInt(256);
bColor = rand.nextInt(256);
radius = rand.nextInt(20);
circleObj = new CircleObj(xstart, ystart, rColor, gColor, bColor, radius);
repaint();
}
});
frame.add(top, BorderLayout.CENTER);
frame.setVisible(true);
}
}
and here is my CircleObj class
import javax.swing.*;
import java.awt.*;
public class CircleObj extends JPanel
{
private int xVal;
private int yVal;
private int red;
private int green;
private int blue;
private int circleRadius;
public CircleObj (int x, int y, int r, int g, int b, int rad)
{
xVal = x;
yVal = y;
red = r;
green= g;
blue = b;
circleRadius = rad;
}
public void paintComponent (Graphics g) {
super.paintComponent(g);
g.setColor(new Color(red, green, blue));
g.fillOval(xVal,yVal,circleRadius,circleRadius);
}
}
You add a MouseListener to the top JPanel, but when do you add the top JPanel to the top-level window, the GUI? --- In the MouseListener! So this will never work since the top JPanel is not part of the GUI initially, and only gets added when a MouseListener that is added to it is triggered. The MouseListener only works on components that are visible and on the GUI.
Next you create a CircleObj object, but never draw with it in any JComponent's or JPanel's paiintComponent method.
I am pretty sure I am almost there.
So no, not quite. You will want to re-start and:
Create a JPanel that has a decent paintComopnent method override,
Add this JPanel to the JFrame to the GUI from the beginning.
Add an ArrayList<CircleObj> to this drawing JPanel
Change your CircleObj class so that it doesn't extend JPanel, but does have a public void draw(Grpahics g) method that will draw it.
Add a MouseListener to the JPanel that controls this drawing. In your MouseListener, add a new CircleObj to the ArrayList and call repaint() to get the drawing JPanel to draw.
In the JPanel's paintComponent override, iterate through the ArrayList<CircleObj> calling each object's draw(g) method.
Read the Swing graphics tutorials.
Here is a second approach... How would I be able to tweak it store each circle in an object (Arraylist of objects) ?
public class Circle {
public static void main (String[] arg) {
JFrame frame = new JFrame("Circles");
CircleObj canvas = new CircleObj();
frame.add(canvas, BorderLayout.CENTER);
frame.setBounds(250, 98, 600, 480);
//frame.setLayout(new BorderLayout());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
} // end main
} //end Circle
CircleObj Class
public class CircleObj extends JPanel {
private int rColor;
private int gColor;
private int bColor;
private int radius;
private Random rand = new Random();
private int xStart;
private int yStart;
public CircleObj () {
addMouseListener(new MouseAdapter() {
public void mouseClicked (MouseEvent e) {
xStart = e.getX();
yStart = e.getY();
rColor = rand.nextInt(256);
gColor = rand.nextInt(256);
bColor = rand.nextInt(256);
radius = rand.nextInt(20);
System.out.println("xstart : " + xStart + ", ystart : " + yStart + ", rColor : " + rColor + ", gColor = " +
gColor + ", bColor: " + bColor + ", radius: " + radius);
repaint();
}
}); // end addMouseListener
}
public void paintComponent (Graphics g) {
super.paintComponent(g);
g.setColor(new Color(rColor, gColor, bColor));
g.fillOval(xStart, yStart, radius, radius);
}
}
I am trying to display a JComponent inside a JPanel.
I am using null layout because location of the components can be changed during runtime and I have to control them.
But the following code does not work. The JComponent only becomes visible on display if I explicity call the "paintComponent" method, which I think is not good practice.
My JComponent Class
public class MyIcon extends JComponent
{
private double xPos;
private double yPos;
private double radius = 30;
public MyIcon(double xPos, double yPos)
{
this.xPos = xPos;
this.yPos = yPos;
this.setBounds((int)xPos, (int)yPos, (int)radius, (int)radius);
this.setPreferredSize(new Dimension((int)radius, (int)radius ) );
}
public Dimension getPreferredSize()
{
return ( new Dimension( (int)radius, (int)radius ) );
}
public Dimension getMinimumSize()
{
return new Dimension((int)radius, (int)radius);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.BLACK);
g2d.drawOval( (int)xPos, (int)yPos, (int)radius, (int)radius);
g2d.fillOval((int)xPos, (int)yPos, (int)radius, (int)radius);
System.out.println("Icon.paintComponnet() called");
}
}
My Panel Class
public class MyPanel extends JPanel
{
private MyIcon myIcon;
private Graphics2D graphics;
private int width = 700;
private int height = 500;
public MyPanel()
{
myIcon = new MyIcon(20,30);
init();
}
private void init()
{
setLayout(null);
setBackground(Color.WHITE);
setPreferredSize( new Dimension(width, height) );
setBorder(BorderFactory.createLineBorder(Color.BLACK));
add( myIcon );
myIcon.repaint();
}
public void paintComponent(Graphics g)
{
graphics = (Graphics2D) g;
super.paintComponent(g);
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
System.out.println("MyPanel.paintComponnet() called");
// why my Icon only gets painted if I explicitly call for it ?
//myIcon.paintComponent(g);
}
}
My Frame Class
public class Editor {
public static void main(String[] args)
{
Editor editor = new Editor();
}
private MyPanel myPanel;
private JFrame frame;
private JToolBar toolBar;
public Editor()
{
myPanel = new MyPanel();
init();
}
private void init()
{
frame = new JFrame("Editor");
Container content = frame.getContentPane();
frame.setSize(800, 600);
frame.setLayout(new BorderLayout(15,15));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
content.add(myPanel,BorderLayout.WEST);
frame.pack();
frame.setVisible(true);
}
}
I'd be use paintIcon() for Class that returns Icon Object
public void paintIcon(Component c, Graphics g, int x, int y) {
for example
Maybe a good approach would be that the Icon class would not extend JComponent but would be just a simple object.
Then, you rename the current Icon.paintComponent you have to something like drawIcon and call the drawIcon method from the MyPanel.paintComponent directly and passing the reference to the Graphics object.
This way you don't have to wonder about using a null layout and you can control the place to display the icon to by just using the Graphics(2d) APIs.