Am new to Java GUI Games, therefore, question might be trivial. Am trying to make a foosball game of sort.
I have been trying to add Ball JComp on top of my FoosballTable Jcomp.
There are two table settings.
What it does is, adds Ball Component to bottom of the Table.
I change the table setting and ball is visible. Otherwise not.
How do I add ball to the top? I have been trying to search online to no avail.
Thank you.
Edit 1
The ball class has overridden paintComponent method. and Frame class has various panels. one panel is the Start button i.e supposed to display the ball
....
jp7.add(Start);
final Ball b = new Ball();
Start.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
JPanel contentball = (JPanel) getContentPane();
contentball.add(b);
contentball.revalidate();
contentball.repaint();
}
});
playersOnString.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent e) {
JPanel contentgr = (JPanel) getContentPane();
if(e.getItem() == "[1] [2] [4] [4]"){
System.out.println("First choice");
remove(ground2);
contentgr.add(ground1);
}
else if(e.getItem()== "[1] [2] [5] [3]"){
System.out.println("Second choice");
remove(ground1);
contentgr.add(ground2);
}
contentgr.repaint();
setVisible(true);
}
});
public class Ball extends JComponent{
/**
*
*/
private static final long serialVersionUID = 1L;
private static Ball ball;
int xAxisSpeed , yAxisSpeed;
Team lastContactTeam;
private int size = 15;
public Dimension getPreferredSize()
{
return (new Dimension(100, 500));
}
public static Ball getInstance(){
Random r = new Random();
if(ball == null){
ball = new Ball();
ball.xAxisSpeed = r.nextInt(10)+1;
ball.yAxisSpeed = r.nextInt(10)+0;
}
return ball;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillOval(190, 355, size, size);
setVisible(true);
}
}
Edit 2
I wish to add ball to the top of the Table that already exists. (a rectangle drawn with PaintComponent method on a panel)
Related
I am working on a simple object drawing program using Swing in Java.
My program simply should draw shapes according to buttons when clicked, and move any shapes with the mouse. I have four buttons which draw rectangle, circle and square on screen. So far I did managed to draw to shapes when you click on buttons. but i want to move the shapes on screen which it did not work out.
The problem is this: When I click on circle shape to drag it around with mouse, it clears all the screen and noting is on the screen.
And, is there a way to clean all the screen when I click on clear button?
Thank you?
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class PaintProject extends JComponent implements ActionListener,
MouseMotionListener {
private int CircleX=0;
private int CircleY=0;
private int RectX=100;
private int RectY=100;
private int SquareX=300;
private int SquareY=200;
public static void main(String[] args) {
JFrame frame = new JFrame("NEW PAINT PROGRAME!");
JButton CircleButton = new JButton("Circle");
CircleButton.setActionCommand("Circle");
JButton RectangleButton = new JButton("Rectangle");
RectangleButton.setActionCommand("Rectangle");
JButton SquareButton = new JButton("Square");
SquareButton.setActionCommand("Square");
PaintProject paint = new PaintProject();
CircleButton.addActionListener(paint);
RectangleButton.addActionListener(paint);
SquareButton.addActionListener(paint);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setLayout(new FlowLayout());
frame.add(paint);
frame.add(CircleButton);
frame.add(RectangleButton);
frame.add(SquareButton);
frame.addMouseMotionListener(paint);
frame.pack();
frame.setVisible(true);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(500, 500);
}
private void drawCircle() {
Graphics g = this.getGraphics();
g.setColor(Color.red);
g.fillOval(CircleX, CircleY, 100, 100);
}
private void drawRectangle() {
Graphics g = this.getGraphics();
g.setColor(Color.green);
g.fillRect(RectX, RectY, 100, 300);
}
private void drawSquare() {
Graphics g = this.getGraphics();
g.setColor(Color.blue);
g.fillRect(SquareX, SquareY, 100, 100);
}
#Override
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
if (command.equals("Circle")) {
drawCircle();
}
else if (command.equals("Rectangle")) {
drawRectangle();
}
else if (command.equals("Square")) {
drawSquare();
}
}
#Override
public void mouseDragged(MouseEvent e) {
CircleX=e.getX();
CircleY=e.getY();
repaint();
}
}
As noted here and here, getGraphics() is not how to perform custom painting in Swing. Instead, override paintComponent() to render the desired content. It looks like you want to drag shapes using the mouse. A basic approach to moving a selected object is shown here; substitute your fillXxx() invocation for the drawString() shown there. For multiple shapes, use a List<Shape>; the clear command then becomes simply List::clear. A complete example is cited here; it features moveable, selectable, resizable, colored nodes connected by edges.
I'm building a program that draws random (User input) rectangles on a JPanel.
Problem 1:
Whenever I type a number in my JTextfield,I need to click twice on
the JBUtton for Rectangles to show up.
Problem 2:
When i type a new number in the JTextField the number of that don't
show the rectangle but it shows the rectangles I typed in previous.
CODE:
private void init() {
final int FRAME_WIDHT = 800;
final int FRAME_HEIGHT = 1000;
int input = 3;
JFrame frame = new JFrame();
frame.setSize(FRAME_WIDHT, FRAME_HEIGHT);
frame.setTitle("Frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
west = new JPanel();
west.setSize(500, 500);
west.setBorder(BorderFactory.createLineBorder(Color.black));
east = new JPanel();
east.setSize(300, 1000);
button = new JButton("Add squares");
field = new JTextField(10);
button.setSize(100, 50);
east.add(button);
east.add(field);
east.setBorder(BorderFactory.createLineBorder(Color.black));
button.addActionListener(new java.awt.event.ActionListener() {
#Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
JButton1ActionPerformed(evt);
}
public void JButton1ActionPerformed(ActionEvent evt) {
int aantalRect = Integer.parseInt(field.getText());
MyDrawing draw = new MyDrawing(aantalRect);
west.add(draw);
draw.revalidate();
draw.repaint();
}
});
frame.add(west, BorderLayout.CENTER);
frame.add(east, BorderLayout.EAST);
frame.setResizable(true);
frame.setVisible(true);
}
public static void main(String[] a) {
P1027 form = new P1027();
}
}
class MyDrawing extends JPanel {
int input = 0;
public MyDrawing(int i) {
this.input = i;
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Random r = new Random();
setPreferredSize(new Dimension(500, 1000));
for (int i = 0; i < input; i++) {
int x = r.nextInt(460);
int y = r.nextInt(960);
g.drawRect(x, y, 40, 40);
}
}
Can any one tell me how to fix that?
Problem 1: You're not be seeing the squares being drawn on your MyDrawing JPanel the first time because you are calling the setPreferredSize(...) method, when you really should be overriding the getPreferredSize() method as explained by this answer. It is also possible that they are being drawn off-screen. You set the preferred height of MyDrawing to 1000, which doesn't fit on my laptop's screen (The green line is the border of a MyDrawing).
To fix Problem 1, override the method and lower the preferred height if necessary:
class MyDrawing extends JPanel {
... //Constructor
#Override
public Dimension getPreferredSize() {
return new Dimension(500, 500); //Changed from 1000 to 500
}
... //paintComponent(...)
//If you change 1000 to 500, don't forget to change 960 to 460 too
}
Problem 2: You're seeing the amount of rectangles you typed into the JTextField previously because:
You are forgetting to remove the previously added MyDrawing from west before adding the new one.
You are calling revalidate() and repaint() on draw when you should be calling it on its parent component, west.
To fix problem 2, remove the old MyDrawing from west, add the new one, then call revalidate() and repaint():
...
public void JButton1ActionPerformed(ActionEvent evt) {
west.removeAll(); //If the old MyDrawing is the only thing
//that has been added to west. Otherwise use
//remove(int index) or remove(Component comp)
west.add(draw);
west.revalidate();
west.repaint();
}
...
Other things:
You switched the T and H around in FRAME_WIDTH.
You could put the code in JButton1ActionPerformed(...) into the actual actionPerformed method.
Your JFrame looks exactly the same with and without the calls to setSize(...) on west, east, and button and that answer I mentioned earlier suggests not using those methods, so consider removing them.
I'm making a GUI application which finds and draws convex hull for a set of points.
Here's the frame:
public class Frame extends JFrame{
Panel panel = new Panel();
JButton drawHull = new JButton("Draw Convex Hull");
Frame(String title) {
super(title);
// setLayout
setLayout(new BorderLayout());
// add components to the frame
add(panel, BorderLayout.CENTER);
add(drawHull, BorderLayout.SOUTH);
// add actionListener for drawHull button
drawHull.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
panel.drawConvexHull();
}
}
);
}
}
The frame contains a button (at the bottom of the frame) and a Panel object.
Here's the Panel class:
public class Panel extends JPanel{
ArrayList<Point> points = new ArrayList<Point>();
public Panel() {
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
points.add(new Point(e.getX(), e.getY()));
repaint();
}
});
}
#Override
protected void paintComponent(Graphics g) {
if(!points.isEmpty()) {
Point p = points.get(points.size()-1);
g.fillOval(p.x-2, p.y-2, 4, 4);
}
}
public void drawConvexHull() {
// code for finding convex hull
}
}
I have added a mouseListener to the Panel class so that when the user clicks anywhere on the panel, a point is drawn.
When I run the code, everything looks fine. Here's a sample run.
Now here's the problem:
As soon as I click the panel, this happens
A button appears on the top of the frame. Why is this happening?
One more thing. When I click this button on the top, a point is drawn. Here, have a look:
Without calling super.paintComponent(g) in paintComponent the background is not repainted leading to unpredictable results on the panel component.
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Point point: points) {
g.fillOval(point.x - 2, point.y - 2, 4, 4);
}
}
I'm learning some swing and awt programming in Java so I decided to make Pong. The Main class is the parent JFrame. It instantiates a Ball and a Paddle and adds them (they are JPanels). However, only the last one added is displayed. How do I fix this?
Code:
public class Main extends JFrame {
public Main() {
super("Pong");
add(new Ball());
add(new Paddle());
setSize(500, 500);
setBackground(Color.orange);
setLocationRelativeTo(null);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new Main().setVisible(true);
}
}
The Ball class:
public class Ball extends JPanel implements ActionListener {
Timer timer;
private Vec2d position;
private Vec2d velocity;
private Dimension ballSize;
public Ball() {
super();
position = new Vec2d(50, 50);
velocity = new Vec2d(2, 3);
timer = new Timer(25, this);
ballSize = new Dimension(40, 40);
timer.start();
}
#Override
public void actionPerformed(ActionEvent ae) {
//Perform game frame logic
bounceBall();
repaint();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.fillArc((int)position.x, (int)position.y, ballSize.width,
ballSize.height, 0, 360);
position.add(velocity);
}
private void bounceBall() {
if(position.x < 0 || position.x > getWidth() - ballSize.width) {
velocity.x *= -1;
}
if (position.y < 0|| position.y > getHeight() - ballSize.height) {
velocity.y *= -1;
}
}
}
And finally, the Paddle class:
public class Paddle extends JPanel implements ActionListener {
private Vec2d position;
private double yVelocity;
private Rectangle rect;
private Timer timer;
public Paddle() {
super();
position = new Vec2d(30, 250);
yVelocity = 0;
timer = new Timer(25, this);
timer.start();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.fillRect((int) position.x, (int) position.y, 20, 40);
}
#Override
public void actionPerformed(ActionEvent ae) {
repaint();
}
}
Note that Vec2d is simply a small two dimensional Vector class I threw together. Also, the Pong logic (collision between Paddle and ball, scoring, etc) is not implemented. I just want to get it to draw correctly
Thanks in advance for the help!
The first thing to do is to add the JPanels to the content pane of your window, not to the window itself. I'm surprised you didn't get a runtime warning about that.
Also, it looks like you are planning to have each of your panels fill the screen, but paint only a small section of it. If that is really the way you want to do it, then you need to do setOpaque(false) on them so the panels under them can show through. But probably a better solution would be to have a single JPanel that is the drawing surface, and have its paintComponent() pass off the Graphics to each of the game objects to let them draw themselves.
add(new Ball());
add(new Paddle());
By default, the layout manager of a JFrame is a BorderLayout. And if you don't specify where you want to add a component (BorderLayout.WEST, or EAST, etc.), the it's added at the center. So you add two components at the same place: in the center. So, only one of them is displayed.
You are adding the Ball and Paddle to the same BorderLayout.CENTER position so only the last one added, (i.e. the Paddle) is displayed. You could use a GridLayout here to display:
setLayout(new GridLayout(1, 2));
add(new Paddle());
add(new Ball());
in the Paddle class, you never add the velocity to position with position.add(velocity) like you do in your ball class..
I'm creating a small game, you click buttons (up, down, left and right) to control a cat (represented by a rectangle) to chase a mouse (represented by another rectangle). Lame I know... anyway I'm using the mvc design pattern and I am having problems calling the repaint method from button listeners in the controller on the panel where the two rectangles are to be 'painted'. They paint successfully the first time but not any further time.
I've implemented the the paintComponent() method in two ways but both didn't work
Create a separate class that extends JPanel and does the paintComponent business, creating a new object of that class in the view and using it to paint the rectangles.
Creating a JPanel and writing the paintComponent stuff in the parenthesis of the new JPanel object.
and I've implemented the code to in the controller to repaint in two ways and both didn't work
Call a method from the view that returns the jpanel that uses the paintComponent method and calling repaint on it.
Creating a jpanel in the controller and assigning the panel from the view to it then calling repaint on that.
The code for the view and controller (which is long, sorry!) is below, it also includes the commented out stuff I couldn't get to work from the two methods to approaching the problem mentioned before...
View
/*
* gameView.java
*/
package game;
import java.awt.;
import java.awt.event.;
import javax.swing.*;
public class gameView extends JFrame{
//components
private JButton up = new JButton("Up");
private JButton down = new JButton("Down");
private JButton left = new JButton("Left");
private JButton right = new JButton("Right");
//panels
private JPanel content = new JPanel();
//boardPanel leftPanel = new boardPanel();
private Stroke drawingStroke = new BasicStroke(1);
private JPanel leftPanel = new JPanel(){
#Override
protected void paintComponent(Graphics g) {
super.paintComponents(g);
myPaint(g);
}
};
private JPanel rightPanel = new JPanel();
//model
private gameModel model;
//mouse and cat
private Rectangle cat;
private Rectangle mouse;
public void myPaint(Graphics g){
Graphics2D g1 = (Graphics2D)g;
Graphics2D g2 = (Graphics2D)g;
g1.setStroke(drawingStroke);
g1.draw(cat);
g1.setPaint(Color.yellow);
g1.fill(cat);
g2.setStroke(drawingStroke);
g2.draw(mouse);
g2.setPaint(Color.red);
g2.fill(mouse);
}
//constructor
public gameView(gameModel _model){
model = _model;
//cat and mouse
cat = new Rectangle(_model.getCatX(), _model.getCatY(), 10, 10);
mouse = new Rectangle(_model.getMouseX(), _model.getMouseY(), 10, 10);
//layout
content.setSize(500, 400);
content.setLayout(new GridLayout(0,2));
leftPanel.setSize(200, 200);
leftPanel.setBackground(Color.blue);
rightPanel.setSize(100, 400);
rightPanel.setLayout(new FlowLayout());
rightPanel.add(new JLabel("Controls"));
rightPanel.add(up);
rightPanel.add(down);
rightPanel.add(left);
rightPanel.add(right);
content.add(leftPanel);
content.add(rightPanel);
this.setSize(500, 400);
this.setContentPane(content);
this.setTitle("Cat & Mouse Game");
}
//returns the leftPanel to repaint in the controller
public JPanel getLeft(){
return leftPanel;
}
//listeners for buttons
public void addUpListener(ActionListener moveUp){
up.addActionListener(moveUp);
}
public void addDownListener(ActionListener moveDown){
down.addActionListener(moveDown);
}
public void addLeftListener(ActionListener moveLeft){
left.addActionListener(moveLeft);
}
public void addRightListener(ActionListener moveRight){
right.addActionListener(moveRight);
}
public void addCloseListener(WindowListener close){
this.addWindowListener(close);
}
//
public Rectangle getCat(){
return cat;
}
public Rectangle getMouse(){
return mouse;
}
//left side board panel
/*class boardPanel extends JPanel{
Stroke drawingStroke = new BasicStroke(1);
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g1 = (Graphics2D)g;
g1.setStroke(drawingStroke);
g1.draw(cat);
g1.setPaint(Color.yellow);
g1.fill(cat);
Graphics2D g2 = (Graphics2D)g;
g2.setStroke(drawingStroke);
g2.draw(mouse);
g2.setPaint(Color.red);
g2.fill(mouse);
}
}
public JPanel getLeft(){
return leftPanel;
}*/
}
Controller
/*
* gameController.java
*/
package game;
import java.awt.event.;
import javax.swing.;
public class gameController {
private gameModel model;
private gameView view;
private JPanel lp = new JPanel();
public gameController(gameModel _model, gameView _view){
model = _model;
view = _view;
lp=_view.getLeft();
//listeners
view.addUpListener(new UpListener());
view.addDownListener(new DownListener());
view.addLeftListener(new LeftListener());
view.addRightListener(new RightListener());
view.addCloseListener(
new WindowAdapter(){
public void windowClosing(WindowEvent we){
System.exit(0);
}
});
}
//DOWN
class DownListener implements ActionListener{
public void actionPerformed(ActionEvent e){
model.setCatY((model.getCatY()+10));
//do a random move for the mouse
//model.randomMove();
//view.getLeft().repaint();
lp.repaint();
System.out.println("x="+model.getCatX()+"y="+model.getCatY());
}
}
//LEFT
class LeftListener implements ActionListener{
public void actionPerformed(ActionEvent e){
model.setCatY((model.getCatY()-10));
//do a random move for the mouse
//model.randomMove();
//view.getLeft().repaint();
lp.repaint();
System.out.println("x="+model.getCatX()+"y="+model.getCatY());
}
}
//RIGHT
class RightListener implements ActionListener{
public void actionPerformed(ActionEvent e){
model.setCatY((model.getCatY()+10));
//do a random move for the mouse
//model.randomMove();
//view.getLeft().repaint();
lp.repaint();
System.out.println("x="+model.getCatX()+"y="+model.getCatY());
}
}
}
Looks like your button listeners update the model, but nothing actually updates the coordinates of the cat and mouse rectangles. They get their initial bounds from the model, but then are never updated.
The view should probably listen to the model to sync the cat and mouse's locations to the actual Rectangle objects.