2D array grid - placing character in the middle of each cell - java

having a 2d array of characters that is supposed to represent a map
char test[][]={{'A','B','C'},{'D','E','F'},{'G','H','I'};
how would I create a 3x3 grid using the java.awt library that has each character at the center of each cell?
The code below gives me a a grid but I am still not sure how to put each character at the center of each cell.
int sideLength=115;
int distance=sideLength*3;
int i=0;
int j=0;
for ( int x=90; x<=distance; x+=sideLength )
{
for( int y=30; y<=distance; y+=sideLength )
{
g.drawRect(x,y,sideLength, sideLength);
g.drawString(Character.toString(test[i][j]), sideLength/2, sideLength/2);
}
i++;
j++;
}
This code gives me this output

Nothing but smoke and mirrors...
Okay, JLabels and Borders
import java.awt.Color;
import java.awt.EventQueue;
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.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.MatteBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setBorder(new EmptyBorder(10, 10, 10, 10));
setLayout(new GridLayout(0, 3));
String test[][]={{"A","B","C"},{"D","E","F"},{"G","H","I"}};
Border paddingBorder = new EmptyBorder(50, 50, 50, 50);
for (int row = 0; row < 3; row++) {
for (int col = 0; col < 3; col++) {
JLabel label = new JLabel(test[row][col]);
label.setVerticalAlignment(JLabel.CENTER);
label.setHorizontalAlignment(JLabel.CENTER);
Border edgeBorder = new MatteBorder(
1,
1,
row == 2 ? 1 : 0,
col == 2 ? 1 : 0,
Color.BLACK);
label.setBorder(new CompoundBorder(edgeBorder, paddingBorder));
add(label);
}
}
}
}
}
There's lots of variations on this subject, but it represents the simplest approach
Custom Paint Route...
If, you want to follow a custom paint route, then you're going to need to have a better understanding of how fonts actually work.
I would recommend starting with Working with Text APIs to gain a basic understanding.
Next, you're incrementing your i and j properties correctly. j needs to be reset before you render each column and should increment for each row.
Personally, I'd do it the other way round, where you used the index for each row/column to get the value from the array and then calculate the x/y position based on the current row/column index, but that's just me.
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
String test[][] = {{"A", "B", "C"}, {"D", "E", "F"}, {"G", "H", "I"}};
public TestPane() {
}
#Override
public Dimension getPreferredSize() {
return new Dimension(90 + (115 * 4), 30 + (115 * 4));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int sideLength = 115;
int distance = sideLength * 3;
int i = 0;
for (int x = 90; x <= distance; x += sideLength) {
int j = 0;
for (int y = 30; y <= distance; y += sideLength) {
g.drawRect(x, y, sideLength, sideLength);
FontMetrics fm = g.getFontMetrics();
int yPos = y + ((sideLength - fm.getHeight()) / 2) + fm.getAscent();
int xPos = x + ((sideLength - fm.stringWidth(test[i][j])) / 2);
g.drawString(test[i][j], xPos, yPos);
j++;
}
i++;
}
}
}
}

You're close, but I would refactor your loops slightly. Instead of iterating on distance, iterate on the index in the array. Use the array index to then derive the positions.
char[][] test = {{'A','B','C'}, {'D','E','F'}, {'G','H','I'}};
int sideLength=115;
for (int i = 0; i < test.length; i++) {
int x = 90 + sideLength * i;
for (int j = 0; j < test[j].length; j++) {
int y = 30 + sideLength * j;
g.drawRect(x, y, sideLength, sideLength);
g.drawString(
Character.toString(test[i][j]),
x + sideLength / 2,
y + sideLength / 2);
}
}

Related

Why are JLabels being painted over higher components in a JLayeredPane?

I have a JLayeredPane that has four layers:
JPanel set as a background
Grid of JPanels each holding a JLabel
Grid of JPanels each holding several JLabels that are only set to visible if the label in the panel below is empty
A custom component that is only used to override the paintComponent() method to draw over everything below
For some reason if I change the background colour of the labels in layer 3 and then draw to layer 4, the labels in layer 3 are painted over the graphics painted in level 4. I have tried to set ignoreRepaint() on various components as well as playing around with the opacity and code structure but all to no avail.
Does anyone know how to prevent this from happening?
I won't attach the source code because the project is quite large but I've attached an example that runs as a stand alone program and demonstrates my problem when you hit the "add arrow" button.
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
public class GraphicsTest {
#SuppressWarnings("serial")
class Painter extends JComponent {
public Painter(int x, int y) {
setBounds(0, 0, x, y);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
}
}
private static final int CELL_SIZE = 40;
private static final int NOTE_SIZE = 20;
private JFrame frame;
private static JButton test;
private static JButton clear;
private static JLayeredPane pane = new JLayeredPane();
private static JPanel back = new JPanel();
private static JPanel[][] cellPanels = new JPanel[10][10];
private static JLabel[][] cells = new JLabel[10][10];
private static JPanel[][] notePanels = new JPanel[10][10];
private static JLabel[][][] notes = new JLabel[10][10][4];
private static Painter painter;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
GraphicsTest window = new GraphicsTest();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public GraphicsTest() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setSize(600, 700);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(null);
pane.setBounds(50, 50, 500, 500);
pane.setLayout(null);
frame.getContentPane().add(pane);
back.setBounds(0, 0, 500, 500);
back.setBackground(Color.BLACK);
pane.add(back, new Integer(100));
for (int i = 0; i < 10; i++) {
for (int k = 0; k < 10; k++) {
String text = "";
if ((i % 2) == 1 && (k % 2) == 1) text = (i + k) + "";
cellPanels[i][k] = new JPanel();
cellPanels[i][k].setBounds(k * CELL_SIZE, i * CELL_SIZE, CELL_SIZE, CELL_SIZE);
cellPanels[i][k].setBackground(Color.WHITE);
cellPanels[i][k].setBorder(new LineBorder(Color.BLACK, 1));
cells[i][k] = new JLabel(text);
cells[i][k].setBounds(0, 0, CELL_SIZE, CELL_SIZE);
cells[i][k].setOpaque(false);
cellPanels[i][k].add(cells[i][k]);
pane.add(cellPanels[i][k], new Integer(200));
}
}
boolean display;
for (int i = 0; i < 10; i++) {
for (int k = 0; k < 10; k++) {
if ((i % 2) == 0 && (k % 2) == 0) {
display = true;
} else {
display = false;
}
notePanels[i][k] = new JPanel();
notePanels[i][k].setBounds(k * CELL_SIZE, i * CELL_SIZE, CELL_SIZE, CELL_SIZE);
notePanels[i][k].setBackground(Color.WHITE);
notePanels[i][k].setBorder(new LineBorder(Color.BLACK, 1));
notePanels[i][k].setLayout(null);
for (int m = 0; m < 2; m++) {
for (int p = 0; p < 2; p++) {
notes[i][k][(m * 2) + p] = new JLabel(30 + "");
notes[i][k][(m * 2) + p].setBounds(m * NOTE_SIZE, p * NOTE_SIZE, NOTE_SIZE, NOTE_SIZE);
notes[i][k][(m * 2) + p].setOpaque(true);
notePanels[i][k].add(notes[i][k][(m * 2) + p]);
}
}
if (display) {
notePanels[i][k].setVisible(true);
} else {
notePanels[i][k].setVisible(false);
}
pane.add(notePanels[i][k], new Integer(300));
}
}
painter = new Painter(500, 500);
pane.add(painter, new Integer(400));
test = new JButton("Add Arrow");
test.setBounds(50, 600, 100, 25);
test.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
highlightNotes();
Arrow.drawArrow(painter.getGraphics(), 20, 20, 400, 400, 20, 30, 40, Color.BLACK, Color.GREEN);
}
});
frame.getContentPane().add(test);
clear = new JButton("Clear");
clear.setBounds(175, 600, 100, 25);
clear.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
painter.repaint();
}
});
frame.getContentPane().add(clear);
}
private static void highlightNotes() {
for (int i = 0; i < 10; i++) {
for (int k = 0; k < 10; k++) {
for (int n = 0; n < 4; n++) {
notes[i][k][n].setBackground(Color.BLUE);
}
}
}
}
static class Arrow {
public static void drawArrow(Graphics g, int tailx, int taily, int headx, int heady,
int shaftw, int headw, int headh, Color outline, Color fill) {
if ((shaftw % 2) == 0) {
shaftw--;
}
if ((headw % 2) == 0) {
headw--;
}
if ((headh % 2) == 0) {
headh--;
}
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
double length = Math.sqrt((double) (((headx - tailx) * (headx - tailx))
+ ((heady - taily) * (heady - taily))));
int tailLength = (int) (length - headw) + 1;
double theta = Math.atan2(heady - taily, headx - tailx);
Point point1 = new Point(0, -(shaftw / 2));
point1 = getTransPoint(point1, theta);
point1.x += tailx;
point1.y += taily;
Point point2 = new Point(tailLength, -(shaftw / 2));
point2 = getTransPoint(point2, theta);
point2.x += tailx;
point2.y += taily;
Point point3 = new Point(tailLength, -(headw / 2));
point3 = getTransPoint(point3, theta);
point3.x += tailx;
point3.y += taily;
Point point4 = new Point((int) length, 0);
point4 = getTransPoint(point4, theta);
point4.x += tailx;
point4.y += taily;
Point point5 = new Point(tailLength, (headw / 2));
point5 = getTransPoint(point5, theta);
point5.x += tailx;
point5.y += taily;
Point point6 = new Point(tailLength, (shaftw / 2));
point6 = getTransPoint(point6, theta);
point6.x += tailx;
point6.y += taily;
Point point7 = new Point(0, (shaftw / 2));
point7 = getTransPoint(point7, theta);
point7.x += tailx;
point7.y += taily;
//Create arrow at tail coordinates passed in
Polygon arrow = new Polygon();
arrow.addPoint(point1.x, point1.y);
arrow.addPoint(point2.x, point2.y);
arrow.addPoint(point3.x, point3.y);
arrow.addPoint(point4.x, point4.y);
arrow.addPoint(point5.x, point5.y);
arrow.addPoint(point6.x, point6.y);
arrow.addPoint(point7.x, point7.y);
//Draw and fill the arrow
g2.setColor(fill);
g2.fillPolygon(arrow);
g2.setColor(outline);
g2.drawPolygon(arrow);
}
private static Point getTransPoint(Point point, double theta) {
int x = (int) ((point.x * Math.cos(theta)) - (point.y * Math.sin(theta)));
int y = (int) ((point.y * Math.cos(theta)) + (point.x * Math.sin(theta)));
return new Point(x, y);
}
}
}

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

Multiple graphic objects from method

I had a task to draw checkers board. Here is my frame class
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JTabbedPane;
public class AppFrame extends JFrame {
public AppFrame() {
setTitle("Kółko i kwadracik");
setSize(1000, 1500);
setLocationRelativeTo(null);
initGUI();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void initGUI() {
setLayout(new BorderLayout());
JTabbedPane tabPane = new JTabbedPane();
tabPane.addTab("Plansza", new PlanszaGry());
tabPane.addTab("Obrazek", new PanelZObrazkiem());
tabPane.addTab("Wykres", new Wykres());
tabPane.addTab("Warcaby", new Warcaby());
tabPane.addTab("4 Warcaby", new Warcaby4());
add(tabPane, BorderLayout.CENTER);
}
}
Than a class to create single checkers board, it's the one new Warcaby()
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Stroke;
import java.awt.geom.Line2D;
import javax.swing.JPanel;
public class Warcaby extends JPanel {
public void paint(Graphics g) {
super.paint(g);
setBackground(Color.WHITE);
Graphics2D g2 = (Graphics2D) g;
Stroke defaultStroke = g2.getStroke();
int y = 9; // tu ustawiamy liczbę linii (czyli w sumie wilekość planszy)
// linie planszy do gry
for (int i = 0; i <= y; i++) {
float dash[] = { 10.0f };
Stroke lineStroke = new BasicStroke(3.0f, BasicStroke.CAP_BUTT,
BasicStroke.JOIN_MITER);
g2.setStroke(lineStroke);
g2.setColor(Color.BLACK);
int x = i * 100;
g2.draw(new Line2D.Double(100 + x, 100, 100 + x, 100 * y));// linie
// pionowe
g2.draw(new Line2D.Double(100, 100 + x, 100 * y, 100 + x)); // linie
// poziome
}
// Plansza do gry (czarne/białe pola)
for (int a = 1; a < y; a++) {
if (a % 2 != 0) {
for (int b = 1; b < y; b++) {
if (b % 2 == 0) {
g.setColor(Color.black);
g.fillRect(b * 100, a * 100, 100, 100);
}
}
} else {
for (int b = 1; b < y; b++) {
if (b % 2 != 0) {
g.setColor(Color.black);
g.fillRect(b * 100, a * 100, 100, 100);
}
}
}
}
}
}
My next task is to draw 4 boards next to eachother, teacher gave me a hint to create method drawing one board with information about it's position. I can't figure it out how to even start. I've start with this:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Stroke;
import java.awt.geom.Line2D;
import javax.swing.JPanel;
public class Warcaby4 extends JPanel {
public void Warcaby(Graphics g, int x, int y) {
super.paint(g);
setBackground(Color.WHITE);
Graphics2D g2 = (Graphics2D) g;
Stroke defaultStroke = g2.getStroke();
float dash[] = { 10.0f };
Stroke lineStroke = new BasicStroke(3.0f, BasicStroke.CAP_BUTT,
BasicStroke.JOIN_MITER);
g2.setStroke(lineStroke);
g2.setColor(Color.BLACK);
for (int i = 0; i <= y; i++) {
x = i * 100;
g2.draw(new Line2D.Double(100 + x, 100, 100 + x, 100 * y));// linie
// pionowe
g2.draw(new Line2D.Double(100, 100 + x, 100 * y, 100 + y)); // linie
// poziome
}
// Plansza do gry (czarne/białe pola)
for (int a = 1; a < y; a++) {
if (a % 2 != 0) {
for (int b = 1; b < y; b++) {
if (b % 2 == 0) {
g.setColor(Color.black);
g.fillRect(b * 100, a * 100, 100, 100);
}
}
} else {
for (int b = 1; b < y; b++) {
if (b % 2 != 0) {
g.setColor(Color.black);
g.fillRect(b * 100, a * 100, 100, 100);
}
}
}
}
}
}
Now I don't know where and how call out it 4 times, am I even doing it right? Please give me some suggestions. :)
My next task is to draw 4 boards next to eachother, teacher gave me a hint to create method drawing one board with information about it's position. I can't figure it out how to even start. I've start with this:
Why not just re-use the component you already have? For example, using a GridLayout you could just create as many components as you need...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Insets;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
public class AppFrame {
public static void main(String[] args) {
new AppFrame();
}
public AppFrame() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridLayout(2, 2));
frame.add(new Warcaby());
frame.add(new Warcaby());
frame.add(new Warcaby());
frame.add(new Warcaby());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class Warcaby extends JPanel {
public Warcaby() {
setBackground(Color.WHITE);
setBorder(new EmptyBorder(5, 5, 5, 5));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// setBackground(Color.WHITE);
Graphics2D g2 = (Graphics2D) g;
Insets insets = getInsets();
int horontialPadding = insets.left + insets.right;
int verticalPadding = insets.top + insets.bottom;
int width = getWidth() - horontialPadding;
int height = getHeight() - verticalPadding;
int size = Math.min(width, height) / 10;
int xOffset = insets.left + ((width - (size * 10)) / 2);
int yOffset = insets.top + ((height - (size * 10)) / 2);
for (int vertical = 0; vertical < 10; vertical++) {
for (int horzontial = 0; horzontial < 10; horzontial++) {
int x = horzontial * size;
int y = vertical * size;
g2.setColor(Color.WHITE);
if (vertical % 2 == 0) {
if (horzontial % 2 == 0) {
g2.setColor(Color.BLACK);
}
} else if (horzontial % 2 != 0) {
g2.setColor(Color.BLACK);
}
g2.fillRect(xOffset + x, yOffset + y, size, size);
}
}
g2.setColor(Color.BLACK);
g2.drawRect(xOffset, yOffset, size * 10, size * 10);
}
}
}
Sorry, I optimised your drawing code, now it can resize based on the available space.
Also, you should NEVER update the state of the UI from within any paint method (like calling setBackground), this is a very bad idea which could lead into an infinite paint loop which would consume your CPU cycles and render your system unusable (yes, I've done this)
As a general rule of thumb, you should prefer paintComponent over paint. See Painting in AWT and Swing and Performing Custom Painting for more details
I've managed to finish this task on my own. Here's the code in case someone will have similar problem.
public void paint(Graphics g) {
super.paint(g);
rysujWarcaby((Graphics) g, 50, 50);
rysujWarcaby((Graphics) g, 50, 500);
rysujWarcaby((Graphics) g, 500, 50);
rysujWarcaby((Graphics) g, 500, 500);
}
public void rysujWarcaby(Graphics g, int x, int y) {
int xx = 1;
int nr = 9;
setBackground(Color.YELLOW);
Graphics2D g2 = (Graphics2D) g;
Stroke lineStroke = new BasicStroke(3.0f, BasicStroke.CAP_BUTT,
BasicStroke.JOIN_MITER);
g2.setStroke(lineStroke);
g2.setColor(Color.BLACK);
for (int i = 0; i < nr; i++) {
xx = i * 50;
g2.draw(new Line2D.Double(x + xx, y, xx + x, y + 50 * 8));
g2.draw(new Line2D.Double(x, y + xx, x + 50 * 8, y + xx));
}
}

Java Swing: Issue painting a grid

The program is supposed to run a cellular automata simulation (think Conway's game of life) on a painted grid and has a start/pause button to, well, start/pause the simulation, which runs on a 1 second interval. As far as I can tell, everything else except for painting the grid (processing, rest of the GUI), works fine.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ConcurrentModificationException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class CA_DriverV2 extends JFrame{
private static final Color white = Color.WHITE, black = Color.BLACK;
private Board board;
private JButton start_pause;
public CA_DriverV2(){
board = new Board();
board.setBackground(white);
start_pause = new JButton("Start");
start_pause.addActionListener(board);
this.add(board, BorderLayout.NORTH);
this.add(start_pause, BorderLayout.SOUTH);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setSize(300, 300);
this.setVisible(true);
}
public static void main(String args[]){
new CA_DriverV2();
}
private class Board extends JPanel implements ActionListener{
private final Dimension DEFAULT_SIZE = new Dimension(5, 5);
private final int DEFAULT_CELL = 10, DEFAULT_INTERVAL = 1000, DEFAULT_RATIO = 60;
private Dimension board_size;
private int cell_size, interval, fill_ratio;
private boolean run;
private Timer timer;
private Color[][] grid;
public Board(){
board_size = DEFAULT_SIZE;
cell_size = DEFAULT_CELL;
interval = DEFAULT_INTERVAL;
fill_ratio = DEFAULT_RATIO;
run = false;
//Initialize grid with random values
//NOTE: Add JOptionPane for option to define fill rate and board size?
//ALT: Have a resize(int h, int w) method to resize grid when needed.
//ALT: Have refill(int r) method to restart with different fill ratio.
grid = new Color[board_size.height][board_size.width];
for (int h = 0; h < board_size.height; h++)
for (int w = 0; w < board_size.width; w++){
int r = (int)(Math.random() * 100);
if (r >= fill_ratio)
grid[h][w] = black;
else grid[h][w] = white;
}
timer = new Timer(interval, this);
}
#Override
public Dimension getPreferredSize(){
return new Dimension(board_size.height, board_size.width);
}
#Override
public void paintComponent(Graphics g){
for (int h = 0; h < board_size.height; h++)
for (int w = 0; w < board_size.width; w++){
try{
if (grid[h][w] == black)
g.setColor(black);
else g.setColor(white);
g.fillRect(h * cell_size, w * cell_size, cell_size, cell_size);
} catch (ConcurrentModificationException cme){}
}
}
public void actionPerformed(ActionEvent e) {
//Timer tick processing
if (e.getSource().equals(timer)){
repaint();
Color[][] newGrid = new Color[board_size.height][board_size.width];
for (int h = 1; h < board_size.height; h++)
for (int w = 1; w < board_size.height; w++) {
int surrounding = 0;
//Count black neighbors
for (int i = -1; i <= 1; i++)
for (int j = -1; j <= 1; j++){
if(i != 0 && j != 0){
try{
if(grid[h + i][w + j] == black)
surrounding++;
} catch(ArrayIndexOutOfBoundsException ae){}
}
}
//Generate next iteration
if (surrounding > 5 || surrounding < 2)
newGrid[h][w] = black;
else newGrid[h][w] = white;
}
for (int h = 1; h < board_size.height; h++){
for (int w = 1; w < board_size.height; w++){
grid[h][w] = newGrid[h][w];
System.out.print(grid[h][w] + " ");
}
System.out.println();
}
System.out.println();
}
//Start-Pause button processing
else if(e.getSource().equals(start_pause)){
if(run){
timer.stop();
start_pause.setText("Pause");
}
else {
timer.restart();
start_pause.setText("Start");
}
run = !run;
}
}
}
}
It prints something at the very top, which looks like a sliver of the initial grid overlayed by a sliver of the button, and the rest is the default grey.
Your board Board variable is added BorderLayout.NORTH not BorderLayout.CENTER, so it only fills the top 5 pixels.
And as per my comment, you should never have code like this in your program:
catch(ArrayIndexOutOfBoundsException ae){}
Not only should you not ignore exceptions, but you shouldn't even catch this type of exceptions. Instead create your for loops with a little care so that they can handle the edges.
Also, don't forget to call the super.paintComponent(g) method in your class's override.

Java draw stairs using drawRect and using inputField for more stairs

I'm a beginner whit Java experience so I hope you can help me.
I want to read the number of steps from a JTextfield. But how can you make the stairs variable?
Graphics g = textP.getGraphics();
int x = 5;
int y = 20;
int width = 10;
int height = 10;
For loop 1 - whil give a drawRect of 6 pieces
for (int i = 0; i < 6; i++) {
g.drawRect(x, y * i, width, height);
}
For loop 2 - whil give a drawRect of 5 pieces
for (int i = 1; i < 6; i++) {
g.drawRect(x + 15, y * i, width, height);
}
For loop 3 - whil give a drawRect of 4 pieces
for (int i = 2; i < 6; i++) {
g.drawRect(x + 30, y * i, width, height);
}
For loop 4 - whil give a drawRect of 3 pieces
for (int i = 3; i < 6; i++) {
g.drawRect(x + 45, y * i, width, height);
}
For loop 5 - whil give a drawRect of 2 pieces
for (int i = 4; i < 6; i++) {
g.drawRect(x + 60, y * i, width, height);
}
For loop 6 - whil give a drawRect of 1 pieces
for (int i = 5; i < 6; i++) {
g.drawRect(x + 75, y * i, width, height);
}
Output (must by an rect ipv *):
*
**
***
****
*****
******
You can do it this way.
JTextField stairs = new JTextField("Enter no. of Stairs");
String noOfStairsStr = stairs.getText();
int noOfStairs = Integer.parseInt(noOfStairsStr);
...
for (int i = 0; i < noOfStairs; i++) { // Use that in the for loop.
Are you expecting something like this
for (int i = 0,k=15; i < 6; i++) {
g.drawRect( ( x+(i*k) ), y * i, width, height);
}
A Graphic environment is complex thing. No longer do you have the safety of fixed character width and heights, now you need to start dealing with a wider range of environmental factors (such as the width and height of the area you have to paint in...)
To get start I would suggest you take a look at
Creating a GUI with Swing
Performing custom painting
2D Graphics
To cover the basics.
In order to paint steps, we need to know (at least) three things.
The number of steps to be painted...
The width of each step
The height of each step.
This example calculates the width and height of the steps as a factor of the width and height of the container it's painting on.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class SimpleSteps {
public static void main(String[] args) {
new SimpleSteps();
}
public SimpleSteps() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JTextField steps;
private StairPane stairPane;
public TestPane() {
setLayout(new BorderLayout());
JPanel options = new JPanel();
steps = new JTextField(10);
JButton create = new JButton("Create");
stairPane = new StairPane();
options.add(new JLabel("Step count: "));
options.add(steps);
options.add(create);
add(stairPane);
add(options, BorderLayout.SOUTH);
create.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String value = steps.getText();
try {
int stepCount = Integer.parseInt(value);
stairPane.setStepCount(stepCount);
} catch (NumberFormatException exp) {
JOptionPane.showMessageDialog(TestPane.this, value + " is not a valid step count", "Error", JOptionPane.ERROR_MESSAGE);
}
}
});
}
}
public class StairPane extends JPanel {
private int stepCount = 0;
public StairPane() {
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (stepCount > 0) {
Graphics g2d = (Graphics2D) g.create();
int stepHeight = getHeight() / stepCount;
int stepWidth = getWidth() / stepCount;
for (int step = stepCount; step != 0; step--) {
int width = stepWidth * step;
int y = (stepHeight * step) - stepHeight;
g2d.fillRect(0, y, width, stepHeight);
}
g2d.dispose();
}
}
private void setStepCount(int stepCount) {
this.stepCount = stepCount;
repaint();
}
}
}

Categories