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.
Related
I was testing an example code that lets people insert their names and the table will fill the name entered along with a seat number.
When the user presses the reserve seat button their name will be added to the table along with the seat number. Everything works except the seat number column. This is my problem I cannot figure out.
int seatNum is set to 1. When the user presses the reserve button, Seat 1 is added to the array list. After that, I wrote to change seatNum to seatNum+1, but this code is ignored. The code will ignore changing the seatNum, which stops the array list from filling, after the code line
seatResArr.set(seatNum, seatElement);.
Can anyone explain how to change the seatNum? If not, please link me a forum with a similar problem as me.
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.NumberFormat;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.JTextField;
public class SeatReservationFrame extends JFrame implements ActionListener {
private JTextField firstNameField; // Holds first name
private JFormattedTextField seatNumField; // Holds seat number
private JLabel tableLabel; // Label for table display
private JLabel seatNumLabel; // Label for seat number
private JLabel firstNameLabel; // Label for first name
private JButton reserveButton; // Triggers seat reservation
private JButton quitButton; // Triggers termination of GUI
private JTable seatStatusTable; // Table tracks seat
reservations
private final static int NUM_SEATS = 5; // Number of seat in reservation system
private static ArrayList<SeatInfo> seatResArr; // ArrayList of Seat objects
/* Constructor creates GUI components and adds GUI components
using a GridBagLayout. */
SeatReservationFrame() {
Object[][] tableVals = new Object[5][2]; // Seat reservation table
String[] columnHeadings = {"Seat Number", "First Name", // Column headings for reservation table
};
GridBagConstraints layoutConst = null; // GUI component layout
// Set frame's title
setTitle("Seat reservation");
// Add 5 seat objects to ArrayList
seatResArr = new ArrayList<SeatInfo>();
seatsAddElements(seatResArr, NUM_SEATS);
// Make all seats empty
seatsMakeEmpty(seatResArr);
// Create seat reservation table
tableLabel = new JLabel("Seat reservation status:");
seatNumLabel = new JLabel("Seat Number:");
firstNameLabel = new JLabel("First Name:");
seatNumField = new JFormattedTextField(NumberFormat.getIntegerInstance());
seatNumField.setEditable(false);
seatNumField.setValue(0);
firstNameField = new JTextField(20);
firstNameField.setEditable(true);
firstNameField.setText("John");
reserveButton = new JButton("Reserve");
reserveButton.addActionListener(this);
quitButton = new JButton("Quit");
quitButton.addActionListener(this);
// Initialize table
seatStatusTable = new JTable(tableVals, columnHeadings);
seatStatusTable.setEnabled(false); // Prevent user input via table
// Add components using GridBagLayout
setLayout(new GridBagLayout());
layoutConst = new GridBagConstraints();
layoutConst.insets = new Insets(10, 10, 1, 0);
layoutConst.fill = GridBagConstraints.HORIZONTAL;
layoutConst.gridx = 0;
layoutConst.gridy = 0;
add(tableLabel, layoutConst);
layoutConst = new GridBagConstraints();
layoutConst.insets = new Insets(1, 10, 0, 0);
layoutConst.fill = GridBagConstraints.HORIZONTAL;
layoutConst.gridx = 0;
layoutConst.gridy = 1;
layoutConst.gridwidth = 4;
add(seatStatusTable.getTableHeader(), layoutConst);
layoutConst = new GridBagConstraints();
layoutConst.insets = new Insets(0, 10, 10, 0);
layoutConst.fill = GridBagConstraints.HORIZONTAL;
layoutConst.gridx = 0;
layoutConst.gridy = 2;
layoutConst.gridwidth = 4;
add(seatStatusTable, layoutConst);
layoutConst = new GridBagConstraints();
layoutConst.insets = new Insets(10, 10, 1, 0);
layoutConst.fill = GridBagConstraints.HORIZONTAL;
layoutConst.gridx = 0;
layoutConst.gridy = 3;
add(seatNumLabel, layoutConst);
layoutConst = new GridBagConstraints();
layoutConst.insets = new Insets(1, 10, 10, 0);
layoutConst.fill = GridBagConstraints.HORIZONTAL;
layoutConst.gridx = 0;
layoutConst.gridy = 4;
add(seatNumField, layoutConst);
layoutConst = new GridBagConstraints();
layoutConst.insets = new Insets(10, 10, 1, 0);
layoutConst.fill = GridBagConstraints.HORIZONTAL;
layoutConst.gridx = 1;
layoutConst.gridy = 3;
add(firstNameLabel, layoutConst);
layoutConst = new GridBagConstraints();
layoutConst.insets = new Insets(1, 10, 10, 0);
layoutConst.fill = GridBagConstraints.HORIZONTAL;
layoutConst.gridx = 1;
layoutConst.gridy = 4;
add(firstNameField, layoutConst);
layoutConst = new GridBagConstraints();
layoutConst.insets = new Insets(0, 10, 10, 5);
layoutConst.fill = GridBagConstraints.HORIZONTAL;
layoutConst.gridx = 4;
layoutConst.gridy = 4;
add(reserveButton, layoutConst);
layoutConst = new GridBagConstraints();
layoutConst.insets = new Insets(0, 5, 10, 10);
layoutConst.fill = GridBagConstraints.HORIZONTAL;
layoutConst.gridx = 5;
layoutConst.gridy = 4;
add(quitButton, layoutConst);
}
/* Called when either button is pressed. */
#Override
public void actionPerformed(ActionEvent event) {
SeatInfo seatElement; // Seat information
String firstName; // First name
int seatNum; // Seat number
// Get source of event (2 buttons in GUI)
JButton sourceEvent = (JButton) event.getSource();
// User pressed the reserve button
if (sourceEvent == reserveButton) {
seatNum = 1;
firstName = firstNameField.getText();
seatElement = new SeatInfo(); // Create new Seat object
seatElement.reserveSeat(firstName);
seatResArr.set(seatNum, seatElement); // Add seat to ArrayList
updateTable(); // Synchronize table with sts ArrayList
seatNum = 4; //!!!!! this code does not work. how can I change the array number?
// Show success dialog
JOptionPane.showMessageDialog(this, "test");
}
else if (sourceEvent == quitButton) {
dispose(); // Terminate program
}
}
/* Updates the reservation information displayed by the table */
public void updateTable() {
final int seatNumCol = 0; // Col num for seat numbers
final int firstNameCol = 1; // Col num for first names
final int lastNameCol = 2; // Col num for last names
final int paidCol = 3; // Col num for amount paid
int i; // Loop index
for (i = 0; i < NUM_SEATS && i < seatResArr.size(); ++i) {
if (seatResArr.get(i).isEmpty()) { // Clear table entries
seatStatusTable.setValueAt(null, i, seatNumCol);
seatStatusTable.setValueAt(null, i, firstNameCol);
}
else { // Update table with content in the seatResArr ArrayList
seatStatusTable.setValueAt(i, i, seatNumCol);
seatStatusTable.setValueAt(seatResArr.get(i).getFirstName(), i, firstNameCol);
}
}
}
/* Makes seats empty */
public static void seatsMakeEmpty(ArrayList<SeatInfo> seatsRes) {
int i; // Loop index
for (i = 0; i < seatsRes.size(); ++i) {
seatsRes.get(i).makeEmpty();
}
}
/* Adds empty seats to ArrayList */
public static void seatsAddElements(ArrayList<SeatInfo> seatsRes, int numSeats) {
int i; // Loop index
for (i = 0; i < numSeats; ++i) {
seatsRes.add(new SeatInfo());
}
}
/* Creates a SeatReservationFrame and makes it visible */
public static void main(String[] args) {
// Creates SeatReservationFrame and its components
SeatReservationFrame myFrame = new SeatReservationFrame();
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myFrame.pack();
myFrame.setVisible(true);
}
}
This is the second class that holds the names entered:
public class SeatInfo {
private String firstName; // First name
// Method to initialize Seat fields
public void reserveSeat(String inFirstName) {
firstName = inFirstName;
}
// Method to empty a Seat
public void makeEmpty() {
firstName = "empty";
}
// Method to check if Seat is empty
public boolean isEmpty() {
return firstName.equals("empty");
}
// Method to print Seat fields
public void printSeatInfo() {
System.out.print(firstName + " ");
}
public String getFirstName() {
return firstName;
}
}
Sorry, I have a hitch to fix, I was able to map a File array with a String array, and now, I want to get a random File from the mapped arraylist to play when a button is clicked, but I don't get it.... It doesn't work...
Here's my code:
private static File[] word =
//Here, I announce the contents of the File array named word, about 50 Files
private String []answer =
//String array to be mapped with File array
//Other swing parameters to be used
private static JLabel sound;
private static JButton check;
private static JTextField spell;
private JButton click;
//Font to be used for all text typed in JTextField
private Font fonty;
//Icon to be displayed when sound is played
JLabel icon = new JLabel (new ImageIcon("C:\\Users\\HP\\Pictures\\Photos\\#010.jpg"));
public Quest1() {
// Mapping of String array to File array
Map<String, File> mapping = new HashMap();
Map<String, File>mpl = new HashMap();
mpl.putAll(mapping);
//Layout for the JFrame set (the class extends JFrame)
setLayout (new BorderLayout());
setContentPane(icon);
fonty = new Font("Script MT Bold", Font.PLAIN, 15);
//JPanel to hold swing components
JPanel hold = new JPanel ();
hold.setLayout(new GridBagLayout());
GridBagConstraints g = new GridBagConstraints();
g.anchor = GridBagConstraints.WEST;
g.gridx = 2;
g.gridy = 1;
g.gridwidth = 2;
g.insets = new Insets(2, 20, 2,2);
sound = new JLabel (new ImageIcon("C:\\Users\\HP\\Downloads\\JLabelSoundImage.jpg"));
sound.setPreferredSize(new Dimension(70,70));
hold.add(sound, g);
click = new JButton ("Play");
click.setFont(fonty);
g.anchor = GridBagConstraints.WEST;
g.gridx = 2;
g.gridy = 5;
g.gridwidth = 2;
g.insets = new Insets(2, 20, 8, 2);
hold.add(click, g);
click.addActionListener (new ActionListener (){
public void actionPerformed (ActionEvent t) {
//Where my Problem lies.... getting a random File from the mapped array list to play when the button is clicked.
List key = new ArrayList (mapping.keySet());
Collections.shuffle(key);
for (Object o: key){
mapping.get(o);
InputStream in = new InputStream(mapping.get(o),(word));
}
}
});
spell = new JTextField (10);
spell.setFont(fonty);
g.anchor = GridBagConstraints.EAST;
g.gridx = 5;
g.gridy = 2;
g.gridwidth = 3;
g.insets = new Insets (2, 2, 2, 20);
hold.add (spell, g);
check = new JButton ("Check my answer");
check.setFont(fonty);
g.anchor = GridBagConstraints.SOUTH;
g.gridx = 8;
g.gridy = 8;
g.gridwidth = 3;
g.insets = new Insets (2, 2, 20, 2);
hold.add (check, g);
check.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent e) {
if (spell.getText().equals(mapping.get(key))) {
String c = "Correct!";
JOptionPane.showMessageDialog(null, c);
}
else {
String d = ("Wrong! the Answer is ") + (mapping.get(key)) ;
JOptionPane.showMessageDialog(null, d);
}
}
});
hold.setVisible(true);
hold.setSize(400,400);
hold.setLocation(50, 50);
hold.setOpaque(false);
add(hold, BorderLayout.CENTER);
}
One problem is not providing the type to your List. This is very risky, so define what type of List it actually is:
List<File> ...
Another problem is mpl.keySet returns a Set, not an ArrayList. You also don't really want to redefine this every time they click the button. Set this Set once, after you've defined your Map.
Set<File> songs = mpl.keySet();
File[] songArray = songs.toArray();
At this point, all you need to do is generate an index and then create a local variable with a reference to the file. This can be done with the Math class.
int index = (int) (Math.random() * songArray.length);
File song = songArray[index];
You may need to add 1 to the index at the end. I don't recall if it will be inclusive or exclusive for all indices.
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'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.
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]);