When a Grid Object is instantiated, a JFrame and JPanel are created. Lines are drawn upon the JPanel to create a square grid. Ideally, the grid will scale if the window is resized.
import javax.swing.JPanel;
import javax.swing.JFrame;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.event.ComponentListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentAdapter;
public class Grid {
private int lines;
private int space;
public static final int DEFAULT_LINES = 5;
public static final int DEFAULT_SPACE = 5;
private JPanel panel = new GridPanel();
private JFrame frame;
public Grid(String name, int lines, int space) {
this.frame = new JFrame(name);
this.lines = lines;
this.space = space;
this.frame.setSize((lines * space), (lines * space));
}
private class GridPanel extends JPanel {
private int start = 0;
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
int end = (lines * space);
g.setColor(Color.BLACK);
for (int i = 0; i < lines; i++) {
int crawl = (space * i);
g.drawLine(start, crawl, end, crawl);
g.drawLine(crawl, start, crawl, end);
}
}
}
/*private class GridHandler extends ComponentAdapter {
#Override
public void componentResized(ComponentEvent e) {
super.componentResized(e);
setSpace();
frame.repaint();
frame.revalidate();
}
}*/
public void setSpace() {
space = (frame.getSize().width * frame.getSize().height) / lines;
}
public void run() {
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(panel);
//frame.addComponentListener(new GridHandler());
frame.setVisible(true);
}
}
public class Run {
public static final int ONE_LINES = 15;
public static final int ONE_SPACE = 20;
public static final int TWO_LINES = 35;
public static final int TWO_SPACE = 16;
public static void main(String[] args) {
Grid grid1 = new Grid("Grid One", ONE_LINES, ONE_SPACE);
Grid grid2 = new Grid("Grid Two", TWO_LINES, TWO_SPACE);
grid1.run();
grid2.run();
}
}
These are the only two files being used. The Handler is currently commented out, and the code does what is expected. Two windows with grids are created. However, when the handler is implemented, the grid no longer shows up. What is the correct implementation for the handler?
For anyone that cares, this is a viable solution. As it turns out, a componentResized Event Handler is not needed. The paintComponent is automatically executed when the JFrame is re-sized.
The following code creates two separate JFrames. Each JFrame contains a single JPanel. A unique square grid is drawn on the JPanel. If the JFrame is re-sized, the grid will also re-size (while still remaining square).
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.*;
public class Grid extends JPanel {
private static final int DEFAULT_COUNT = 10;
private static final int DEFAULT_SIZE = 100;
private int count;
public Grid(int count, int size) {
if (size < 1) {
this.count = DEFAULT_COUNT;
this.setPreferredSize(new Dimension(DEFAULT_SIZE, DEFAULT_SIZE));
} else {
this.count = count;
this.setPreferredSize(new Dimension(size, size));
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D graphics = (Graphics2D) g;
graphics.setColor(Color.black);
Dimension size = getSize();
int w = size.width;
int h = size.height;
if (w > h) {
w = h;
} else if (h > w) {
h = w;
}
int spaceWidth = (int)((double)w / count);
int spaceHeight = (int)((double)h / count);
for (int row = 0; row <= count; row++) {
int y = (row * spaceHeight);
int x = (row * spaceWidth);
graphics.drawLine(0, y, (spaceWidth * count), y);
graphics.drawLine(x, 0, x, (spaceHeight * count));
}
}
}
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.*;
public class Test {
public static final int COUNT_1 = (-5);
public static final int SIZE_1 = 4;
public static final int COUNT_2 = 35;
public static final int SIZE_2 = 16;
public static void main(String[] args) {
int area1 = COUNT_1 * SIZE_1;
int area2 = COUNT_2 * SIZE_2;
Grid grid = new Grid(COUNT_1, area1);
JFrame frame = new JFrame("Grid");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(grid);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
Grid grid2 = new Grid(COUNT_2, area2);
JFrame frame2 = new JFrame("Grid");
frame2.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame2.add(grid2);
frame2.pack();
frame2.setLocationRelativeTo(null);
frame2.setVisible(true);
}
}
Related
I am developing the peg game in java, and I have been stuck on getting a hole to change color when it is clicked on to indicate that it has been selected. I currently have 3 classes, all of which extend JPanel:
Display.java: creates the JFrame and renders the gameboard to the JFrame.
GameBoard.java: Holds the logic for rendering the gameboard.
Hole.java: Renders a hole and holds the logic for the MouseListener. When one clicks on a hole, it should turn blue to indicate that it is selected.
I am able to render the holes onto the gameboard, however, the MouseListener does not work; When I click on a hole, it does not turn blue.
Below are the three classes:
Display.java
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.util.logging.*;
public class Display extends JPanel {
private static final long serialVersionUID = 1L;
private static String staticClassName = Display.class.getName();
private static Logger logger = Logger.getLogger(staticClassName);
private final static Logger LOGGER = Logger.getLogger(staticClassName);
private static String title;
private static int width;
private static int height;
private static JFrame frame;
private static JPanel mainPanel;
private static GameBoard gameBoard;
public Display(String title, int width, int height){
logger.info(staticClassName +".Constructor: Constructing Display");
Display.title = title;
Display.width = width;
Display.height = height;
logger.info(staticClassName +".Constructor: Display constructed.");
initDisplay();
}
private static void initDisplay() {
logger.info(staticClassName +".initDisplay(): Entering method");
try {
logger.info(staticClassName +".initDisplay(): About to create JFrame");
frame = new JFrame(title);
frame.setLocationByPlatform(true);
frame.setVisible(true);
frame.setSize(width, height);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainPanel = new JPanel();
logger.info(staticClassName +".initDisplay(): About to create GameBoard object");
gameBoard = new GameBoard();
mainPanel.add(gameBoard);
frame.getContentPane().add(mainPanel);
frame.pack();
} catch (Exception e) {
logger.info(staticClassName +".initDisplay(): Failed to render display: " + e);
}
logger.info(staticClassName +".initDisplay(): Exiting Method");
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
LOGGER.setLevel(Level.INFO);
Display d = new Display("Peg Game", 800, 800);
} catch (Exception e) {
}
}
});
}
}
GameBoard.java
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Path2D;
import java.util.logging.Logger;
import javax.swing.JPanel;
public class GameBoard extends JPanel {
private static final long serialVersionUID = 1L;
private static String staticClassName = GameBoard.class.getName();
private static Logger logger = Logger.getLogger(staticClassName);
private static final int RGB1 = 223;
private static final int RGB2 = 191;
private static final int RGB3 = 159;
private static final int WIDTH = 800;
private static final int HEIGHT = WIDTH;
private Path2D path = new Path2D.Double();
private static Color boardColor = new Color(RGB1, RGB2, RGB3);
private int [] adjacentHoles1;
public GameBoard() {
logger.info(staticClassName +".Constructor: Constructing GameBoard");
double firstX = (WIDTH / 2.0) * (1 - 1 / Math.sqrt(3));
double firstY = 3.0 * HEIGHT / 4.0;
path.moveTo(firstX, firstY);
path.lineTo(WIDTH - firstX, firstY);
path.lineTo(WIDTH / 2.0, HEIGHT / 4.0);
path.closePath();
logger.info(staticClassName +".Constructor: GameBoard constructed");
}
#Override
protected void paintComponent(Graphics g) {
logger.info(staticClassName +".paintComponent(): Entering method");
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(boardColor);
g2.fill(path);
int xPos = 390;
int yPos = 310;
// I was rendering up to 15 holes, but took them out for purpose of
// shortening my example
for (int i = 0; i < 15; i ++ ) {
if (i == 0) {
// Declare the hole here
Hole hole = new Hole(i, xPos, yPos, adjacentHoles1);
// Render it here
hole.paintComponent(g2);
yPos += 50;
}
}
logger.info(staticClassName +".paintComponent(): Exiting method");
}
#Override
public Dimension getPreferredSize() {
logger.info(staticClassName +".getPreferredSize(): Entering method");
if (isPreferredSizeSet()) {
logger.info(staticClassName +".getPreferredSize(): isPreferredSizeSet() == true. Exiting method");
return super.getPreferredSize();
}
logger.info(staticClassName +".getPreferredSize(): isPreferredSizeSet() == false. Exiting method");
return new Dimension(WIDTH, HEIGHT);
}
}
Hole.java
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.util.logging.Logger;
import javax.swing.JPanel;
public class Hole extends JPanel {
private static final long serialVersionUID = 1235245435988434L;
private static String staticClassName = Hole.class.getName();
private static Logger logger = Logger.getLogger(staticClassName);
private int holeNumber;
private int xPos, yPos;
private final int HOLEWIDTH = 20;
private final int HOLEHEIGHT = HOLEWIDTH;
private static final int RGB1 = 0;
private static final int RGB2 = 0;
private static final int RGB3 = 0;
private static Color defaultCircleColor = new Color(RGB1, RGB2, RGB3);
private static Color selectedCircleColor = Color.BLUE;
private static Color circleColor = defaultCircleColor;
private int [] adjacentHoles;
public Hole (int holeNumber, int xPos, int yPos, int [] adjacentHoles) {
logger.info(staticClassName +".Constructor: Constructing Hole");
this.holeNumber = holeNumber;
this.xPos = xPos;
this.yPos = yPos;
this.adjacentHoles = adjacentHoles;
initComponents();
}
#Override
protected void paintComponent(Graphics g) {
logger.info(staticClassName +".paintComponent(): Entering method");
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(circleColor);
g2.fillOval(xPos,yPos,HOLEWIDTH,HOLEHEIGHT);
logger.info(staticClassName +".paintComponent(): Exiting method");
}
private void initComponents() {
addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent event) {
selectHole(event);
}});
}
public void selectHole(java.awt.event.MouseEvent event) {
logger.info(staticClassName +"------------------------------------------------");
logger.info(staticClassName +".selectHole(): Entering method");
if (circleColor == defaultCircleColor) {
circleColor = selectedCircleColor;
repaint();
}
else {
circleColor = defaultCircleColor;
repaint();
}
logger.info(staticClassName +".selectHole(): Exiting method");
logger.info(staticClassName +"------------------------------------------------");
}
#Override
public Dimension getPreferredSize() {
logger.info(staticClassName +".getPreferredSize(): Getting the preferred size of the circle.");
return new Dimension(800, 800);
}
}
As a side note, if you notice that I could be using better coding practices anywhere in my code, please let me know.
So, your basic problem is right here...
for (int i = 0; i < 15; i ++ ) {
if (i == 0) {
// Declare the hole here
Hole hole = new Hole(i, xPos, yPos, adjacentHoles1);
// Render it here
hole.paintComponent(g2);
yPos += 50;
}
}
Hole is component, you should never call any paint method of component, but, you component is also not "live", meaning that it can never receive ANY events.
What you should do instead, is attach the MouseListener to the GameBoard and test if the mouse was clicked at a place there is a hole.
The simplest solution is to make use of the "shapes" API and generate a list of "holes". This can then be simply iterated over to paint and check to see if the mouse was clicked within it.
I've not gone to a great deal of effort in determining the location of the holes, instead I've just laid them out in rows/cols, but you should get the basic idea of the intended solution
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Path2D;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Display extends JPanel {
private static final long serialVersionUID = 1L;
private static String staticClassName = Display.class.getName();
private static Logger logger = Logger.getLogger(staticClassName);
private final static Logger LOGGER = Logger.getLogger(staticClassName);
private static String title;
private static int width;
private static int height;
private static JFrame frame;
private static JPanel mainPanel;
private static GameBoard gameBoard;
public Display(String title, int width, int height) {
logger.info(staticClassName + ".Constructor: Constructing Display");
Display.title = title;
Display.width = width;
Display.height = height;
logger.info(staticClassName + ".Constructor: Display constructed.");
initDisplay();
}
private static void initDisplay() {
frame = new JFrame(title);
frame.setLocationByPlatform(true);
frame.setVisible(true);
frame.setSize(width, height);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainPanel = new JPanel();
gameBoard = new GameBoard();
mainPanel.add(gameBoard);
frame.getContentPane().add(mainPanel);
frame.pack();
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
LOGGER.setLevel(Level.INFO);
Display d = new Display("Peg Game", 800, 800);
} catch (Exception e) {
}
}
});
}
public static class GameBoard extends JPanel {
private static final long serialVersionUID = 1L;
private static String staticClassName = GameBoard.class.getName();
private static Logger logger = Logger.getLogger(staticClassName);
private static final int RGB1 = 223;
private static final int RGB2 = 191;
private static final int RGB3 = 159;
private static final int WIDTH = 800;
private static final int HEIGHT = WIDTH;
private Path2D path = new Path2D.Double();
private static Color boardColor = new Color(RGB1, RGB2, RGB3);
private int[] adjacentHoles1;
private Shape[] holes;
private Shape selectedHole;
public GameBoard() {
logger.info(staticClassName + ".Constructor: Constructing GameBoard");
double firstX = (WIDTH / 2.0) * (1 - 1 / Math.sqrt(3));
double firstY = 3.0 * HEIGHT / 4.0;
path.moveTo(firstX, firstY);
path.lineTo(WIDTH - firstX, firstY);
path.lineTo(WIDTH / 2.0, HEIGHT / 4.0);
path.closePath();
logger.info(staticClassName + ".Constructor: GameBoard constructed");
holes = new Shape[15];
int yPos = 310;
int index = 0;
for (int row = 0; row < 3; row++) {
int xPos = 390;
for (int col = 0; col < 5; col++) {
holes[index] = new Ellipse2D.Double(xPos, yPos, 50, 50);
index++;
xPos += 50;
}
yPos += 50;
}
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
selectedHole = null;
for (Shape hole : holes) {
if (hole.contains(e.getPoint())) {
selectedHole = hole;
break;
}
}
repaint();
}
});
}
#Override
protected void paintComponent(Graphics g) {
logger.info(staticClassName + ".paintComponent(): Entering method");
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(boardColor);
g2.fill(path);
g2.setColor(Color.BLACK);
for (Shape hole : holes) {
g2.fill(hole);
}
if (selectedHole != null) {
g2.setColor(Color.RED);
g2.fill(selectedHole);
}
logger.info(staticClassName + ".paintComponent(): Exiting method");
}
#Override
public Dimension getPreferredSize() {
logger.info(staticClassName + ".getPreferredSize(): Entering method");
if (isPreferredSizeSet()) {
logger.info(staticClassName + ".getPreferredSize(): isPreferredSizeSet() == true. Exiting method");
return super.getPreferredSize();
}
logger.info(staticClassName + ".getPreferredSize(): isPreferredSizeSet() == false. Exiting method");
return new Dimension(WIDTH, HEIGHT);
}
}
}
When i setSize of a jLabel, normally it grows towards bottom. How can i increase the height in positive y direction ?
After pressing init
Current Result
Expected result
My source code
private void initActionPerformed(java.awt.event.ActionEvent evt) {
int p = Integer.parseInt(abc[0].getText());
int q = Integer.parseInt(abc[1].getText());
int r = Integer.parseInt(abc[2].getText());
int s = Integer.parseInt(abc[3].getText());
int t = Integer.parseInt(abc[4].getText());
one.setSize(20, p*10 );
one.setBackground(Color.decode("#03A9F4"));
two.setSize(20, q*10 );
two.setBackground(Color.decode("#03A9F4"));
three.setSize(20, r*10 );
three.setBackground(Color.decode("#03A9F4"));
four.setSize(20, s*10 );
four.setBackground(Color.decode("#03A9F4"));
five.setSize(20, t*10 );
five.setBackground(Color.decode("#03A9F4"));
}
one,two,three are the label names.
abc is an array containing all the labels
You're finding out that Java considers positive y direction graphics to be down, which is in keeping with how computer monitors see y direction. Solutions include:
Figure out a maximum size, and subtract your y height from it to figure out where to start your JLabel.
Even better, don't use JLabels but draw within a JPanel's paintComponent, using the same calculations as above.
For example:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
#SuppressWarnings("serial")
public class GraphicsEg extends JPanel {
private static final int DATA_COLUMNS = 5;
private List<JSlider> sliders = new ArrayList<>();
private DrawPanel drawPanel = new DrawPanel(DATA_COLUMNS);
public GraphicsEg() {
JPanel sliderPanel = new JPanel(new GridLayout(1, 0, 5, 5));
SliderListener sliderListener = new SliderListener();
for (int i = 0; i < DATA_COLUMNS; i++) {
JSlider slider = new JSlider(0, 100, 50);
slider.setPaintLabels(true);
slider.setPaintTicks(true);
slider.setPaintTrack(true);
slider.setMajorTickSpacing(20);
slider.setMinorTickSpacing(5);
slider.setOrientation(SwingConstants.VERTICAL);
slider.addChangeListener(sliderListener);
sliders.add(slider);
sliderPanel.add(slider);
}
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
setLayout(new BorderLayout(5, 5));
add(drawPanel, BorderLayout.CENTER);
add(sliderPanel, BorderLayout.PAGE_END);
sliderValuesIntoDrawPanel();
}
private void sliderValuesIntoDrawPanel() {
int[] data = new int[DATA_COLUMNS];
for (int i = 0; i < data.length; i++) {
data[i] = sliders.get(i).getValue();
}
drawPanel.setData(data);
}
private class SliderListener implements ChangeListener {
#Override
public void stateChanged(ChangeEvent e) {
sliderValuesIntoDrawPanel();
}
}
private static void createAndShowGui() {
GraphicsEg mainPanel = new GraphicsEg();
JFrame frame = new JFrame("GraphicsEg");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
#SuppressWarnings("serial")
class DrawPanel extends JPanel {
private static final int PREF_W = 600;
private static final int PREF_H = 400;
private static final int PAD = 20;
private static final Color BORDER_COLOR = Color.BLUE;
private static final Color COLUMN_COLOR = Color.RED;
private static final double RELATIVE_COL_WIDTH = 2.0 / 3.0;
private int dataColumns = 0;
private int[] data;
public DrawPanel(int dataColumns) {
this.dataColumns = dataColumns;
data = new int[dataColumns];
setBorder(BorderFactory.createLineBorder(BORDER_COLOR));
}
public void setData(int[] data) {
this.data = data;
repaint();
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i = 0; i < data.length; i++) {
drawColumn(g, i, data[i]);
}
}
private void drawColumn(Graphics g, int index, int columnHeight) {
g.setColor(COLUMN_COLOR);
int width = (int) (RELATIVE_COL_WIDTH * (PREF_W - 2 * PAD) / dataColumns);
int x = PAD + (index * (PREF_W - 2 * PAD)) / dataColumns;
int height = (columnHeight * (PREF_H - 2 * PAD)) / 100;
int y = PREF_H - PAD - height;
g.fillRect(x, y, width, height);
}
}
I'm trying to code a simple Pong and I have the background panel which contains a Bar panel. So of course I need to be able to place the bar on the size and move it vertically at request. Now I'm just trying to put it in a starting position. If I don't disable the layout the bar gets placed in the top center regardless of location setting, but if I disable the layout and set location it just doesn't show up. I'm not sure what I missing. Here is a code snippet if it can be relevant:
public PongPanel() {
setLayout(null);
setPreferredSize(SIZE);
setBackground(Color.BLACK);
player_one_bar = new Bar();
add(player_one_bar);
player_one_bar.setLocation(10, getSize().height/2-3);
}
If you set the layout manager as null you'll have to specify the exact coordinates of the panel, meaning something like -
setBounds(10, 10, 20, 100);
Will put the panel at location (10,10) with Width of 20 and Height of 100.
If by "bar" you mean Pong game paddle, then it shouldn't be a component at all but rather a logical entity that represents a position, which is visually represented by a sprite that gets drawn in the JPanel's paintComponent method.
For example:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class PongPaddle extends JPanel {
private static final int PREF_W = 800;
private static final int PREF_H = 500;
private static final int RECT_X = 20;
private static final int RECT_W = 10;
private static final int RECT_H = 60;
private static final int STARTING_Y = (PREF_H - RECT_H) / 2;
private static final int TIMER_DELAY = 15;
private static final int DELTA_PADDLE = 3;
private boolean paddle1GoingDown = true;
private boolean paddle2GoingDown = false;
private Rectangle paddle1 = new Rectangle(RECT_X, STARTING_Y, RECT_W, RECT_H);
private Rectangle paddle2 = new Rectangle(PREF_W - RECT_X - RECT_W,
STARTING_Y, RECT_W, RECT_H);
public PongPaddle() {
setBackground(Color.black);
new Timer(TIMER_DELAY, new TimerListener()).start();
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class TimerListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
int deltaPaddle1 = paddle1GoingDown ? 1 : -1;
deltaPaddle1 *= DELTA_PADDLE;
int x = paddle1.getLocation().x;
int y = paddle1.getLocation().y + deltaPaddle1;
if (y + RECT_H >= PREF_H) {
paddle1GoingDown = false;
}
if (y <= 0) {
paddle1GoingDown = true;
}
paddle1.setLocation(x, y);
int deltaPaddle2 = paddle2GoingDown ? 1 : -1;
deltaPaddle2 *= DELTA_PADDLE;
x = paddle2.getLocation().x;
y = paddle2.getLocation().y + deltaPaddle2;
if (y + RECT_H >= PREF_H) {
paddle2GoingDown = false;
}
if (y <= 0) {
paddle2GoingDown = true;
}
paddle2.setLocation(x, y);
repaint();
if (!PongPaddle.this.isShowing()) {
((Timer) e.getSource()).stop();
}
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.white);
if (paddle1 != null) {
g2.fill(paddle1);
}
if (paddle2 != null) {
g2.fill(paddle2);
}
}
private static void createAndShowGui() {
PongPaddle mainPanel = new PongPaddle();
JFrame frame = new JFrame("PongPaddle");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
I have a 2d array of Grids (JPanels) that are added to another JPanel using the GridLayout. That JPanel is added to the JFrame. Whenever a click happens on the JFrame I'm attempting to take the Point of the click and determine if any of those Grids in the 2d array contain that Point.
I'm attempting to do this inside frame.addMouseListener...
I know the frame is registering the mouse clicks. For some reason the Grids don't register that they should be containing that Point. Can anyone explain this? if(theView[i][j].contains(me.getPoint())){ This is the line of code that seems to be failing me.
I originally attempted to have the Grids know when they were clicked on so I wouldn't have to coordinate between the frame and grids, but I couldn't get that to work.
Here's the level designer.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.*;
import javax.swing.*;
public class LevelDesigner extends JPanel implements ButtonListener{
private final int SIZE = 12;
private int [][] thePit;
private Grid [][] theView;
private ButtonPanel bp;
public static int val;
private int rows, cols;
private JPanel gridPanel;
private JFrame frame;
public LevelDesigner(int r, int c){
frame = new JFrame();
int h = 10, w = 10;
setVisible(true);
setLayout(new BorderLayout());
setBackground(Color.BLUE);
rows = r;
cols = c;
thePit = new int[r][c];
theView = new Grid[r][c];
gridPanel = new JPanel();
gridPanel.setVisible(true);
gridPanel.setBackground(Color.BLACK);
gridPanel.setPreferredSize(getMaximumSize());
GridLayout gridLayout = new GridLayout();
gridLayout.setColumns(cols);
gridLayout.setRows(rows);
gridPanel.setLayout(gridLayout);
for(int i = 0; i < r; i++){
for(int j = 0; j < c; j++){
theView[i][j] = new Grid(i, j, SIZE, this);
gridPanel.add(theView[i][j]);
}
}
String test [] = {"0", "1","2","3","4","save"};
bp = new ButtonPanel(test, this);
this.add(bp, BorderLayout.SOUTH);
this.add(gridPanel, BorderLayout.CENTER);
frame.addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent me) {
for(int i = 0; i < rows; ++i){
for(int j = 0; j < cols; ++j){
if(theView[i][j].contains(me.getPoint())){
theView[i][j].actionPerformed(null);
return;
}
}
}
}
});
frame.setVisible(true);
frame.setExtendedState(java.awt.Frame.MAXIMIZED_BOTH);
frame.setTitle("Epic Crawl - Main Menu");
frame.pack();
frame.setLocationRelativeTo(null);
frame.repaint();
frame.add(this);
}
public String toString(){
int noRows = thePit.length;
int noColumns = thePit[0].length;
String s="";
for (int r=0;r<noRows;r++){
for (int c=0;c<noColumns;c++){
s=s + thePit[r][c] + " ";
}
s=s+"\n";
}
return(s);
}
public void notify( int i, int j){
thePit[i][j] = val;
}
public void print(){
final JFileChooser fc = new JFileChooser();
fc.setCurrentDirectory(new java.io.File("."));
int returnVal = fc.showSaveDialog( null);
if( returnVal == JFileChooser.APPROVE_OPTION ){
try{
PrintWriter p = new PrintWriter(
new File( fc.getSelectedFile().getName() ) );
System.out.println(" printing");
p.println( this );
p.close();
}
catch( Exception e){
System.out.println("ERROR: file not saved");
}
}
}
public void buttonPressed(String buttonLabel, int id){
if(id == 5)
print();
else
val = id;
}
public void buttonReleased( String buttonLabel, int buttonId ){}
public void buttonClicked( String buttonLabel, int buttonId ){}
public static void main(String arg[]){
LevelDesigner levelDesigner = new LevelDesigner(4, 4);
}
}
And here is the Grid.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.InputStream;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class Grid extends JPanel implements ActionListener{
LevelDesigner grid;
int myI, myJ;
private String[] imageNames = {"dirt.png", "grass.png", "Door.png", "woodfloor.png", "32x32WoodFloor.png"};
BufferedImage gridImage;
private String imagePath;
public Grid(int i, int j, int size, LevelDesigner m){
imagePath = "";
grid = m;
myI = i;
myJ = j;
setBackground(Color.RED);
this.setBorder(BorderFactory.createLineBorder(Color.black));
this.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent ae){
grid.notify(myI, myJ);
imagePath = "Images/" + imageNames[LevelDesigner.val];
gridImage = null;
InputStream input = this.getClass().getClassLoader().getResourceAsStream(imagePath);
try{
gridImage = ImageIO.read(input);
}catch(Exception e){System.err.println("Failed to load image");}
}
public void paintComponent(Graphics g){
super.paintComponent(g); // Important to call super class method
g.clearRect(0, 0, getWidth(), getHeight()); // Clear the board
g.drawImage(gridImage, 0, 0, getWidth(), getHeight(), null);
}
}
The contains method checks if the Point is within the boundaries of the JPanel but using a coordinate system relative to the JPanel. Instead consider using findComponentAt(Point p).
For example:
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
public class TestMouseListener {
private static final int SIDE_COUNT = 4;
private JPanel mainPanel = new JPanel();
private MyGridCell[][] grid = new MyGridCell[SIDE_COUNT][SIDE_COUNT];
public TestMouseListener() {
mainPanel.setLayout(new GridLayout(SIDE_COUNT, SIDE_COUNT));
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[i].length; j++) {
grid[i][j] = new MyGridCell();
mainPanel.add(grid[i][j].getMainComponent());
}
}
mainPanel.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
Point p = e.getPoint();
Component c = mainPanel.findComponentAt(p);
for (MyGridCell[] gridRow : grid) {
for (MyGridCell myGridCell : gridRow) {
if (c == myGridCell.getMainComponent()) {
myGridCell.setLabelText("Pressed!");
} else {
myGridCell.setLabelText("");
}
}
}
}
});
}
public Component getMainComponent() {
return mainPanel;
}
private static void createAndShowGui() {
TestMouseListener mainPanel = new TestMouseListener();
JFrame frame = new JFrame("TestMouseListener");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel.getMainComponent());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class MyGridCell {
private static final int PREF_W = 200;
private static final int PREF_H = PREF_W;
#SuppressWarnings("serial")
private JPanel mainPanel = new JPanel() {
public Dimension getPreferredSize() {
return MyGridCell.this.getPreferredSize();
};
};
private JLabel label = new JLabel();
public MyGridCell() {
mainPanel.setBorder(BorderFactory.createLineBorder(Color.black));
mainPanel.setLayout(new GridBagLayout());
mainPanel.add(label);
}
public Component getMainComponent() {
return mainPanel;
}
public void setLabelText(String text) {
label.setText(text);
}
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
}
Component#contains "Checks whether this component "contains" the specified point, where the point's x and y coordinates are defined to be relative to the coordinate system of this component"
This means that the contains will only return true if the Point is within the bounds of 0 x 0 x width x height.
So if the component is position at 400x200 and is sized at 200x200 (for example). When you click within in, the mouse point will be between 400x200 and 600x400, which is actually out side of the relative position of the component (200x200) - confused yet...
Basically, you either need to convert the click point to a relative coordinate within the context of the component you are checking...
Point p = SwingUtilities.convertPoint(frame, me.getPoint(), theView[i][j])
if (theView[i][j].contains(p)) {...
Or use the components Rectangle bounds...
if (theView[i][j].getBounds().contains(me.getPoint())) {...
So, remember, mouse events are relative to the component that they were generated for
I need help with drawing the grids to the GUI as well as the program later letting me change the colour of the boxes drawn. I know i will have to use paintComponent(Graphics g), but i have no idea how or where.
So here is a copy of the code i have got so far ( even though i have been told it can be quite daunting just being given code i think it is the best way for people to help and not just do it for me). From the top it sets values, creates the GUI, calls the GUI, fills a 2d array with boxes( i think). Then in the Boxes class setting values the boxes class will need, then the start of how to draw them (didn't know how to work it out), then some seta methods for the x and y coordinates.
what i would like you to do is show how to have the boxes be drawn to the Jpanel, to make a grid and then to show me how to change the colour to different shades of blue, depending on a external value.
import java.awt.*;
import java.awt.Graphics;
import java.util.*;
import javax.swing.*;
public class NewGrid {
Boxes[][] Boxs;
int BoxesX;
int BoxesY;
NewGrid() {
buildtheGUI();
}
JFrame frame = new JFrame();
JPanel panel = new JPanel();
public void buildtheGUI() {
frame.setSize(500, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel);
frame.setVisible(true);
}
public static void main(String[] args) {
new NewGrid();
}
public void addboxes() {
Boxs = new Boxes[panel.getWidth() / 10][panel.getHeight() / 10];
for (int i = 0; i < panel.getWidth() / 10; i++) {
for (int j = 0; j < panel.getHeight() / 10; j++) {
Boxs[i][j] = new Boxes();
Boxs[i][j].setx(i * (panel.getWidth() / 10));
Boxs[i][j].sety(j * (panel.getHeight() / 10));
Boxs[i][j].draw(null);
}
}
}
}
public class Boxes extends JPanel {
int x;
int y;
int width = 10;
int hieight = 10;
Color colour = Color.BLACK;
public void draw(Graphics g) {
g.setColor(colour);
g.fillRect(x, y, width, hieight);
}
public void setx(int i ){
x = i;
}
public void sety(int i ){
y = i;
}
}
I can't comment something, to try to make things easier,
I code there box.putClientProperty(unique_identifier, value_for_identifier), you can to multiple this method as you want
from every Swing Listener you can to get this and proper coordinated defined in putClientProperty
.
JComponent comp = event.getComponent();
String strRow = (String) comp.getClientProperty("row");
String strColumn = (String) comp.getClientProperty("column");
simple code
import java.awt.*;
import java.awt.Graphics;
import java.util.*;
import javax.swing.*;
public class NewGrid {
private int row = 10;
private int column = 10;
private JFrame frame = new JFrame();
private JPanel panel = new JPanel();
private NewGrid() {
addboxes();
panel.setLayout(new GridLayout(row, column));
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
private void addboxes() {
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
Boxes box = new Boxes();
box.putClientProperty("row", row);
box.putClientProperty("column", column);
panel.add(box);
}
}
}
public static void main(String[] args) {
Runnable doRun = new Runnable() {
#Override
public void run() {
new NewGrid();
}
};
SwingUtilities.invokeLater(doRun);
}
}
class Boxes extends JPanel {
private static final long serialVersionUID = 1L;
#Override
public Dimension getMinimumSize() {
return new Dimension(20, 20);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(20, 20);
}
#Override
public Dimension getMaximumSize() {
return new Dimension(20, 20);
}
#Override
public void paintComponent(Graphics g) {
int margin = 2;
Dimension dim = getSize();
super.paintComponent(g);
g.setColor(Color.red);
g.fillRect(margin, margin, dim.width - margin * 2,
dim.height - margin * 2);
}
}