Swing draw string centeralised - java

I have to draw n + 1 amount of circles horizontally and vertically in a GUI. Which I have successfully done as shown below. With this, a 2D array of strings will be printed between them, centralised.
How it currently stands
Now I want to draw numbers in a "square" of the dots.
How I want the final result
for (int i = 0; i < width; i++) {
for (int j = 0; j < width; j++) {
canvas.drawCircle( (j + 1) * 125, (i + 1) * 125, 15, Color.white);
}
}
for (int r = 0; r < size; r++) {
for (int c = 0; c < size; c++) {
canvas.drawString(events[r][c], (r + 1) * 150, (c + 1) * 150, Color.green );
}
}
Width in this case is 4, so basically (n-1) dots/circles in the picture.
Size is 3 which is just the length of the 2d array, as there are 4 circles in this case there will be 3 numbers between each one
Events is the 2D array with the data containing the numbers
The drawCircle method's signature is
(x, y, radius, color)
The drawString method's signature is
(text, x, y color)
I believe part of the problem is also the drawing of circles. Basically I think it has to do with the rubbish formula I have for determining the x, y coords for both circles and the text. Any help is appreciated, thank you.

Provided is some code which I believe does what you want. Some of the constants may be tweaked to fit your final requirements. I used a 2D array of numbers and converted to strings during paint. It also allows for the following:
Changing the ball diameter or number of balls will still provide a
correct graph (although it will change its location within the
panel).
The String numbers track along with the size of the balls
Anti-aliasing was turned on to smooth out the graphics.
FontMetrics was used to fine tune the location of the numbers.
One final note: Because this is not resource intensive, the coordinates are calculated within the paintComponent method. A more optimum solution would be to adopt the Flyweight design pattern and precalculate as much as possible before entering paintComponent.
import java.awt.*;
import javax.swing.*;
public class SwingMain extends JPanel {
final static int WIDTH = 700;
final static int HEIGHT = 700;
final static int SEPARATION = 100;
final static int DIAMETER = 25;
final static int NBALLS = 4;
final static int XSTART = WIDTH / (NBALLS + 2);
final static int YSTART = HEIGHT / (NBALLS + 2);
JFrame frame = new JFrame();
int[][] numbers = new int[NBALLS - 1][NBALLS - 1];
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new SwingMain().start());
}
public void start() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setPreferredSize(new Dimension(WIDTH, HEIGHT));
frame.add(this);
setBackground(Color.RED);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
// populate numbers in 2D array.
for (int r = 0; r < NBALLS - 1; r++) {
for (int c = 0; c < NBALLS - 1; c++) {
numbers[r][c] = r * (NBALLS - 1) + c + 1;
}
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
// Allow smoothing of the graphics.
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.white);
// Iterating by the number of balls is more consistent than
// by x and y due to round of errors.
int y = YSTART;
for (int r = 0; r < NBALLS; r++) {
int x = XSTART;
for (int c = 0; c < NBALLS; c++) {
g2d.fillOval(x, y, DIAMETER, DIAMETER);
x += SEPARATION;
}
y += SEPARATION;
}
// This is the same as above except that the start begins
// halfway between the first row and column
// have the size of the font track with the diameter of the balls
g2d.setFont(new Font("ARIAL", Font.BOLD, DIAMETER));
FontMetrics fm = g2d.getFontMetrics();
y = YSTART + SEPARATION / 2;
for (int r = 0; r < NBALLS - 1; r++) {
int x = XSTART + SEPARATION / 2;
for (int c = 0; c < NBALLS - 1; c++) {
String number = Integer.toString(numbers[r][c]);
// Do some final position adjustment with the font metrics to
// center the number
int strWidth = fm.stringWidth(number);
int strHeight = fm.getAscent();
g2d.drawString(number,
x - strWidth / 2 + DIAMETER / 2,
y + strHeight);
x += SEPARATION;
}
y += SEPARATION;
}
}
}

You could store the coordinates of the circles in a 2D array as well, and use that to find the location of the strings. One thing to note is that the drawCircle method for some reason wont draw the circle with the given center (the coordinates you give will be the top left corner actually).
Point[][] circleCoords = new Point[width][width]; //suppose Point class has x and y coords
for (int i = 0; i < width; i++) {
for (int j = 0; j < width; j++) {
//the -15 actually centers the circle to the coordianates
circleCoords[i][j] = new Point((j + 1) * 125 - 15, (i + 1) * 125 -15);
canvas.drawCircle(circleCoords[i][j].x , circleCoords[i][j].y, 15, Color.white);
}
}
for (int r = 0; r < width-1; r++) {
for (int c = 0; c < width-1; c++) {
//calculate coords from circleCoords array: halfway between them
int xCoord = (circleCoords[r][c].x + circleCoords[r+1][c].x)/2;
int yCoord = (circleCoords[r][c].y + circleCoords[r][c+1].y)/2;
//wont be out of bounds, becouse this runs to width-1
canvas.drawString(events[r][c], xCoord, yCoord, Color.green );
}
}
This still wont actually be perfectly centered, because the drawString will use the coordinates for top left point as well, and not centerpoint. Maybe I miscalculated something, but this should give you the idea: instead of calculating the coordinates independently, re-use the circle coordinates.

Consider a class that represents a single square. The value is represented by a JLabel which is placed at the bottom using straight-forward layout manager (BorderLayout in this example). You can change or manipulate the layout manager to change to position of the JLabel.
class Square extends JPanel{
private static int WIDTH = 100, HEIGHT = 100, DAIMETER = 30, GAP = 5;
private final JLabel label;
Square(int value) {
setPreferredSize(new Dimension(WIDTH, HEIGHT));
setLayout(new BorderLayout());
setBackground(Color.red);
setOpaque(true);
label = new JLabel(String.valueOf(value), JLabel.RIGHT);
label.setForeground (Color.white);
Border margin = new EmptyBorder(GAP,GAP,GAP,2*GAP); //top left bottom right
label.setBorder(margin);
add(label, BorderLayout.PAGE_END);
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.white);
g2d.fillOval(WIDTH/2 - DAIMETER/2, HEIGHT/2-DAIMETER/2, DAIMETER, DAIMETER);
}
}
Now add 16 instances of this Square to panel representing a board. Its layout manager is set to GridLayout:
class Board extends JPanel{
private static int ROWS = 4, COLS = 4;
Board(){
setLayout(new GridLayout(ROWS, COLS));
for(int index = 0; index < ROWS * COLS; index ++){
add(new Square(index)); //index is used as value for demonstration purposes
}
}
}
Putting it all together (this is a one-file mcve. Copy paste the entire code into SwingMain.java and run )
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
public class SwingMain {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocation(400,250);
frame.add(new Board());
frame.pack();
frame.setResizable(false);
frame.setVisible(true);
}
}
class Board extends JPanel{
private static int ROWS = 4, COLS = 4;
Board(){
setLayout(new GridLayout(ROWS, COLS));
for(int index = 0; index < ROWS * COLS; index ++){
add(new Square(index)); //index is used as value for demonstration purposes
}
}
}
class Square extends JPanel{
private static int WIDTH = 100, HEIGHT = 100, DAIMETER = 30, GAP = 5;
private final JLabel label;
Square(int value) {
setPreferredSize(new Dimension(WIDTH, HEIGHT));
setLayout(new BorderLayout());
setBackground(Color.red);
setOpaque(true);
label = new JLabel(String.valueOf(value), JLabel.RIGHT);
label.setForeground (Color.white);
Border margin = new EmptyBorder(GAP,GAP,GAP,2*GAP); //top left bottom right
label.setBorder(margin);
add(label, BorderLayout.PAGE_END);
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.white);
g2d.fillOval(WIDTH/2 - DAIMETER/2, HEIGHT/2-DAIMETER/2, DAIMETER, DAIMETER);
}
}

Related

Graphing one function at a time

I have 3 different functions superimposed on each other and I'm trying to add radio buttons so that when button1 is selected, the function associated with it will draw, and the others will be invisible.
If there is a better way to do this, I'll do that.
import java.awt.*;
import java.awt.geom.Path2D;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.*;
public class DrawingStuff extends JComponent {
DrawingStuff(){
JRadioButton line1 = new JRadioButton("F(x)");
JRadioButton line2 = new JRadioButton("G(x)");
JRadioButton line3 = new JRadioButton("Cos(2x)");
ButtonGroup bG = new ButtonGroup();
bG.add(line1);
bG.add(line2);
bG.add(line3);
this.setLayout( new FlowLayout());
this.add(line1);
this.add(line2);
this.add(line3);
line1.setSelected(true);
this.setVisible(true);
}
public void paintComponent(Graphics g)
{
//w is x, and h is y (as in x/y values in a graph)
int w = this.getWidth()/2;
int h = this.getHeight()/2;
Graphics2D g1 = (Graphics2D) g;
g1.setStroke(new BasicStroke(2));
g1.setColor(Color.black);
g1.drawLine(0,h,w*2,h);
g1.drawLine(w,0,w,h*2);
g1.drawString("0", w - 7, h + 13);
Graphics2D g2 = (Graphics2D) g;
g2.setStroke(new BasicStroke(2));
g2.setColor(Color.red);
int scale = 4;
//Path2D path1 = new Path2D.Double();
//path1.moveTo(w, h);
Polygon p = new Polygon();
for (int x = 0; x <= 4; x++) {
//path1.lineTo(w+scale*x, h - scale*((x*x*x) + x - 3));
p.addPoint(w+scale*x, h - scale*((x*x*x) + x - 3));
}
//g2.draw(path1);
g2.drawPolyline(p.xpoints, p.ypoints, p.npoints);
Polygon p1 = new Polygon();
//Path2D path2 = new Path2D.Double();
//path2.moveTo(w, h);
for (int x = -10; x <= 10; x++) {
//path2.lineTo(w+scale*x, h - scale * ((x*x*x)/100) - x + 10);
p1.addPoint(w + scale * x, h - scale * ((x*x*x)/100) - x + 10);
}
//g2.draw(path2);
g2.drawPolyline(p1.xpoints, p1.ypoints, p1.npoints);
Path2D path = new Path2D.Double();
for (int i = 0; i < 100; i++) {
double theta = i * 2 * Math.PI / 100;
double r = Math.cos(2 * theta);
double dX = w * r * Math.cos(theta) + w;
double dY = h * r * Math.sin(theta) + h;
if (i == 0) {
path.moveTo(dX, dY);
} else {
path.lineTo(dX, dY);
}
}
path.closePath();
g2.draw(path);
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setSize(800, 600);
frame.setTitle("Graphs");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
DrawingStuff draw = new DrawingStuff();
frame.add(draw);
frame.setVisible(true);
}
}
I'm not sure how to call the buttons from the constructor, and when I attempted to set a function aside for the buttons, they would replicate whenever I would maximize or restore down the window.
I also don't know how to erase a a line once plotted.
Thanks.
I also don't know how to erase a a line once plotted.
The secret is to draw only visible lines in your paintComponent() implementation. To do this, wrap your function in a class that maintains a notional visible field and give that class methods to get and set the attribute.
public void paintComponent(Graphics g) {
…
if (x. getFunctionVisible()) {
g2.drawPolyline(…);
}
}
In this example, VisibleAction uses getSeriesVisible() and setSeriesVisible() to effect a change; you implementation might declare getSeriesVisible() and setSeriesVisible() to effect a change; in contrast, your implementation might define getFunctionVisible() and set getFunctionVisible sVisible().
A relate example is seen here.

Matrix square brackets

I'm using Java Swing and I need to display a matrix with square brackets (normal square bracket like the one we use in math that spans more than one line), the matrix size is not fixed, it depends on the input.
Here is the code I'm using to display the matrix:
public static void printMatrix(String[][] matrix) {
String output = "";
for (int x = 0; x < matrix.length; x++) {
output += Arrays.toString(matrix[x]) + "\n";
}
JOptionPane.showMessageDialog(null, output, "Matrix",
JOptionPane.INFORMATION_MESSAGE);
}
The output:
But I need to have one big connected square bracket as follows:
So I'm searching on how to do this and I found this link https://docs.oracle.com/javase/tutorial/uiswing/components/border.html but it doesn't contain the brackets that I need and also found this https://team.mumie.net/mumie/mathletfactory_lib_apidocs/net/mumie/mathletfactory/display/noc/matrix/MatrixBorder.html#MatrixBorder%28java.awt.Component,%20int%29 but I didn't find any examples on how to use it.
Based on nIcE cOw's answer on one of my above comments, you need to create your own CustomBorder class that extends AbstractBorder and override its paintBorder() method to draw each part of the brackets.
In this case I divided this task in 3 parts, the top / bottom / left & right part of both brackets.
The internalGap variable is the space that should be between the content and the border
Here are some screenshots of how the output looks like:
With 2, 6 and 10 elements
The code that produces the above outputs is:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Insets;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.AbstractBorder;
public class EquationMatrixBorder {
private JPanel pane;
private CustomBorder customBorder;
private static final int ROWS_AND_COLS = 1;
private void displayGUI() {
JFrame frame = new JFrame("Custom Border Example");
customBorder = new CustomBorder(Color.RED, 15, 10);
pane = new JPanel();
pane.setLayout(new GridLayout(ROWS_AND_COLS, ROWS_AND_COLS, 15, 15));
//Used to fill the grid, not relevant to question
Random random = new Random();
for (int i = 0; i < ROWS_AND_COLS; i++) {
for (int j = 0; j < ROWS_AND_COLS; j++) {
int r = 0;
if (j % 2 == 0) {
r = random.nextInt(2);
} else {
r = random.nextInt(2) - 1;
}
pane.add(new JLabel(String.valueOf(r)));
}
}
pane.setBorder(customBorder);
frame.add(pane);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
Runnable runnable = new Runnable() {
#Override
public void run() {
new EquationMatrixBorder().displayGUI();
}
};
EventQueue.invokeLater(runnable);
}
}
class CustomBorder extends AbstractBorder {
private Color color;
private int gap;
private int bracketsTopAndBottom = 10;
private int internalGap;
public CustomBorder(Color color, int gap, int internalGap) {
this.color = color;
this.gap = gap;
this.internalGap = internalGap;
}
#Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
super.paintBorder(c, g, x, y, width, height);
Graphics2D g2d = null;
if (g instanceof Graphics2D) {
g2d = (Graphics2D) g;
g2d.setColor(color);
g2d.setStroke(new BasicStroke(3));
//top part of brackets
g2d.drawLine(x + gap, y + gap, x + gap + bracketsTopAndBottom, (y + gap));
g2d.drawLine(width - x - gap - bracketsTopAndBottom, y + gap, width - gap - x, (y + gap));
//bottom part of brackets
g2d.drawLine(x + gap, height - gap, x + gap + bracketsTopAndBottom, height - gap);
g2d.drawLine(width - x - gap - bracketsTopAndBottom, height - gap, width - gap - x, height - gap);
//left and right part of brackets
g2d.drawLine(x + gap, y + gap, x + gap, height - gap);
g2d.drawLine(width - x - gap, y + gap, width - x - gap, height - gap);
}
}
#Override
public Insets getBorderInsets(Component c) {
return getBorderInsets(c, new Insets(gap, gap, gap, gap));
}
#Override
public Insets getBorderInsets(Component c, Insets insets) {
insets.left = insets.top = insets.right = insets.bottom = gap + internalGap;
return insets;
}
}
Note
I haven't done rows and cols numbers shown in desired output of OP, I'm leaving that out as this question is only related to the square brackets

Determine if circles intersect

I am working on a project where I have to draw 20 circles with random starting points and random sizes. Then I have to determine if any of the circles intersect. If a circle intersects with another, I have to color that circle green. And if the circle does not intersect with another, the color needs to be red. I have all of the code... I think... but when I run it, I still get some circles that should be green, but are red instead. Here is my code. Any help will be greatly appreciated.
import java.awt.Graphics;
import javax.swing.JPanel;
import java.util.Random;
import javax.swing.JFrame;
import java.awt.*;
public class IntersectingCircles extends JPanel
{
private int[] xAxis = new int [20]; // array to hold x axis points
private int[] yAxis = new int [20]; // array to hold y axis points
private int[] radius = new int [20]; // array to hold radius length
public static void main (String[] args)
{
JFrame frame = new JFrame("Random Circles");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add (new IntersectingCircles());
frame.pack();
frame.setVisible(true);
}
public IntersectingCircles()
{
setPreferredSize(new Dimension(1300, 800)); // set window size
Random random = new Random();
for (int i = 0; i < 20; i++)
{
xAxis[i] = random.nextInt(800) + 100;
yAxis[i] = random.nextInt(500) + 100;
radius[i] = random.nextInt(75) + 10;
}
}
public void paintComponent(Graphics g)
{
for (int i = 0; i < 20; i++)
{
int color = 0;
for (int h = 0; h < 20; h++)
{
if(i < h)
{
double x1 = 0, x2 = 0, y1 = 0, y2 = 0, d = 0;
x1 = (xAxis[i] + radius[i]);
y1 = (yAxis[i] + radius[i]);
x2 = (xAxis[h] + radius[h]);
y2 = (yAxis[h] + radius[h]);
d = (Math.sqrt(((x2 - x1) * (x2 - x1)) + ((y2 - y1)*(y2 - y1))));
if (d > radius[i] + radius[h] || d < (Math.abs(radius[i] - radius[h])))
{
color = 0;
}
else
{
color = 1;
break;
}
}
}
if (color == 0)
{
g.setColor(Color.RED);
g.drawOval(xAxis[i], yAxis[i], radius[i] * 2, radius[i] * 2);
}
else
{
g.setColor(Color.GREEN);
g.drawOval(xAxis[i], yAxis[i], radius[i] * 2, radius[i] * 2);
}
}
}
}
In the inside for loop, you are only comparing circles of i index with circles with h index, but only those with i < h, because of the condition:
for (int h = 0; h < 20; h++)
{
if(i < h)
{
...
So, instead you should compare every i circle with every h circle, except if they are the same. You want instead:
for (int h = 0; h < 20; h++)
{
if(i != h) //note the change here
{
...

Nesting for-loop in Order to Create Brick Wall

I am new to programming and this is my first time posting to this site. I am currently working on an assignment which will allow a user to input a number between 1 and 20, and then will create a brick wall based upon the number of brick layers the user entered into the JTextField. I was able to create one row, but I don't really understand nesting statements, and all of the examples I've looked at on the web just confuse me more, so I was wondering if someone could possibly help me to better understand nesting for-loops.
//Package List
import java.awt.*;
import java.applet.*;
import javax.swing.*;
import java.util.*;
import java.awt.event.*;
public class Wall extends JApplet implements KeyListener {
//Component declaration
JLabel directions;
JTextField input;
//Variable declaration
int startX = 50;
int startY = 650;
int width = 50;
int height = 20;
int spacing = 2;
//Method declaration
public void init()
{
getContentPane().setBackground(new Color (128, 128, 128));//Changes backround of JApplet to black
//Set JTextField and JLabel
setLayout (new FlowLayout( ));
directions = new JLabel("Enter in any number between 1 and 20 and then press Enter on your keyboard.");
input = new JTextField ( 10 );
add (directions );
add (input);
//Key listener
addKeyListener( this );
setFocusable( true );
}
//Method declaration
public void paint(Graphics g)
{
super.paint (g);
for (int col=1; col<= 8; col++)
{
// for (int row; row<=20; row++)
{ g.setColor (Color.RED);
g.fillRect (startX, startY, 50, 20);
startX = startX + spacing + width;
}
}
}
//Key event methods
public void keyReleased( KeyEvent ke ){}
public void keyTyped (KeyEvent ke ) {}
public void keyPressed ( KeyEvent ke )
{
int key = ke.getKeyCode ( );
if (key == KeyEvent.VK_ENTER)
{
}
}
You need to calculate the x/y position of the brick based on the current row/col. Now, you could simply initialise these values at the start of each loop and increment as required, or you could use a little maths...
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import javax.swing.JApplet;
import javax.swing.JLabel;
import javax.swing.JTextField;
public class AnotherBrickInTheWall extends JApplet {
//Component declaration
JLabel directions;
JTextField input;
//Variable declaration
int startX = 0;
int startY = 50;
int width = 50;
int height = 20;
int spacing = 2;
//Method declaration
public void init() {
getContentPane().setBackground(new Color(128, 128, 128));//Changes backround of JApplet to black
//Set JTextField and JLabel
setLayout(new FlowLayout());
directions = new JLabel("Enter in any number between 1 and 20 and then press Enter on your keyboard.");
input = new JTextField(10);
add(directions);
add(input);
}
//Method declaration
#Override
public void paint(Graphics g) {
super.paint(g);
for (int row = 0; row < 8; row++) {
int y = startY + (row * (height + spacing));
for (int col = 0; col < 8; col++) {
int x = startX + (col * (width + spacing));
System.out.println(x + "x" + y);
g.setColor(Color.RED);
g.fillRect(x, y, width, height);
}
}
}
}
Now, you should never paint on a component which has components added to, this will cause the painting to appear over the top of the components and end up with all sorts of painting issues.
Instead, create a custom component, extending from something like JPanel and override it's paintComponent method instead and place your custom painting here.
You could then add your controls another JPanel and using a BorderLayout on your applet, add these two panels, the fields in the NORTH position and wall in the CENTER position
Updated
If you wanted to get "really" fancy, you could even adjust the x position based on the current row, for example...
int xOffset = 0;
for (int row = 0; row < 8; row++) {
int y = startY + (row * (height + spacing));
if (row % 2 == 0) {
xOffset = width / 2;
} else {
xOffset = 0;
}
for (int col = 0; col < 8; col++) {
int x = xOffset + (startX + (col * (width + spacing)));
System.out.println(x + "x" + y);
g.setColor(Color.RED);
g.fillRect(x, y, width, height);
}
}
Also, JTextField is has an ActionListener which is triggered when the field is actioned, typically by the user pressing Enter. This means that you shouldn't need the KeyListener.
See How to Use Text Fields for more details.
int x=num //1-20
int step=num/8;
int last_row=num%8;
for(int j=1;j<=step;j++){
int nos=8;
if(j == step && last_step ! = 0)
nos = last_step;
for (int col=1; col<= nos; col++)
{
g.setColor (Color.RED);
g.fillRect (startX, startY, 50, 20);
startX = startX + spacing + width;
startY = startY*j;
}
}
Try this.

Image not showing on JLabel

I've been tasked to make a java replica of Candy Crush Saga.
Right now im quite stuck on the GUI part.
I've decided that each candy will be represented by a JLabel holding the candy icon, and a mouselistener to control the functionality.
What happens is, after i finish running the screen shows, the mouse listeners respond but the image doesn't show, meaning i can press the labels get a response but cannot see the icons. I take this as the labels are on the panel but somehow not visible or the icon is not loaded correctly - although when checking the ImageIcon.toString it shows the path to the file.
Any ideas?
Here is the code:
public class Board extends JPanel {
Candy[][] board;
static final int TILE_SIZE = 55;
static final int TILES_MARGIN = 8;
public Board() {
setFocusable(true);
board = new Candy[13][13];
Candy c;
for (int i = 0; i < 13; i++)
for (int j = 0; j < 13; j++) {
if (i != 0 && i != 1 && j != 0 && j != 1 && i != 11 && i != 12 && j != 11 && j != 12) {
Random rand = new Random();
int randomNum = rand.nextInt((6 - 1) + 1) + 1;
c = new Basic(randomNum, this);
} else {
c = new Basic(0, this);
}
setAt(i, j, c);
}
repaint();
}
public void drawCandy(Graphics g2, Candy candy, int x, int y) {
Graphics2D g = ((Graphics2D) g2);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE);
int value = candy.getClr();
int xOffset = offsetCoors(x);
int yOffset = offsetCoors(y);
ImageIcon myImg = candy.switchIcon();
JLabel toAdd = new JLabel(myImg);
toAdd.setIcon(myImg);
toAdd.setLocation(xOffset,yOffset);
toAdd.setSize(TILE_SIZE,TILE_SIZE);
toAdd.addMouseListener(new ButtonPressed(x,y,candy));
toAdd.setVisible(true);
if (value != 0)
add(toAdd);
}
private static int offsetCoors(int arg) {
return (arg-2) * (TILES_MARGIN + TILE_SIZE) + TILES_MARGIN;
}
public void paint(Graphics g) {
super.paint(g);
removeAll();
requestFocusInWindow();
g.setColor(Color.black);
g.fillRect(0, 0, this.getSize().width, this.getSize().height);
for (int x = 2; x < 11; x++) {
for (int y = 2; y < 11; y++) {
drawCandy(g, board[x][y], x, y);
}
}
validate();
}
and the JFrame :
public Game() {
super("Candy Crush Game");
setDefaultLookAndFeelDecorated(true);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
getContentPane().setLayout(new BorderLayout());
setSize(600, 600);
setResizable(false);
setLocationRelativeTo(null);
this.board = new Board();
this.score = 0;
this.moves = 20;
this.getContentPane().add(board, BorderLayout.CENTER);
setVisible(true);
board.checkSquare(2, 2, 10, 10);
}
I'm quite frustrated, any help will be great!
Instead of overriding paint() method use paintComponent() method for JPanel.
#Overrie
public void paintComponent(Graphics g) {
super.paintComponent(g);
//your custom painting here
}
Read more
Painting in AWT and Swing
paintComponent() vs paint() and JPanel vs Canvas in a paintbrush-type GUI
There might be some issue in reading image icon. My another post might help you.
ImageIcon does not work with me
Instead of creating new JLabel simply change it's icon.

Categories