I'm a beginning Java student and I'm trying to either randomly change the position of JPanels within a JFrame or randomly change the label in the JPanel. I managed to get a grid to randomly change colors and thought I would try to make something like the changing 1s and 0s at the beginning of the Matrix movie. So far I'm unable to achieve the desired results and would like some help. In my code I have the random color changer (I know it's not what I need, but I'm assuming I need to add correct code to the Action Listener).
Here's what I have:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Random;
public class MatrixGrid extends JFrame {
final int grid = 20;
final int pnlCnt = grid * grid;
final JFrame frame = new JFrame("WELCOME TO THE MATRIX");
final JPanel[] panels = new JPanel[pnlCnt];
Timer t;
public MatrixGrid() {
for (int i = 0; i < panels.length; i++) {
final String[] labels = new String[]{"0", "1"};
Random rand = new Random();
int index = rand.nextInt(labels.length);
String randomTitle = labels[index];
JLabel label = new JLabel(randomTitle, JLabel.CENTER);
label.setForeground(Color.green);
label.setVerticalAlignment(JLabel.CENTER);
panels[i] = new JPanel();
panels[i].setBackground(Color.BLACK);
panels[i].add(label);
frame.getContentPane().add(panels[i]);
}
frame.setLayout(new GridLayout(grid,grid));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setExtendedState(java.awt.Frame.MAXIMIZED_BOTH);
frame.setVisible(true);
//I know this won't do what I want, but I think this is where I need
//to add code to randomize the panels or labels
ActionListener action = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < panels.length; i++) {
Color mix = new Color(255,255,255);
Random random = new Random();
int r = random.nextInt(255);
int g = random.nextInt(255);
int b = random.nextInt(255);
if(mix != null)
{
r = (r + mix.getRed()) / 2;
g = (g + mix.getGreen()) / 2;
b = (b + mix.getBlue()) / 2;
}
Color color = new Color(r, g, b);
panels[i].setBackground(color);
}
}
};
t = new Timer(100, action);
t.setRepeats(true);
t.start();
}
public static void main(String args[]) {
MatrixGrid q = new MatrixGrid();
}
}
Could someone point me in the right direction? I've googled until my eyes are about to fall out of my head. Any help would be very much appreciated. Cheers
I dont know if i did what You want.
I changed the for in the constructor:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Random;
public class NewClass extends JFrame {
final int grid = 20;
final int pnlCnt = grid * grid;
final JFrame frame = new JFrame("WELCOME TO THE MATRIX");
final JPanel[] panels = new JPanel[pnlCnt];
Timer t;
public NewClass() {
for (int i = 0; i < panels.length; i++) {
final String[] labels = new String[]{"0", "1"};
final Random rand = new Random();
int index = rand.nextInt(labels.length);
String randomTitle = labels[index];
final JLabel label = new JLabel(randomTitle, JLabel.CENTER);
Timer lblt = new Timer(00, new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
label.setText(labels[rand.nextInt(labels.length)]);
}
});
lblt.setRepeats(true);
lblt.start();
label.setForeground(Color.green);
label.setVerticalAlignment(JLabel.CENTER);
panels[i] = new JPanel();
panels[i].setBackground(Color.BLACK);
panels[i].add(label);
frame.getContentPane().add(panels[i]);
}
frame.setLayout(new GridLayout(grid, grid));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setExtendedState(java.awt.Frame.MAXIMIZED_BOTH);
frame.setVisible(true);
//I know this won't do what I want, but I think this is where I need
//to add code to randomize the panels or labels
ActionListener action = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < panels.length; i++) {
Color mix = new Color(255, 255, 255);
Random random = new Random();
int r = random.nextInt(255);
int g = random.nextInt(255);
int b = random.nextInt(255);
if (mix != null) {
r = (r + mix.getRed()) / 2;
g = (g + mix.getGreen()) / 2;
b = (b + mix.getBlue()) / 2;
}
Color color = new Color(r, g, b);
panels[i].setBackground(color);
}
}
};
t = new Timer(00, action);
t.setRepeats(true);
t.start();
}
public static void main(String args[]) {
NewClass q = new NewClass();
}
}
Edit: I put the whole code, try to run it and see if it does what You want.
Related
I made a class which takes as parameters 2 dimentions ( n,m ) and a matrix ( mat ). This class makes a JFrame,fills it with buttons colored white(for 1's) or black( for 0's).
The issue is, the matrix being sent is continually changing and i want the button colors to update. If i set the mainframe game = new mainframe(n,m,mat) inside the loop im changing the matrix in,it continually spawns JFrame windows.
I read some stuff on this site that using repaint() or revalidate() could do something like this. I tried putting it in various segments of code but had no luck with it.
The main class is just a loop which calls "mainframe" and updates a matrix in a loop. Here is the class which makes the actual GUI work:
package game;
import java.awt.Color;
public class mainframe extends Jframe {
public mainframe(int n,int m,int mat[][]){
JButton[] buttons = new JButton[n*m];
setSize(600,400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setLayout(new GridLayout(n,m));
for(int i = 0; i<n*m;i++) {
buttons[i] = new JButton();
}
int counter = 0;
for(int j=0;j<n;j++){
for(int k=0;k<m;k++){
if(mat[j][k]==0){
buttons[counter].setBackground(Color.BLACK);
}
add(buttons[counter]);
counter++;
}
}
}
}
Put the setVisible(true); or revalidate(); after you added your components. Better work with the frame content pane.
import javax.swing.*;
import java.awt.*;
class Scratch {
public static void main(String[] args) throws InterruptedException {
JFrame jFrame = new JFrame();
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jFrame.setSize(600, 400);
jFrame.setVisible(true);
for (int i = 5; i < 10; ++i) {
jFrame.setContentPane(createPanel(i, i, new int[i][i]));
jFrame.revalidate();
Thread.sleep(1000);
}
}
public static JPanel createPanel(int n, int m, int[][] mat) {
JButton[] buttons = new JButton[n * m];
JPanel jPanel = new JPanel();
jPanel.setLayout(new GridLayout(n, m));
for (int i = 0; i < n * m; i++) {
buttons[i] = new JButton();
}
for (int j = 0; j < n; j++) {
for (int k = 0; k < m; k++) {
int index = k + k * j;
if (mat[j][k] == 0) {
buttons[index].setBackground(Color.BLACK);
}
jPanel.add(buttons[index]);
}
}
return jPanel;
}
}
package Unit2Exam;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Unit2Exam {
static int r;
static int g;
static int b;
static int rb;
static int rg;
static int on;
static int rr;
static int i;
public static JTextField field1;
public static JTextField field2;
public static JTextField field3;
public static void main(String[] args) {
//This is my constructor for the Math class, it allows me to import methods from that class
//final Math a = new Math();
final Unit2Exam Calculator = new Unit2Exam();
//Makes a font
Font font = new Font("Verdana", Font.PLAIN, 12);
GridBagConstraints grid = new GridBagConstraints();
//This creates the JFRAMES
JFrame frame = new JFrame("Free Fall Application");
//This sets the title
JPanel panel = new JPanel(new GridBagLayout());
//makes and adds the panel
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
grid.fill = GridBagConstraints.BOTH;
JFrame colors = new JFrame("Colors");
JPanel colorPanel = new JPanel(new GridBagLayout());
colors.add(colorPanel);
colors.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
grid.fill = GridBagConstraints.BOTH;
//causes the jbuttons to fill the borders (to make it look better)
grid.weightx = 1;
grid.weighty = 1;
// frame.setSize(new Dimension(200, 200));
frame.setResizable(false);
colors.setResizable(false);
colors.setVisible(true);
colorPanel.setVisible(true);
frame.setVisible(true);
panel.setVisible(true);
//This is where I implement all of the J stuff (i.e. Buttons, Textfields, and JLabels)
JLabel title = new JLabel("Jonathan Kipper");
JLabel label1 = new JLabel("Initial Velocity (m/s):");
JLabel label2 = new JLabel("Time (Seconds):");
JLabel label3 = new JLabel("Distance (meters):");
JTextField field1 = new JTextField(6);
JTextField field2 = new JTextField(6);
JTextField field3 = new JTextField(6);
JButton button1 = new JButton("Calculate");
JButton button2 = new JButton("Clear");
JButton colorButton = new JButton();
grid.gridx = 0;
grid.gridy = 0;
panel.add(title, grid);
title.setVisible(true);
title.setFont(font);
grid.gridx = 0;
grid.gridy = 1;
panel.add(label1, grid);
label1.setVisible(true);
label1.setFont(font);
grid.gridx = 0;
grid.gridy = 2;
panel.add(label2, grid);
label2.setVisible(true);
label2.setFont(font);
grid.gridx = 0;
grid.gridy = 3;
panel.add(label3, grid);
label3.setVisible(true);
label3.setFont(font);
grid.gridx = 1;
grid.gridy = 1;
panel.add(field1, grid);
field1.setVisible(true);
grid.gridx = 1;
grid.gridy = 2;
panel.add(field2, grid);
field2.setVisible(true);
grid.gridx = 1;
grid.gridy = 3;
panel.add(field3, grid);
field3.setText("");
field3.setVisible(true);
grid.gridx = 0;
grid.gridy = 4;
panel.add(button1, grid);
button1.setVisible(true);
grid.gridx = 1;
grid.gridy = 4;
panel.add(button2, grid);
button2.setVisible(true);
button2.setFont(font);
frame.pack();
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
frame.setLocation(dim.width / 2 - frame.getSize().width / 2, dim.height / 2 - frame.getSize().height / 2);
frame.setSize(250, 150);
grid.gridx=0;
grid.gridy=0;
colorPanel.add(colorButton, grid);
colorButton.setText("Click to stop colors");
colorButton.setVisible(true);
colors.pack();
Dimension dimz = Toolkit.getDefaultToolkit().getScreenSize();
colors.setLocation(dimz.width / 3 - frame.getSize().width / 3, dimz.height / 2 - frame.getSize().height / 2);
colors.setSize(200, 150);
i=1;
//Infinite for loop
button1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
double zzz = Calculator.distance();
String za = String.valueOf(zzz);
field3.setText(za);
}
});
button2.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
field1.setText("");
field2.setText("");
field3.setText("");
}
});
colorButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (i == 1) {
colorButton.setText("Click here to start");
i = 0;
} else if (i == 0) {
colorButton.setText("Click here to stop");
i = 1;
}
}
});
on = 0;
r = 0;
g = 0;
b = 0;
rr = 255;
rg = 255;
rb = 255;
//This is the loop for the color changing
while (i != 0) {
//Colors
Color color = new Color(r, g, b);
Color rcolor = new Color(rr, rg, rb);
//Panels
panel.setBackground(color);
frame.setBackground(color);
//Buttons
button1.setBackground(rcolor);
button2.setBackground(rcolor);
colorButton.setBackground(rcolor);
//Labels
label1.setForeground(rcolor);
label2.setForeground(rcolor);
label3.setForeground(rcolor);
title.setForeground(rcolor);
//Text fields
field1.setForeground(rcolor);
field2.setForeground(rcolor);
field3.setForeground(rcolor);
field1.setBackground(color);
field2.setBackground(color);
field3.setBackground(color);
//Sets a slight delay to avoid seizures
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
//Goes through the different colors
if (on == 0) {
if (r == 255) {
on = 1;
} else {
r++;
rr--;
}
} else if (on == 1) {
if (g == 255) {
on = 2;
} else {
g++;
rg--;
}
} else if (on == 2) {
if (b == 255) {
on = 3;
} else {
b++;
rb--;
}
} else if (on == 3) {
if (r == 0) {
on = 4;
} else {
r--;
rr++;
}
} else if (on == 4) {
if (g == 0) {
on = 5;
} else {
g--;
rg++;
}
} else if (on == 5) {
if (b == 0) {
on = 0;
} else {
b--;
rb++;
}
}
}
}
public static double distance(){
String d = field1.getText();
double velocity = Double.parseDouble(d);
String dd = field2.getText();
double time = Double.valueOf(dd);
double totalDistance = (velocity * time) + (4.9 * (time * time));
return totalDistance;
}
}
UPDATE: I can't leave the method as a public static void because it errors out when trying to call it to return a value. I've changed the strings to field.getText(); instead of the String.valueOf(field); It keeps giving me nullpoint errors in the method and when I call the method earlier in the program.
Uhm, you are trying to get the String by
String.valueOf(JTextField)
Thats doing something waaay different from what you want. You can get the Text of the Field by:
e.g. String d = field1.getText();
Edit:
I dont think, Unit2Exam has a purpose, but on your button, you are still using it. First of all, declare distance as static Method:
public static void distance()
Then, replace in your ActionListener
aa.distance()
with
Calculator.distance()
Edit 2:
So, another answer.
First of all, your code is quite messed up, i assume you are new to java. Let me tell you your mistakes:
First of all:
final Unit2Exam Calculator = new Unit2Exam();
Since you have no constructor, you dont need this. Cut it out.
Second:
The reason, why youre field returns null, is because:
JTextField field1 = new JTextField(6);
JTextField field2 = new JTextField(6);
JTextField field3 = new JTextField(6);
creates a local Textfield called field1, which has nothing to do with your global JTextField field1, which stays empty for the rest of its life.
Just remove the "JTextField" before each declaration and it should work:
field1 = new JTextField(6);
field2 = new JTextField(6);
field3 = new JTextField(6);
Final result:
package Unit2Exam;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Unit2Exam {
static int r;
static int g;
static int b;
static int rb;
static int rg;
static int on;
static int rr;
static int i;
public static JTextField field1;
public static JTextField field2;
public static JTextField field3;
public static void main(String[] args) {
//Makes a font
Font font = new Font("Verdana", Font.PLAIN, 12);
GridBagConstraints grid = new GridBagConstraints();
//This creates the JFRAMES
JFrame frame = new JFrame("Free Fall Application");
//This sets the title
JPanel panel = new JPanel(new GridBagLayout());
//makes and adds the panel
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
grid.fill = GridBagConstraints.BOTH;
JFrame colors = new JFrame("Colors");
JPanel colorPanel = new JPanel(new GridBagLayout());
colors.add(colorPanel);
colors.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
grid.fill = GridBagConstraints.BOTH;
//causes the jbuttons to fill the borders (to make it look better)
grid.weightx = 1;
grid.weighty = 1;
// frame.setSize(new Dimension(200, 200));
frame.setResizable(false);
colors.setResizable(false);
colors.setVisible(true);
colorPanel.setVisible(true);
frame.setVisible(true);
panel.setVisible(true);
//This is where I implement all of the J stuff (i.e. Buttons, Textfields, and JLabels)
JLabel title = new JLabel("Jonathan Kipper");
JLabel label1 = new JLabel("Initial Velocity (m/s):");
JLabel label2 = new JLabel("Time (Seconds):");
JLabel label3 = new JLabel("Distance (meters):");
field1 = new JTextField(6);
field2 = new JTextField(6);
field3 = new JTextField(6);
JButton button1 = new JButton("Calculate");
JButton button2 = new JButton("Clear");
JButton colorButton = new JButton();
grid.gridx = 0;
grid.gridy = 0;
panel.add(title, grid);
title.setVisible(true);
title.setFont(font);
grid.gridx = 0;
grid.gridy = 1;
panel.add(label1, grid);
label1.setVisible(true);
label1.setFont(font);
grid.gridx = 0;
grid.gridy = 2;
panel.add(label2, grid);
label2.setVisible(true);
label2.setFont(font);
grid.gridx = 0;
grid.gridy = 3;
panel.add(label3, grid);
label3.setVisible(true);
label3.setFont(font);
grid.gridx = 1;
grid.gridy = 1;
panel.add(field1, grid);
field1.setVisible(true);
grid.gridx = 1;
grid.gridy = 2;
panel.add(field2, grid);
field2.setVisible(true);
grid.gridx = 1;
grid.gridy = 3;
panel.add(field3, grid);
field3.setText("");
field3.setVisible(true);
grid.gridx = 0;
grid.gridy = 4;
panel.add(button1, grid);
button1.setVisible(true);
grid.gridx = 1;
grid.gridy = 4;
panel.add(button2, grid);
button2.setVisible(true);
button2.setFont(font);
frame.pack();
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
frame.setLocation(dim.width / 2 - frame.getSize().width / 2, dim.height / 2 - frame.getSize().height / 2);
frame.setSize(250, 150);
grid.gridx=0;
grid.gridy=0;
colorPanel.add(colorButton, grid);
colorButton.setText("Click to stop colors");
colorButton.setVisible(true);
colors.pack();
Dimension dimz = Toolkit.getDefaultToolkit().getScreenSize();
colors.setLocation(dimz.width / 3 - frame.getSize().width / 3, dimz.height / 2 - frame.getSize().height / 2);
colors.setSize(200, 150);
i=1;
//Infinite for loop
button1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
double zzz = Unit2Exam.distance();
String za = String.valueOf(zzz);
field3.setText(za);
}
});
button2.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
field1.setText("");
field2.setText("");
field3.setText("");
}
});
colorButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (i == 1) {
colorButton.setText("Click here to start");
i = 0;
} else if (i == 0) {
colorButton.setText("Click here to stop");
i = 1;
}
}
});
on = 0;
r = 0;
g = 0;
b = 0;
rr = 255;
rg = 255;
rb = 255;
//This is the loop for the color changing
while (i != 0) {
//Colors
Color color = new Color(r, g, b);
Color rcolor = new Color(rr, rg, rb);
//Panels
panel.setBackground(color);
frame.setBackground(color);
//Buttons
button1.setBackground(rcolor);
button2.setBackground(rcolor);
colorButton.setBackground(rcolor);
//Labels
label1.setForeground(rcolor);
label2.setForeground(rcolor);
label3.setForeground(rcolor);
title.setForeground(rcolor);
//Text fields
field1.setForeground(rcolor);
field2.setForeground(rcolor);
field3.setForeground(rcolor);
field1.setBackground(color);
field2.setBackground(color);
field3.setBackground(color);
//Sets a slight delay to avoid seizures
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
//Goes through the different colors
if (on == 0) {
if (r == 255) {
on = 1;
} else {
r++;
rr--;
}
} else if (on == 1) {
if (g == 255) {
on = 2;
} else {
g++;
rg--;
}
} else if (on == 2) {
if (b == 255) {
on = 3;
} else {
b++;
rb--;
}
} else if (on == 3) {
if (r == 0) {
on = 4;
} else {
r--;
rr++;
}
} else if (on == 4) {
if (g == 0) {
on = 5;
} else {
g--;
rg++;
}
} else if (on == 5) {
if (b == 0) {
on = 0;
} else {
b--;
rb++;
}
}
}
}
public static double distance(){
String d = field1.getText();
double velocity = Double.parseDouble(d);
String dd = field2.getText();
double time = Double.valueOf(dd);
double totalDistance = (velocity * time) + (4.9 * (time * time));
return totalDistance;
}
I change it to
public double distance() {
String d = field1.getText();
double velocity = Double.parseDouble(d);
String dd = field2.getText();
double time = Double.valueOf(dd);
double totalDistance = (velocity * time) + (4.9 * (time * time));
return totalDistance;
}
However I'm still getting a null pointer exception. It changed the error slightly however. It's saying on line 273, which is the:
String d = field1.getText();
is an issue.
I 'm doing a chessboard , my idea is to make an array of JPanels , each box is a JPanel with color, the problem I have , when I make such assignment
" chessboard [ rows ] [columns ] = b" and compile gives me an exception .
Why the assignment gives me an error ?
How I can fix it?
Is the layout grid , should go in the JFrame or JPanel ?
thanks.
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
First Class
public class ChessBoard extends JPanel {
private JPanel[][] chessBoardSquares = new JPanel[8][8];
private final JPanel tile;
public ChessBoard () {
tile = new JPanel();
tile.setLayout(new GridLayout(8, 8));
for (int rows = 0; rows < 8; rows++) {
for (int columns = 0;columns< 8;columns++) {
JPanel b = new JPanel();
chessBoardSquares = new JPanel[rows][columns];
if ((rows+columns +1)%2 == 0){
b.setBackground(Color.WHITE);
chessBoardSquares[rows][columns] = b;
}
tile.add( chessBoardSquares [rows][columns]);
}
}
}
}
main
public class example {
public static void main(String[] args) {
JFrame window = new JFrame();
ChessBoard chessBoard = new ChessBoard();
window.add( chessBoard );
window.setVisible(true);
}
}
You're not filling your array properly.
This
for (int rows = 0; rows < 8; rows++) {
for (int columns = 0;columns< 8;columns++) {
JPanel b = new JPanel();
// ***** this creates a completely new array *******
chessBoardSquares = new JPanel[rows][columns];
should be
for (int rows = 0; rows < 8; rows++) {
for (int columns = 0;columns< 8;columns++) {
JPanel b = new JPanel();
// this assigns a JPanel to an array item
chessBoardSquares[rows][columns] = new JPanel();
Also as an aside, I don't see where you're adding the tile JPanel to your GUI, and you'll want to fix this.
It should be better like this :
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ChessBoard extends JPanel {
private final JPanel[][] tiles = new JPanel[8][8];
public ChessBoard() {
Dimension dims = new Dimension(64, 64);
setLayout(new GridLayout(8, 8));
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
JPanel b = new JPanel();
b.setPreferredSize(dims);
b.setMinimumSize(dims);
if ((i + j + 1) % 2 == 0) {
b.setBackground(Color.WHITE);
} else {
b.setBackground(Color.BLACK);
}
add(b);
tiles[i][j] = b;
}
}
}
public static void main(String[] args) {
JFrame f = new JFrame("Chess");
ChessBoard chessBoard = new ChessBoard();
f.add(chessBoard);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
I am working on a program to generate and solve sudoku puzzles in java using a swing gui. I am having a problem where I use the .setText() method on a JTextField but the text is not updated.
Here is my code:
main class:
package sudoku;
public class SudokuSolver {
public static void main(String[] args) {
GUI gui = new GUI();
gui.setVisible(true);
}
}
GUI class:
package sudoku;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JButton;
import java.awt.Window.Type;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class GUI extends JFrame implements ActionListener {
private JPanel contentPane;
private Puzzle puzzle = new Puzzle();
private Board board = new Board();
private int[][] puzz = new int[9][9];
// GUI Constructor
public GUI() {
// set up window
setResizable(false);
setTitle("Sudoku Solver");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 300, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
// set up button panel
JPanel buttons = new JPanel();
contentPane.add(buttons, BorderLayout.SOUTH);
// set up generate button
JButton genButton = new JButton("Generate");
genButton.setMnemonic('g');
buttons.add(genButton);
genButton.addActionListener(this);
// set up solve button
JButton solveButton = new JButton("Solve");
solveButton.setMnemonic('s');
buttons.add(solveButton);
solveButton.addActionListener(this);
// set up board
contentPane.add(board, BorderLayout.CENTER);
}
// Button listener
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
if (cmd == "Generate") {
// generate puzzle
puzz = puzzle.generate();
} else if (cmd == "Solve") {
// solve puzzle
puzz = puzzle.solve(puzz);
}
// display puzzle on the board
board.fill(puzz);
}
}
Board class:
package sudoku;
import java.awt.Color;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
public class Board extends JPanel {
// 9x9 board sections
private BoardSection nw = new BoardSection();
private BoardSection n = new BoardSection();
private BoardSection ne = new BoardSection();
private BoardSection w = new BoardSection();
private BoardSection c = new BoardSection();
private BoardSection e = new BoardSection();
private BoardSection sw = new BoardSection();
private BoardSection s = new BoardSection();
private BoardSection se = new BoardSection();
// array of sections
private BoardSection[] sections = { nw, n, ne, w, c, e, sw, s, se };
// Board Constructor
public Board() {
// 3x3 grid layout
setLayout(new GridLayout(3, 3));
// border
setBorder(BorderFactory.createLineBorder(Color.BLACK, 2));
// add board sections to board
for (int i = 0; i < sections.length; i++) {
sections[i] = new BoardSection();
add(sections[i]);
}
}
// fill the board with data
public void fill(int[][] data) {
// create data sections
String[][] nwData = new String[3][3];
String[][] nData = new String[3][3];
String[][] neData = new String[3][3];
String[][] wData = new String[3][3];
String[][] cData = new String[3][3];
String[][] eData = new String[3][3];
String[][] swData = new String[3][3];
String[][] sData = new String[3][3];
String[][] seData = new String[3][3];
// break data into data sections
nwData = createSection(data, 0, 0);
nData = createSection(data, 3, 0);
neData = createSection(data, 6, 0);
wData = createSection(data, 0, 3);
cData = createSection(data, 3, 3);
eData = createSection(data, 6, 3);
swData = createSection(data, 0, 6);
sData = createSection(data, 3, 6);
seData = createSection(data, 6, 6);
// fill board section with data section
nw.fillSection(nwData);
n.fillSection(nData);
ne.fillSection(neData);
w.fillSection(wData);
c.fillSection(cData);
e.fillSection(eData);
sw.fillSection(swData);
s.fillSection(sData);
se.fillSection(seData);
}
// split data into 3x3 section with 0,0 starting at x, y then convert to
// string
private String[][] createSection(int[][] data, int x, int y) {
int[][] intSection = new int[3][3];
String[][] strSection = new String[3][3];
// break into section
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
intSection[i][j] = data[i + x][j + y];
}
}
// convert section to string
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
strSection[i][j] = Integer.toString(intSection[i][j]);
}
}
return strSection;
}
}
BoardSection class:
package sudoku;
import java.awt.Color;
import java.awt.GridLayout;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.BorderFactory;
public class BoardSection extends JPanel {
// each square
private JTextField nw = new JTextField();
private JTextField n = new JTextField();
private JTextField ne = new JTextField();
private JTextField w = new JTextField();
private JTextField c = new JTextField();
private JTextField e = new JTextField();
private JTextField sw = new JTextField();
private JTextField s = new JTextField();
private JTextField se = new JTextField();
// array of the squares
private JTextField[] fields = new JTextField[] { nw, n, ne, w, c, e, sw, s,
se };
// Board Section Constructor
public BoardSection() {
// 3x3 grid layout
setLayout(new GridLayout(3, 3));
// border
setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
// add all fields to the board section
for (int i = 0; i < fields.length; i++) {
fields[i] = new JTextField(1);
fields[i].setHorizontalAlignment(JTextField.CENTER);
fields[i].setEditable(false);
add(fields[i]);
}
}
// Display the data on the board
public void fillSection(String[][] data) {
int x = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
fields[x].setText(data[i][j]);
x++;
}
}
}
}
I also have another class called Puzzle where there is a generate() and a solve() method that both return int[][]. I don't believe anything in it is relevant to the problem so I'm omitting it for space.
The problem is with this line is the BoardSection class:
fields[x].setText(data[i][j]);
I am not getting any error messages, however it is not updating the text. I tried replacing data[i][j] with "Z" to see if the problem was the data I was passing but it still doesn't work with just a simple string. I did however try putting the following line in the for loop that is inside the BoardSection constructor method and it DID display.
fields[i].setText("0");
Can anyone explain why it works in the constructor but not when the fillSection() method is called?
Do you mean to only ever fill the first field? You never update the x variable to anything other the 0?
public void fillSection(String[][] data) {
data = new String[3][3];
int x = 0; // This never changes?
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
fields[x].setText(data[i][j]);
}
}
}
You could try...
fields[i * j].setText(data[i][j]);
Or actually modify the x parameter accordingly...
Updated...
The other problem you're having is your shadowing the data variable been passed to your fillSection method...
public void fillSection(String[][] data) {
// Oh look, I've overridden every thing
// you just gave with my own copy of the data!!
data = new String[3][3];
//...
}
Updated...
Don't know if this is related or not, but it's still a problem...
You're String comparison is wrong...== is check to see if the two objects share the same memory space, which is never going to be true for String (in this manner)
if (cmd == "Generate") {
Instead, you should be using String#equals to compare the contents of the objects...
if ("Generate".equals(cmd)) {
This would mean that the puzz is never been updated, so when you pass it to your fields, it is probably blank...
Updated...
Yet another issue ;)
In your Board class, you are defining 9 board sections...
private BoardSection nw = new BoardSection();
private BoardSection n = new BoardSection();
private BoardSection ne = new BoardSection();
private BoardSection w = new BoardSection();
private BoardSection c = new BoardSection();
private BoardSection e = new BoardSection();
private BoardSection sw = new BoardSection();
private BoardSection s = new BoardSection();
private BoardSection se = new BoardSection();
// array of sections
private BoardSection[] sections = {nw, n, ne, w, c, e, sw, s, se};
But in you constructor, you are re-inistalition them (within in the sections array)...
// Board Constructor
public Board() {
//...//
// add board sections to board
for (int i = 0; i < sections.length; i++) {
// Look ma, new Board!!
sections[i] = new BoardSection();
add(sections[i]);
}
}
This means that the BoardSections nw, etc are never actually added to the screen...
Instead, you should simply drop those sections and use the array directly...
public class Board extends JPanel {
// array of sections
private BoardSection[] sections;
// Board Constructor
public Board() {
//...//
// add board sections to board
sections = new BoardSection[9];
for (int i = 0; i < sections.length; i++) {
sections[i] = new BoardSection();
add(sections[i]);
}
}
// fill the board with data
public void fill(int[][] data) {
// create data sections
String[][] nwData = new String[3][3];
String[][] nData = new String[3][3];
String[][] neData = new String[3][3];
String[][] wData = new String[3][3];
String[][] cData = new String[3][3];
String[][] eData = new String[3][3];
String[][] swData = new String[3][3];
String[][] sData = new String[3][3];
String[][] seData = new String[3][3];
// break data into data sections
nwData = createSection(data, 0, 0);
nData = createSection(data, 3, 0);
neData = createSection(data, 6, 0);
wData = createSection(data, 0, 3);
cData = createSection(data, 3, 3);
eData = createSection(data, 6, 3);
swData = createSection(data, 0, 6);
sData = createSection(data, 3, 6);
seData = createSection(data, 6, 6);
// fill board section with data section
sections[0].fillSection(nwData);
sections[1].fillSection(nData);
sections[2].fillSection(neData);
sections[3].fillSection(wData);
sections[4].fillSection(cData);
sections[5].fillSection(eData);
sections[6].fillSection(swData);
sections[7].fillSection(sData);
sections[8].fillSection(seData);
}
Calling setText() only updates the model for the JTextField. In other words, the JTextField stores an internal String with the value which you sent it. However, the view (i.e. what is shown on your screen) is not updated. This is actually a good thing because painting is quite slow. If the UI was updated every time you call setText() in your Sudoku program, it would have to update 81 times.
You can force the view to update by calling invalidate() on any subclass of Component. In your situation, you probably should call invalidate() on the main JFrame or the JPanel that contains all of your JTextFields. This will cause the GUI to refresh once, rather than the 81 times mentioned before.
P.S. For more information, I suggest you research the Model-View-Controller design pattern.
The problem is when I set the background color of the square JPanel as square.setBackground(colors[j]) the square draws only the first color of the list of colors without displaying the other 3. This is my code:
import java.awt.*;
import java.util.*;
import javax.swing.*;
import java.awt.*;
#SuppressWarnings({ "unused", "serial" })
public class RegionPartition extends JFrame
{
JLayeredPane layeredPane;
JPanel regionBoard;
JLabel regionPiece;
private static int DELAY = 200;
private Color[] colors = new Color[]{Color.PINK, Color.GREEN, Color.BLACK, Color.RED};
public RegionPartition()
{
Dimension boardSize = new Dimension(500, 500);
// Use a Layered Pane for this this application
layeredPane = new JLayeredPane();
getContentPane().add(layeredPane);
layeredPane.setPreferredSize(boardSize);
regionBoard = new JPanel();
layeredPane.add(regionBoard, JLayeredPane.DEFAULT_LAYER);
regionBoard.setLayout( new GridLayout(4, 4) );
regionBoard.setPreferredSize( boardSize );
regionBoard.setBounds(0, 0, boardSize.width, boardSize.height);
Random random = new Random();
for (int i = 0; i < 16; i++) {
JPanel square = new JPanel(new BorderLayout());
square.setBorder(BorderFactory.createLineBorder(Color.black));
regionBoard.add( square );
square.setBackground(Color.green);
int j=0;
square.setBackground(colors[j]);
j++;
}
}
{
JPanel panel = new JPanel()
{
Clients[] c = new Clients[128];
Random random = new Random();
private final int SIZE = 450;
private int DELAY = 9999999;
public void paintComponent (Graphics g)
{
super.paintComponent(g);
for (int i=0; i<c.length; i++)
{
int x = ( int ) ( random.nextFloat() * SIZE ) + 10;
int y = ( int ) ( random.nextFloat() * SIZE ) + 10;
g.drawOval( x, y, 10, 10 );
g.fillOval(x, y, 10, 10);
}
for (int j=0; j<DELAY; j++)
{
repaint();
}
}
};
panel.setOpaque(false);
//Set the glass pane in the JFrame
setGlassPane(panel);
//Display the panel
panel.setVisible(true);
}
public static void main(String[] args)
{
JFrame frame = new RegionPartition();
frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE );
frame.pack();
frame.setResizable(true);
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
protected void paintComponent(Graphics g)
{
// TODO Auto-generated method stub
}
}
That is because you are always setting j to 0 on each iteration:
int j=0;
square.setBackground(colors[j]);
j++;
you may want to change j for an i or do a nested loop, that depends on what you really want to do here.
If you want to make all 16 squares have all four colors in a grid like manner, you might want to change your loop to something like:
for (int i = 0; i < 16; i++) {
JPanel square = new JPanel(new GridLayout(2,2));
square.setBorder(BorderFactory.createLineBorder(Color.black));
regionBoard.add( square );
for(int j=0; j<4; ++j){
JPanel insideSquare = new JPanel();
insideSquare.setBackground(colors[j]);
square.add(insideSquare);
}
}
Because you only have 4 colors in your color array, but your loop index exceeds this, you could use:
square.setBackground(colors[ i % colors.length]);
to alternate the colors of your squares.
You are instantiating int j within the scope of your for loop, so its value is not preserved across multiple iterations. You should declare it at a point in your code to allow it scope over your entire for loop.
int j = 0;
<for loop>
square.setBackground(colors[j]);
j++;
<end for>
However, your j is serving the purpose of i in this situation, where i is sufficient as an array index. It would be more correct to remove j entirely and instead do the following:
square.setBackground(colors[i]);