Java Swing Help - java

I'm trying to create a grid of JButtons, with index values to the left and right of the button grid.
Here is my code, but I'm getting a NullPointerException. What is the problem?
public class Test {
public static void main(String args[]) {
JFrame myapp = new JFrame("test");
myapp.setLayout(new FlowLayout());
myapp.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myapp.setSize(400,400);
myapp.setVisible(true);
myapp.getContentPane().add(Board());
}
private static JPanel Board() {
JButton[][] buttons = new JButton [10][10];
JPanel board = new JPanel(new GridLayout(11,11));
String[] rowlabels = {" ","A","B","C","D","E","F","G","H","I","J"};
String[] columnlabels = {" ","1","2","3","4","5","6","7","8","9","10"};
JTextField k;
for (int i = 0; i < 11; i++) {
for (int j = 0; j < 11; j++) {
if ((j != 0) && (i != 0)) {
//myboard[i-1][j-1].addActionListener(new ButtonHandler());
board.add(buttons[i-1][j-1]);
}
if (i == 0) {
if (j != 0) {
// used to display row of numbers
k = new JTextField(columnlabels[j]);
k.setEditable(false);
k.setHorizontalAlignment((int) JFrame.CENTER_ALIGNMENT);
} else {
// used to display column of numbers
k = new JTextField();
k.setEditable(false);
}
board.add(k);
} else if (j == 0) {
k = new JTextField(rowlabels[i]);
k.setEditable(false);
k.setHorizontalAlignment((int) JFrame.CENTER_ALIGNMENT);
board.add(k);
}
}
}
return board;
}
}
I'm probably doing something obvious, but Swing is kind of new to me, so any help would be greatly appreciated.

Swing GUIs should be constructed on the EDT. That part is left as an exercise for the OP.
import java.awt.*;
import javax.swing.*;
public class Test {
public static void main(String args[]) {
JFrame myapp = new JFrame("test");
myapp.setLayout(new FlowLayout());
myapp.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myapp.getContentPane().add(Board());
// very important!
myapp.pack();
// do these last.
myapp.setSize(400,400);
myapp.setVisible(true);
}
private static JPanel Board() {
JButton[][] buttons = new JButton [10][10];
for(int x=0; x<buttons.length; x++) {
for (int y=0; y<buttons[0].length; y++) {
buttons[x][y] = new JButton();
}
}
JPanel board = new JPanel(new GridLayout(11,11));
String[] rowlabels = {" ","A","B","C","D","E","F","G","H","I","J"};
String[] columnlabels = {" ","1","2","3","4","5","6","7","8","9","10"};
JTextField k;
for (int i = 0; i < 11; i++) {
for (int j = 0; j < 11; j++) {
if ((j != 0) && (i != 0)) {
//myboard[i-1][j-1].addActionListener(new ButtonHandler());
board.add(buttons[i-1][j-1]);
}
if (i == 0) {
if (j != 0) {
// used to display row of numbers
k = new JTextField(columnlabels[j]);
k.setEditable(false);
k.setHorizontalAlignment((int) JFrame.CENTER_ALIGNMENT);
} else {
// used to display column of numbers
k = new JTextField();
k.setEditable(false);
}
board.add(k);
} else if (j == 0) {
k = new JTextField(rowlabels[i]);
k.setEditable(false);
k.setHorizontalAlignment((int) JFrame.CENTER_ALIGNMENT);
board.add(k);
}
}
}
return board;
}
}
Given the nature of the GUI, I guess you are after something more like this.
import java.awt.*;
import javax.swing.*;
public class Test {
public static void main(String args[]) {
JFrame myapp = new JFrame("test");
myapp.setLayout(new FlowLayout());
myapp.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myapp.getContentPane().add(Board());
// very important!
myapp.pack();
// do this last.
myapp.setVisible(true);
}
private static JPanel Board() {
JButton[][] buttons = new JButton [10][10];
for(int x=0; x<buttons.length; x++) {
for (int y=0; y<buttons[0].length; y++) {
JButton temp = new JButton();
temp.setPreferredSize(new Dimension(30,30));
buttons[x][y] = temp;
}
}
JPanel board = new JPanel(new GridLayout(11,11));
String[] rowlabels = {" ","A","B","C","D","E","F","G","H","I","J"};
String[] columnlabels = {" ","1","2","3","4","5","6","7","8","9","10"};
JTextField k;
for (int i = 0; i < 11; i++) {
for (int j = 0; j < 11; j++) {
if ((j != 0) && (i != 0)) {
//myboard[i-1][j-1].addActionListener(new ButtonHandler());
board.add(buttons[i-1][j-1]);
}
if (i == 0) {
if (j != 0) {
// used to display row of numbers
k = new JTextField(columnlabels[j]);
k.setEditable(false);
k.setHorizontalAlignment((int) JFrame.CENTER_ALIGNMENT);
} else {
// used to display column of numbers
k = new JTextField();
k.setEditable(false);
}
board.add(k);
} else if (j == 0) {
k = new JTextField(rowlabels[i]);
k.setEditable(false);
k.setHorizontalAlignment((int) JFrame.CENTER_ALIGNMENT);
board.add(k);
}
}
}
return board;
}
}

JButton[][] buttons = new JButton [10][10];
only creates an array of nulls, you have to initialize the buttons. and adding null to panel causes a NPE.

Just tried your code and noticed that you get NPE because you are just creating a buttons array but do not create buttons in it so your buttons array contains null values and when trying to add it in board it throws NPE.
Try something like this after creating array:
private static JPanel Board() {
JButton[][] buttons = new JButton [10][10];
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
buttons[i][j] = new JButton();
}
}
JPanel board = new JPanel(new GridLayout(11,11));
String[] rowlabels = {" ","A","B","C","D","E","F","G","H","I","J"};
String[] columnlabels = {" ","1","2","3","4","5","6","7","8","9","10"};
JTextField k;
// ---- your remaining code.
}

Related

Remembering coordinates for chess game from the inner to outer class

So basically, I want to save all the coordinates of all row numbers that are processed in the actionPerformed method in the ButtonListener class to my Board class in order to move pieces for chess. When I run the program, the inner class ButtonListener saves all the variables which is good. But the variables do not keep the saved values when they are called to my constructor in class Board. I want to keep the values in the variables from the inner class to the outer class.
Edit:Provided the entire class.
public class Board extends JPanel {
Piece movingPiece;
ImageIcon image;
private int row1;
private int col1;
private int row2;
private int col2;
private JButton btn[][];
private Square squares[][];
public Board(String gameType, int row, int col) {
setLayout(new GridLayout(8, 8));
squares = new Square[row][col];
btn = new JButton[row][col];
setUpSquares();
setUpBtns();
setUpChessPieces();
findPieces();
movePiece(row1, col1, row2, col2);// all 0's
}
public void setUpSquares() {
for (int i = 0; i < ChessGame.EIGHT; i++) {
for (int j = 0; j < ChessGame.EIGHT; j++) {
squares[i][j] = new Square();
}
}
}
public void setUpBtns() {
for (int i = 0; i < ChessGame.EIGHT; i++) {
for (int j = 0; j < ChessGame.EIGHT; j++) {
btn[i][j] = new JButton();
add(btn[i][j]);
btn[i][j].addActionListener(new ButtonListener());
if ((i + j) % 2 == 0) {
btn[i][j].setBackground(Color.WHITE);
btn[i][j].setForeground(Color.WHITE);
} else {
btn[i][j].setBackground(Color.DARK_GRAY);
btn[i][j].setForeground(Color.DARK_GRAY);
}
}
}
}
public void movePiece(int row1, int col1, int row2, int col2) {
squares[row1][col1].getPiece().setRow(row2);
squares[row1][col1].getPiece().setCol(col2);
movingPiece = squares[row1][col1].getPiece();
squares[row2][col2].setPiece(movingPiece);
btn[row2][col2].setIcon(new ImageIcon(squares[row2][col2].getPiece().getPieceColor()));
}
/**
* Finds pieces and sets the piece icons to the button.
*/
public void findPieces() {
for (int i = 0; i < ChessGame.EIGHT; i++) {
for (int j = 0; j < ChessGame.EIGHT; j++) {
if (squares[i][j].getPiece() != null) {
btn[i][j].setIcon(new ImageIcon(squares[i][j].getPiece().getPieceColor()));
} else {
btn[i][j].setIcon(null);
}
}
}
}
public void setUpChessPieces() {
// white pieces
for (int i = 0; i < ChessGame.EIGHT; i++) {
Pawn pawn1 = new Pawn(1, i, 1, "white");
squares[1][i].setPiece(pawn1);
}
for (int i = 0; i < ChessGame.EIGHT; i += 7) {
Rook rook1 = new Rook(0, i, 1, "white");
squares[0][i].setPiece(rook1);
}
for (int i = 1; i < ChessGame.EIGHT; i += 5) {
Knight knight1 = new Knight(0, i, 1, "white");
squares[0][i].setPiece(knight1);
}
for (int i = 2; i < ChessGame.EIGHT; i += 3) {
Bishop bishop1 = new Bishop(0, i, 1, "white");
squares[0][i].setPiece(bishop1);
}
King king1 = new King(0, 4, 1, "white");
squares[0][4].setPiece(king1);
Queen queen1 = new Queen(0, 3, 1, "white");
squares[0][3].setPiece(queen1);
// black pieces
for (int i = 0; i < ChessGame.EIGHT; i++) {
Pawn pawn2 = new Pawn(6, i, 2, "black");
squares[6][i].setPiece(pawn2);
}
for (int i = 0; i < ChessGame.EIGHT; i += 7) {
Rook rook2 = new Rook(7, i, 1, "black");
squares[7][i].setPiece(rook2);
}
for (int i = 1; i < ChessGame.EIGHT; i += 5) {
Knight knight2 = new Knight(7, i, 1, "black");
squares[7][i].setPiece(knight2);
}
for (int i = 2; i < ChessGame.EIGHT; i += 3) {
Bishop bishop2 = new Bishop(7, i, 1, "black");
squares[7][i].setPiece(bishop2);
}
King king2 = new King(7, 4, 1, "black");
squares[7][4].setPiece(king2);
Queen queen2 = new Queen(7, 3, 1, "black");
squares[7][3].setPiece(queen2);
}
public class ButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
JButton src = (JButton) e.getSource();
if (src.getBackground() != Color.DARK_GRAY && src.getBackground() != Color.WHITE) {
src.setBackground(src.getForeground());
} else {
src.setBackground(Color.MAGENTA);
}
for (int i = 0; i < ChessGame.EIGHT; i++) {
for (int j = 0; j < ChessGame.EIGHT; j++) {
if (squares[i][j].getPiece() != null) {
if (btn[i][j] == src) {
row1 = i;
col1 = j;
}
}
if (squares[i][j].getPiece() == null) {
if (btn[i][j] == src) {
row2 = i;
col2 = j;
}
}
}
}
System.out.println("row1:" + row1 + " col1:" + col1);
System.out.println("row2:" + row2 + " col2:" + col2);
}
}
}
Your problem is that you are calling the movePiece(int, int, int, int) from the constructor, and 2 buttons have not necessarily been clicked. The listener has been added to each button, but you don't know that the listener has been activated at that point. So, row1, col1, row2, and col2 are all set to the value that ints take when they have not been initiated yet, 0. So, you really want to call the move method from the listener. Something like:
btn[i][j].addActionListener(e -> {
JButton src = (JButton) e.getSource();
//Process src to get row1, col1, row2, and col2 as you did
movePiece(row1, col1, row2, col2);
});
I replaced your ButtonListener class with a lambda expression, but you can leave it as you did. The important part is that you are calling movePiece from the action listener because it ensures that row1, col1, row2, and col2 are all defined.

Adding/Changing variable name with an int or string in Java

I'm new to Java so I'm sure my code is abysmal in comparison to cleaner/organized code.
Link to full code: http://pastebin.com/UXJzU2ax
What it looks like when ran.
Image
I'm attempting to add a number onto the end of a variable via a number in an array. I'm unsure as to how this can be achieved.
I have created a 10x10 grid of buttons with randomly generated colors, I wish to change the adjacent buttons color on click, but only if the color is the same.
Color generation.
int[] squares;
squares = new int[101];
for (int i = 1; i <= 100; i++){
squares[i] = i;
JButton button = new JButton("" + squares[i]);
int color = (int) (Math.random() * 4); //rand 1 to 4
if (color == 1){
button.setBackground(Color.red);
} else if (color == 2){
button.setBackground(Color.green);
} else if (color == 3){
button.setBackground(Color.yellow);
} else {
button.setBackground(Color.blue);
}
button.setName("button" + (Integer.toString(squares[i])));
button.addActionListener(new ActionListener()
{
My way of knowing where directions are.
right = Integer.parseInt(button.getText()) + 1;
up = Integer.parseInt(button.getText()) - 10;
down = Integer.parseInt(button.getText()) + 10;
right2 = squares[right];
up2 = squares[up];
down2 = squares[down];
This is where I'm running into troubles.
if (btnSelectedColor.getBackground() == button.getBackground()){
//Where I need the change in "button", like "button[right].getBackground", or something similar.
if (button.getBackground() == btnSelectedColor.getBackground()){
}
}
Here's how you can access the other buttons.
Note: I will not write all the logic here. I will leave the method of getting the neighbors to you.
In the actionPerformed callback, you need somehting like this:
public void actionPerformed(ActionEvent e)
{
// get all components of the panel
Component[] comp = panel.getComponents();
// loop through all components
for (int i = 0; i < comp.length; i++)
{
// if it's a button...
if (comp[i] instanceof JButton)
{
JButton b = (JButton) comp[i];
// if b is a neighbor of button (e.g. the one clicked),
// then change its background color
// I leave this logic to you (seems like you wrote most if it already)
// Hint: Convert the text of b to an int and convert the
// text of button to an int and compare the ints to see if
// they are neighbors. You can convert the int of
// button.getText once outside of the loop. No sense in
// doing the conversion every time since it will be the same.
}
}
// Rest of code in your actionPerformed method...
}
Good luck!
I would extend JButton
public class BuddyButton extends JButton {
The new BuddyButton would have 4 fields
private BuddyButton north;
private BuddyButton south;
private BuddyButton east;
private BuddyButton west;
Initerate buttons[][]
BuddyButton buttons[][] = new BuddyButton[10][10];
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
BuddyButton buddy = new BuddyButton();
buttons[i][j] = buddy;
panel.add(buddy);
buddy.addActionListener(listener);;
}
}
Loop through buttons[][] again linking all the BuddyButtons
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
BuddyButton buddy = new BuddyButton();
buttons[i][j] = buddy;
panel.add(buddy);
buddy.addActionListener(listener);
}
}
public static void linkBuddies(int i, int j) {
if (i > 0)
buttons[i][j].setNorth(buttons[i - 1][j]);
if (i < 10)
buttons[i][j].setSouth(buttons[i + 1][j]);
if (j > 0)
buttons[i][j].setWest(buttons[i + 1][j - 1]);
if (j > 10)
buttons[i][j].setEast(buttons[i + 1][j + 1]);
}
When a BuddyButton is clicked cast e.getSource() back to a BuddyButton
listener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
BuddyButton buddy = (BuddyButton) e.getSource();
BuddyButton north = buddy.getNorth();
BuddyButton south = buddy.getSouth();
BuddyButton east = buddy.getEast();
BuddyButton west = buddy.getWest();
//Check for nulls and talk to the neighbors!!!!
}};

Sleep or wait time on every call to method from main in Swing class

I coded a Swing class where in the main there is only one call to a method solve(). This method implements a while loop and uses another method in almost every round, this method is called paint() and changes the value of only one JPanel inside of a 9x9 GridLayout, whose reference is stored in a 2D array.
I need a timer inisde paint() so before the panel is modified, 2 seconds pass. It does this the first time is called, but after the 2 seconds it does every round of the loop without waiting. The goal is to watch 2 seconds pass before any panel is modified. I tried using javax Timer. Thread.sleep() doesn't work in a Swing class apparently.
import javax.swing.*;
import javax.swing.Timer;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
import java.util.Stack;
public class SudokuApp {
private JFrame frame;
int i = 9;
int j = 9;
JPanel[][] board = new JPanel[i][j];
JButton nextButton = new JButton("Resolver");
Box[][] sudoku = new Box[9][9];
Box newCurrent = new Box();
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
SudokuApp window = new SudokuApp();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public SudokuApp() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setTitle("Sudoku Solver");
frame.setBounds(100, 100, 510, 555);
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
frame.getContentPane().add(panel, BorderLayout.CENTER);
panel.setLayout(new GridLayout(i, j));
//Initiate board
for (int m = 0; m < i; m++) {
for (int n = 0; n < j; n++) {
board[m][n] = new JPanel();
JTextField textField = new JTextField(1);
textField.setFont(new Font("Lucida Grande", Font.BOLD, 25));
board[m][n].add(textField);
panel.add(board[m][n]);
}
}
Box last = new Box();
for (int m = 0; m < this.i; m++) {
for (int n = 0; n < this.j; n++) {
sudoku[m][n] = new Box(m, n);
if (m != 0 || n != 0) sudoku[m][n].back = last;
last = sudoku[m][n];
}
}
//Solve button action listener
nextButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {
if (validBoard()) {
nextButton.setEnabled(false);
solve();
}
else JOptionPane.showMessageDialog(null, "Condiciones iniciales inválidas.");
} });
frame.getContentPane().add(nextButton, BorderLayout.SOUTH);
}
private boolean validBoard() {
for (int m = 0; m < i; m++) {
for (int n = 0; n < j; n++) {
JTextField current = (JTextField) board[m][n].getComponent(0);
String text = current.getText();
if (text.length() == 1 && !text.contains("0")) {
try {
int number = Integer.parseInt(text);
if (!add(number, m, n)) return false;
current.setEditable(false);
} catch (NumberFormatException e) {
return false;
}
} else {
current.setText("");
current.setEditable(false);
}
}
}
return true;
}
private void solve() {
int i = 0;
int j = 0;
int newI = i + 1;
while (i < 9) {
while (j < 9) {
Box current = sudoku[i][j];
if (current.number == 0) {
HashSet<Integer> possibles = new HashSet<>();
HashSet<Integer> takenNumbers = getTakenNumbers(i, j);
for (int k = 1; k <= 9; k++) if (!takenNumbers.contains(k)) possibles.add(k);
if (possibles.isEmpty()) {
current.number = 0;
erase(i, j);
tryOther(current.back);
i = newCurrent.i;
newI = i + 1;
j = newCurrent.j + 1;
} else {
for (Integer p : possibles) current.possibles.push(p);
current.number = (int) current.possibles.pop();
paint(current.number, i, j);
j++;
newI = i + 1;
}
} else {
j++;
newI = i + 1;
}
}
i = newI;
j = 0;
}
}
private void tryOther(Box box) {
if (box.possibles.empty()) {
if (box.back != null) {
if (!box.initial) {
box.number = 0;
erase(box.i, box.j);
}
tryOther(box.back);
}
else newCurrent = null;
} else {
if (getTakenNumbers(box.i, box.j).contains(box.possibles.peek())) {
box.possibles.pop();
tryOther(box);
}
newCurrent = box;
box.number = (int) box.possibles.pop();
paint(box.number, box.i, box.j);
}
}
private boolean add(int a, int i, int j) {
if (getTakenNumbers(i, j).contains(a)) return false;
sudoku[i][j].number = a;
sudoku[i][j].initial = true;
return true;
}
private void paint(int a, int i, int j) {
JPanel panel = board[i][j];
JTextField jTextField = (JTextField) board[i][j].getComponent(0);
jTextField.setFont(new Font("Lucida Grande", Font.PLAIN, 25));
jTextField.setForeground(Color.gray);
ActionListener task = new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("T");
}
};
Timer timer = new Timer(3000 , task);
timer.setRepeats(false);
timer.start();
jTextField.setText("" + a);
panel.revalidate();
panel.repaint();
}
private void erase(int i, int j) {
JTextField jTextField = (JTextField) board[i][j].getComponent(0);
jTextField.setText("");
board[i][j].revalidate();
board[i][j].repaint();
}
private HashSet<Integer> getTakenNumbers(int i, int j) {
HashSet<Integer> takenNumbers = new HashSet<>();
for (int k = 0; k < 9; k++) if (sudoku[i][k].number != 0 && k != j) takenNumbers.add(sudoku[i][k].number);
for (int k = 0; k < 9; k++) if (sudoku[k][j].number != 0 && k != i) takenNumbers.add(sudoku[k][j].number);
int bigBoxRow = 0;
int bigBoxColumn = 0;
if (i <= 5 && i > 2) bigBoxRow = 3;
if (i <= 8 && i > 5) bigBoxRow = 6;
if (j <= 5 && j > 2) bigBoxColumn = 3;
if (j <= 8 && j > 5) bigBoxColumn = 6;
for (int k = bigBoxRow; k < bigBoxRow + 3; k++) for (int l = bigBoxColumn; l < bigBoxColumn + 3; l++) if (sudoku[k][l].number != 0 && k != i && l != j) takenNumbers.add(sudoku[k][l].number);
return takenNumbers;
}
}
import java.util.Stack;
public class Box {
public int number = 0;
public int i, j;
public Stack possibles = new Stack();
public Box back;
public boolean initial = false;
public Box(int i, int j) {
this.i = i;
this.j = j;
}
public Box() {}
}
You need to change the structure of your program. Specifically, you will want to get rid of the nested while loops within your solve method and instead replace it with a single Swing Timer. That Timer will repeat 9 * 9 times, and will have a counter field inside of it, and inside of it you will want to do the code that you currently do within your nested while loops.
It could look something like...
// TIMER_DELAY could be 2000 if you want a 2 second delay
new Timer(TIMER_DELAY, new ActionListener() {
private int i = 0;
private int j = 0;
#Override
public void actionPerformed(ActionEvent e) {
// MAX_ROWS is 9
if (i == MAX_ROWS) {
// we've iterated through the whole thing
((Timer) e.getSource()).stop();
}
if (j == MAX_ROWS) {
// we've gone through all the columns
i++; // the next row
j = 0; // start at column 0
}
// TODO the code in the nested while loop.
j++;
}
}).start();
For an example of a functioning program that places text in fields with a delay (but doesn't solve anything):
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class SudokuMCVE extends JPanel {
private static final int CLUSTER = 3;
private static final int MAX_ROWS = 9;
private static final float FIELD_PTS = 32f;
private static final int GAP = 3;
private static final Color BG = Color.BLACK;
private static final Color SOLVED_BG = Color.LIGHT_GRAY;
public static final int TIMER_DELAY = 2 * 1000;
private JTextField[][] fieldGrid = new JTextField[MAX_ROWS][MAX_ROWS];
public SudokuMCVE() {
JPanel mainPanel = new JPanel(new GridLayout(CLUSTER, CLUSTER));
mainPanel.setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
mainPanel.setBackground(BG);
JPanel[][] panels = new JPanel[CLUSTER][CLUSTER];
for (int i = 0; i < panels.length; i++) {
for (int j = 0; j < panels[i].length; j++) {
panels[i][j] = new JPanel(new GridLayout(CLUSTER, CLUSTER, 1, 1));
panels[i][j].setBackground(BG);
panels[i][j].setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
mainPanel.add(panels[i][j]);
}
}
for (int row = 0; row < fieldGrid.length; row++) {
for (int col = 0; col < fieldGrid[row].length; col++) {
fieldGrid[row][col] = createField(row, col);
int i = row / 3;
int j = col / 3;
panels[i][j].add(fieldGrid[row][col]);
}
}
setLayout(new BorderLayout());
add(mainPanel, BorderLayout.CENTER);
add(new JButton(new SolveAction("Solve")), BorderLayout.PAGE_END);
}
private JTextField createField(int row, int col) {
JTextField field = new JTextField(2);
field.setHorizontalAlignment(JTextField.CENTER);
field.setFont(field.getFont().deriveFont(Font.BOLD, FIELD_PTS));
return field;
}
private class SolveAction extends AbstractAction {
public SolveAction(String name) {
super(name);
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
new Timer(TIMER_DELAY, new ActionListener() {
private int i = 0;
private int j = 0;
#Override
public void actionPerformed(ActionEvent e) {
// MAX_ROWS is 9
if (i == MAX_ROWS) {
((Timer) e.getSource()).stop();
}
if (j == MAX_ROWS) {
i++;
j = 0;
}
int number = (int) (MAX_ROWS * Math.random()) + 1;
fieldGrid[i][j].setBackground(SOLVED_BG);
fieldGrid[i][j].setText(String.valueOf(number));
j++;
}
}).start();
}
}
private static void createAndShowGui() {
SudokuMCVE mainPanel = new SudokuMCVE();
JFrame frame = new JFrame("SudokuMCVE");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
createAndShowGui();
});
}
}

Movement restriction on GridLayout to only adjacent grid buttons

I am making a game where move across a gridlayout of jbuttons, only allowing movement to adjacent grid jbuttons. The goal is to try and make it to the topleft (From the btm right). I think this is all that is relevant:
//Here is my method to determine whether it is a valid move (i dont want you to be able to move anywhere but adjacent spots
public boolean goodMove(int x, int y) {
int val = Math.abs(current.x - x) + Math.abs(current.y - y);
return val == 1;
}
//Here is the logic in the actionlister, a big if else loop that is now referencing only the jbuttons in my gridlayout (the game panel)
public void actionPerformed(ActionEvent e) {
JButton clicked = (JButton) e.getSource();
if (clicked == SHOWMINES) {
if (SHOWMINES.getText().equals("Show Mines")) {
showMines();
SHOWMINES.setText("Hide Mines");
} else {
hideMines();
}
} else {
if (clicked == NEWGAME) {
newGame();
} else {
if (clicked == SHOWPATH) {
if (SHOWPATH.getText().equals("Show Path")) {
showPath();
SHOWPATH.setText("Hide Path");
} else {
hidePath();
}
} else {
if (clicked == OKAY) {
resetGridSize(Integer.parseInt(gridSizeInput.getText()));
newGame();
} else {
}
int gs = Integer.parseInt(gridSizeInput.getText());
for (int i = 0; i < gs - 1; i++) {
for (int j = 0; j < gs - 1; j++) {
if (clicked == grid[i][j]) {
if (goodMove(i, j)) {//debug tester ,this is where the problem is.
System.out.println("TEST");
current = new Point(i, j);
grid[i][j].setBackground(Color.green);
grid[i][j].setText("=");
}else{System.out.println("TEST2");}
}
}
}
}
}
}
}// end of action listener
Grid[][] is my array of grid buttons, gridSizeInput is the textfield that you can adjust the gridsize in.
Thanks in advance (I'm new to programming, so keep it simple if you can :)
EDIT: I forgot to mention, it is not recognizing my if(goodMove()) loop, its just printing out TWO for my else.
EDIT: My question is why is not working, no buttons will are be recognized as clicked in my grid, I guess I am asking to see if something I have written is glaringly obviously wrong. thanks.
EDIT: Okay here is my entire action listener for all my buttons. This is my first post, sorry I am not more helpful- let me know if anything else I can add.
Your problem may be as simple as your not extending your for loops out far enough. Try changing this:
for (int i = 0; i < gs - 1; i++) {
for (int j = 0; j < gs - 1; j++) {
to this:
for (int i = 0; i < gs; i++) {
for (int j = 0; j < gs; j++) {
Edit
This was the minimal code example that I created to test the concept:
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.*;
import javax.swing.*;
public class Foo extends JPanel {
public static final int GRID_SIZE = 10;
private Point current;
private JButton[][] grid;
public Foo() {
ButtonListener listener = new ButtonListener();
setLayout(new GridLayout(GRID_SIZE, GRID_SIZE));
grid = new JButton[GRID_SIZE][GRID_SIZE];
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[i].length; j++) {
grid[i][j] = new JButton(" ");
grid[i][j].addActionListener(listener);
add(grid[i][j]);
}
}
current = new Point(GRID_SIZE - 1, GRID_SIZE - 1);
}
private class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
JButton clicked = (JButton) e.getSource();
// !! int gs = Integer.parseInt(gridSizeInput.getText());
int gs = GRID_SIZE;
// !! for (int i = 0; i < gs - 1; i++) {
// for (int j = 0; j < gs - 1; j++) {
for (int i = 0; i < gs; i++) {
for (int j = 0; j < gs; j++) {
if (clicked == grid[i][j]) {
if (goodMove(i, j)) {
System.out.println("TEST");
current = new Point(i, j);
grid[i][j].setBackground(Color.green);
grid[i][j].setText("=");
} else {
System.out.println("TEST2");
}
}
}
}
}
}
public boolean goodMove(int x, int y) {
int val = Math.abs(current.x - x) + Math.abs(current.y - y);
return val == 1;
}
private static void createAndShowGui() {
Foo mainPanel = new Foo();
JFrame frame = new JFrame("Foo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

Connecting JFrame to JPanel using JButton, Problems with JTextFields [duplicate]

This question already has an answer here:
Java: GUI - JButton opening new JPanel and reading the JTextFields
(1 answer)
Closed 9 years ago.
My problem is making my Main class and Journal class connect together, in the Main class users will input two variables and click the button to create the table, in the Journal class, it will take the two variables and make it go through a process before they get added into the table so i need JTextField1 as variable a and JTextField2 as variable b.
I used netbeans to create the Main class and my own methods to create the table class please help! Thanks! This is the part of the Main class Netbeans tells me to edit when I right click > Events > Action > Action Performed
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
int data1 = Integer.parseInt(jTextField1.getText());
int data2 = Integer.parseInt(jTextField2.getText());
}
Here is my Code:
package Components;
/**
*
* #author dustinpx2014
*/
import java.awt.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;
public class Journal extends JPanel
{
private JTable table;
private int a;//Number of Students
private int b;// Length of Trip
public Journal()
{
String colN1 = "Date";
String colN2 = "Student";
int c = a*2/b; // Determining # of Journals
int col = c*2; // Creating two columns for every journal(Day and Student)
String[] columnNames = new String[col]; //For Loop: inserting column names
for(int colF = 0; colF < col; colF++)
{
if(colF%2 == 0)
{
columnNames[colF] = colN1;
}
else
{
columnNames[colF] = colN2;
}
}
int row = b; //row = number of days
int d = 1; //day number
int s = 1; //student number
int x = 0; //counter for the # of times students write
int z = 1; // student number(no limit)
int z1 = a/2; // student number 2
int x1 = 0; // counter for the # of times students write 2
int x2 = 0;
int w = 1;
Object[][] data = new Object[row][col];
for (int col1 = 0; col1 < data[0].length; col1++)
{
for (int row1 = 0; row1<data.length; row1++)//goes through the table by column
{
if(d > b) //reseting the date
{
d = 1;
}
if(s > a && x <= 2) //reseting student number and adds count
{
s = 1;
x++;
}
if(z > a)
{
z = 1;
}
if(z1 > a && x1 <= 2)
{
z1 = 1;
x1++;
}
if (w>a)
{
w++;
}
if(col1%2 == 0) //inserts the day
{
data[row1][col1]= "Day " + d;
d++;
}
else if (s!=data[row1][col1])//inserts student number
{
data[row1][col1]= s;
s++;
z++;
w++;
}
for (int col2 = 1; col2 < data[0].length; col2++)
{
for (int row2 = 0; row2<data.length; row2++)//goes through the table by column
{
if(z == data[row2][col2] && col2%2!=0)//checks for repeats and replaces them
{
for (int y = 0; y < col; y++) //checking all columns
{
if (z1 == a/2 && x1 <= 5) //adds count
{
x1++;
}
else if(z1 > a && x1 <= 5)
{
z1 = 1;
x1++;
}
if(z == data[row2][y])
{
data[row2][col2] = z1;
z1++;
w++;
}
}
}
}
}
for (int row3 = 1; row3 < data.length; row3++)
{
for (int col3 = 0; col3<data[0].length; col3++)//goes through the table by rows
{
if(w == data[row3][col3] && col3%2!=0)//checks for repeats and replaces them
{
for(int y2 = 0; y2 < col; y2++)
{
if(
row3<row-1 &&
row3> 1 &&
w==data[row3+1][y2] &&
w==data[row3-1][y2] &&
w==data[row3][y2]
) //checks rows
{
data[row3][col3] = 0;
}
}
}
}
}
}
}
JTable table = new JTable(data, columnNames);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane(table);
add(scrollPane);
}
public JTable getTable() {
return table;
}
private static void gui()
{
JFrame gui = new JFrame();
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gui.setTitle("Journal List");
gui.setSize(700,200);
gui.setLocationRelativeTo(null);
gui.setVisible(true);
gui.add(new Journal());
}
}
Please help add anything or delete anything in my code to make them work, THANK YOU :)
write that over your constrictor
public static void main(String args[]){
Journal is= new Journal();
}
public Journal()
{...}

Categories

Resources