Need help arranging JTextFields in JFrame - java

I'm making a Sudoku program in java to learn some algorithms so I want the user to be able to input an unsolved Sudoku puzzle. Here is what I have so far that creates 81 (9x9) boxes:
JTextField input[] = new JTextField[80];
for(int i = 0; i <= 79; i++)
{
input[i] = new JTextField();
input[i].setPreferredSize(new Dimension(30,30));
f.getContentPane().add(input[i]);
}
When I run this program though all I get is just one input field. I know that all the text fields and initialized, created and added to the jframe. I know you have to mess this the layout but I'm not sure how to do that. Any help is appropriated.

Use a JPanel with GridLayout.
Also:
JTextField input[] = new JTextField[80];
That's 80 (not 81) text fields.
Update: (sample code)
public class SodokuBoardDemo {
public static void main(String... args) {
SudokuBoard board = new SudokuBoard();
JFrame frame = new JFrame("Sodoku");
frame.add(board);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static class SudokuBoard extends JPanel {
public SudokuBoard() {
setBorder(BorderFactory.createLineBorder(Color.GRAY));
setLayout(new GridLayout(3, 3));
BoardPart input[] = new BoardPart[9];
for (int i = 0; i < 9; i++) {
input[i] = new BoardPart();
add(input[i]);
}
}
public static class BoardPart extends JPanel {
public BoardPart() {
setBorder(BorderFactory.createLineBorder(Color.GRAY));
setLayout(new GridLayout(3, 3));
JTextField input[] = new JTextField[9];
for (int i = 0; i < 9; i++) {
input[i] = new JTextField();
input[i].setPreferredSize(new Dimension(30, 30));
add(input[i]);
}
}
}
}
}

If you are unsure about how to use different Layouts there is a great tutorial on Oracle documents. If you want to brush up on the components themselves you could also check out the tutorial on them. :)
ps: It might be me being too sleepy but it would appear that you have created 80 text fields not 81.

Related

How to setText of 2d array of JTextFIelds using actionlistener?

My assignment is to create 2 JPanels, one for a 2d array, 6 rows of 5 empty JTextFields and another for JButtons that should somewhat resemble an on-screen keyboard. I created the JPanels with the empty JTextFields and JButtons, now I need a way so that when I press a JButton with a letter from the alphabet it will assign that letter to the first available JTextField on the first available row and move one column at a time until the whole row is filled with letters (trying to add letters to a full row should do nothing). I also need to create a backspace button which I have that will remove the last letter (pressing backspace on an empty row should do nothing).
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class Wordle extends JFrame implements ActionListener
{
private JPanel p1;
private JPanel p2;
private JTextField [][] g;
public Wordle()
{
setSize(500,300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
p1 = new JPanel();
p1.setLayout(new GridLayout(6, 5));
g=new JTextField [5][6];
for(int r=0; r<g.length; r++)
{
for(int c=0; c<g[r].length; c++)
{
g[r][c]= new JTextField();
getContentPane().add(g[r][c]);
p1.add(g[r][c]);
}
}
p2 = new JPanel();
p2.setLayout(new GridLayout(4, 7));
JButton a= new JButton("A");
a.addActionListener(this);
p2.add(a);
JButton b= new JButton("B");
b.addActionListener(this);
p2.add(b);
JButton c= new JButton("C");
c.addActionListener(this);
p2.add(c);
JButton d= new JButton("D");
d.addActionListener(this);
p2.add(d);
JButton e= new JButton("E");
e.addActionListener(this);
p2.add(e);
JButton f= new JButton("F");
f.addActionListener(this);
p2.add(f);
JButton g= new JButton("G");
g.addActionListener(this);
p2.add(g);
JButton h= new JButton("H");
h.addActionListener(this);
p2.add(h);
JButton i= new JButton("I");
i.addActionListener(this);
p2.add(i);
JButton j= new JButton("J");
j.addActionListener(this);
p2.add(j);
JButton k= new JButton("K");
k.addActionListener(this);
p2.add(k);
JButton l= new JButton("L");
l.addActionListener(this);
p2.add(l);
JButton m= new JButton("M");
m.addActionListener(this);
p2.add(m);
JButton n= new JButton("N");
n.addActionListener(this);
p2.add(n);
JButton o= new JButton("O");
o.addActionListener(this);
p2.add(o);
JButton p= new JButton("P");
p.addActionListener(this);
p2.add(p);
JButton q= new JButton("Q");
q.addActionListener(this);
p2.add(q);
JButton r= new JButton("R");
r.addActionListener(this);
p2.add(r);
JButton s= new JButton("S");
s.addActionListener(this);
p2.add(s);
JButton t= new JButton("T");
t.addActionListener(this);
p2.add(t);
JButton u= new JButton("U");
u.addActionListener(this);
p2.add(u);
JButton v= new JButton("V");
v.addActionListener(this);
p2.add(v);
JButton w= new JButton("W");
w.addActionListener(this);
p2.add(w);
JButton x= new JButton("X");
x.addActionListener(this);
p2.add(x);
JButton y= new JButton("Y");
y.addActionListener(this);
p2.add(y);
JButton z= new JButton("Z");
z.addActionListener(this);
p2.add(z);
JButton BackSpace= new JButton("<-");
BackSpace.addActionListener(this);
p2.add(BackSpace);
JButton Enter= new JButton("[");
Enter.addActionListener(this);
p2.add(Enter);
this.getContentPane().add(p1,BorderLayout.NORTH);
this.getContentPane().add(p2,BorderLayout.SOUTH);
this.setVisible(true);
}
public void actionPerformed(ActionEvent e) //need help with
{
if(e.getSource().equals("A"))
{
for(int r=0; r<g.length; r++)
{
for(int c=0; c<g[r].length; c++)
{
g[r][c].setText("A");
}
}
}
}
public static void main(String[] args)
{
new Wordle();
}
}
This is my code and my main issue is setting the text in the 2d array of JTextFields using actionlistener, I don't mind doing each if loop for each letter individually as long as it makes sense and works the way I intended it to, btw if you haven't already noticed this is the game "Wordle" I am trying to make, I'm still a newbie programmer and all of this is new to me so some kind of intuitive explanation would be much appreciated.
This line if(e.getSource().equals("A")) is your first issue. It simply will not work because e.getSource() returns an object that will never equal "A".
Instead, you need to first cast the source to the correct object type like so:
public void actionPerformed(ActionEvent e) //need help with
{
JButton clicked = (JButton)e.getSource();
Now we can now get the text from the button using use getText() like this (Although there is a smarter solution we can use down below):
public void actionPerformed(ActionEvent e) //need help with
{
JButton clicked = (JButton)e.getSource();
if(clicked.getText().equals("A")) {
...
The next issue you face is how you store the data, you need to track the current cell using a class variable, rather than just filling up the whole array:
private int row = 0;
private int column = 0;
Then all together the changes might look a bit like this:
//Class variables
private int row = 0;
private int column = 0;
public void actionPerformed(ActionEvent e) //need help with
{
//Cast the event source to a button
JButton clicked = (JButton)e.getSource();
//Handle backspace
if(clicked.getText().equals("<-"))
{
//Decrease the tracking number
column--;
//Make sure that only valid cells are back spaced
if(column < 0)
{
column = 0;
}
//Set the cell to be blank
g[row][column].setText("");
}
//Handle enter
else if(clicked.getText().equals("["))
{
//Add your behaviour here
....
//Finally move to the next row
row++;
}
//Handle the rest of the letter buttons here
else
{
//We don't need `for` loops, we can just directly add the letter from
//the clicked button to the correct place in the array like so
g[row][column].setText(clicked.getText);
//Increment the tracking numbers
column++;
//Move to the next row when the column value is over 5:
if(column > 4)
{
//Move to the next row
row++;
//Reset the column number to 0
column = 0;
}
}
}

Simple Java GUI Interface - Centering

So I was coding a Punnett square applet to automize a few simple biology calculations and output a simple Punnett square visual. For those of you who don't know, a Punnett square is just a device used in Biology to find ratios of a certain genotype in all the possible children. It's relatively simple;and example would be parents Aa and aa would create offspring of Aa, Aa, aa, and aa ( just crossed them). I have implemented this for single and double genes (Aa+Aa; AaBb+AaBb), with single genes being in a 2x2 table and double being in a 4x4 table.
The issue I am having is with my display- What I want is for each item in the 4x4 table to be centered ( they are currently all located to the left of each cell). Additionally, I wanted to find a way to put the parent's genes on the side of the table (so to the left and to the top to indicate each parent).
I am somewhat a novice at GUI, and was struggling to find any help online in regards to this kind of situation, so was wondering whether you could help.
Here is the code for the GUI class:
//Imports
public class GeneticsGUI
{
public static void main(String[] args)
{
JPanel content = new JPanel();
content.setLayout(new BorderLayout());
content.setSize(600, 600);
JTextField parent1 = new JTextField();
JTextField parent2 = new JTextField();
JPanel top = new JPanel(new GridLayout(3,2));
top.add(new JLabel("Parent 1:"));
top.add(parent1);
top.add(new JLabel("Parent 2:"));
top.add(parent2);
JButton submit = new JButton("Calculate");
submit.addActionListener( new ActionListener() {
#Override
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==submit)
{
String p1 = parent1.getText();
String p2 = parent2.getText();
if(p1!=null&&p2!=null&&p1.length()==2&&p2.length()==2)
{
JPanel c2 = new JPanel();
JFrame window = new JFrame("Genetics");
window.add(c2);
window.setContentPane(c2);
window.setSize(600, 400);
window.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
window.setVisible(true);
String[][] mono = Genetics.monohybridPunett(p1, p2);
for(int row = 0; row<2 ; row++)
{
for(int col = 0; col<2; col++)
{
mono[row][col] = " "+ mono[row][col];
}
}
JTable table = new JTable(mono.length,mono.length);
table.setShowGrid(true);
for(int i = 0; i<mono.length; i++)
for(int j = 0; j<mono.length; j++)
table.setValueAt(mono[i][j], i, j);
DefaultTableCellRenderer t = new DefaultTableCellRenderer();
t.setHorizontalTextPosition(DefaultTableCellRenderer.CENTER);
t.setVerticalTextPosition(DefaultTableCellRenderer.CENTER);
table.setSize(300, 300);
table.isCellEditable(0,0);
table.setRowHeight(100);
c2.add(table,BorderLayout.EAST);;
c2.revalidate();
}
else if(p1!=null&&p2!=null&&p1.length()==4&&p2.length()==4)
{
JPanel c2 = new JPanel();
JFrame window = new JFrame("Genetics");
window.add(c2);
window.setContentPane(c2);
window.setSize(600, 500);
window.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
window.setVisible(true);
String[][] di = Genetics.dihybridPunett(p1, p2);
JTable table = new JTable(di.length,di.length);
table.setShowGrid(true);
DefaultTableModel model = new DefaultTableModel(di,new Object[]{"AaBb","AaBb","",""});
table.isCellEditable(0, 0);
table.setModel(model);
table.setRowHeight(100);
table.getColumnModel().getColumn(0).setPreferredWidth(100);
table.getColumnModel().getColumn(1).setPreferredWidth(100);
table.getColumnModel().getColumn(2).setPreferredWidth(100);
table.getColumnModel().getColumn(3).setPreferredWidth(100);
c2.add(table,BorderLayout.CENTER);
c2.revalidate();
}
}
}
});
top.add(submit);
content.add(top, BorderLayout.NORTH);
JFrame window = new JFrame("Genetics");
window.add(content);
window.setContentPane(content);
window.setSize(600,150);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
}
}

Generate JFrames in a loop, naming issue

Beginner Java programmer here. I'm trying to create a card game to learn more about Java. I have an array of names I pulled out a database. For each String in the array I want to create a JPanel and inside JLabels where I will set the name, power, health, etc.
The problem is when I create these in a loop they all have the same name and overwrite each other. Since I read Java doesn't have dynamic Variable names, how do I solve this?
public void loadDatabaseCardElements(ArrayList cards) {
ArrayList<String> buildCards = cards;
int i;
for(i = 0; i != buildCards.size();) {
String var = buildCards.get(0);
//create the Panel etc
JPanel mainHolder = new JPanel();
mainHolder.setLayout(new BoxLayout(mainHolder, BoxLayout.PAGE_AXIS));
JLabel name = new JLabel("Name: " + var);
JLabel powerLabel = new JLabel("Power: ");
JLabel healthLabel = new JLabel("Health: ");
JLabel armorLabel = new JLabel("Armor: ");
JLabel type1Label = new JLabel("Type1");
JLabel type2Label = new JLabel("Type2: ");
JLabel ability1Label = new JLabel("Ability1: ");
JLabel ability2Label = new JLabel("Ability2: ");
JLabel ability3Label = new JLabel("Ability3: ");
JButton card1 = new JButton("Add to deck");
mainHolder.add(name);
mainHolder.add(powerLabel);
mainHolder.add(healthLabel);
mainHolder.add(armorLabel);
mainHolder.add(type1Label);
mainHolder.add(type2Label);
mainHolder.add(ability1Label);
mainHolder.add(ability2Label);
mainHolder.add(ability3Label);
mainHolder.add(card1);
mainHolder.setBorder(BorderFactory.createLineBorder(Color.black));
mainHolder.setPreferredSize( new Dimension( 130, 200 ) );
frame1.add(mainHolder, BorderLayout.WEST);
SwingUtilities.updateComponentTreeUI(frame1);
card1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
preDeck.add(var); //add to another array when clicked
}
});
if (buildCards.size() != 0) {
buildCards.remove(0);
} else {
}
}
}
The reason for overwriting all the panels with same name is due to this part of your code:
int i;
for(i = 0; i != buildCards.size();) {
String var = buildCards.get(0);
You are assigning the first element of your list to each JLabel. This could help you achieve what you need:
for(int i = 0; i < buildCards.size(); i++){
String var = buildCards.get(i);
// Followed by your code
}
set a growable layout for a standard jpanel in the frame and then add a new jpanel to the standard jpanel every time. this should solve the naming problem. if u need access to each panel, you can store them in an array

Adding multiple instances of a JButton to JFrame in grid

The code below is supposed to create and object instance for a specific type (say color) JButton I want to represent in a grid. When I iterate through the for-loop to add the buttons to the jframe it adds nothing. But if I add a single instance variable it will add that. Anybody have an idea?
public class Grid {
protected JButton [][] board;
private JButton player;
private JButton openCell;
private JButton wall;
private JButton closedCell;
public Grid(String [] args) { // args unused
// Instantiation
board = new JButton [6][6];
layout = new String [6][6];
blueCell = new JButton("BLUE CELL");
redCell = new JButton("RED CELL");
greenCell = new JButton("GREEN CELL");
whiteCell = new JButton("WHITE CELL");
// Configuration (add actions later)
// Decoration
blueCell.setBackground(Color.blue);
redCell.setBackground(Color.red);
greenCell.setBackground(Color.green);
whiteCell.setBackground(Color.white);
for (int rows = 0; rows < 6; rows++) {
for (int cols = 0; cols < 6; cols++) {
if ((layout[rows][cols]).equals('*')) {
board[rows][cols] = blueCell;
}
else if ((layout[rows][cols]).equals('.')) {
board[rows][cols] = redCell;
}
else if ((layout[rows][cols]).equals('x')) {
board[rows][cols] = greenCell;
}
else {
board[rows][cols] = whiteCell;
}
}
}
JFrame game = new JFrame();
game.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
game.setLayout(new GridLayout (6, 6));
game.setSize(500, 500);
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board.length; j++) {
if ((board[i][j]).equals(blueCell)) {
grid.add(blueCell);
}
else if ((board[i][j]).equals(redCell)) {
grid.add(redCell);
}
else if ((board[i][j]).equals(greenCell)) {
grid.add(greenCell);
}
else {
grid.add(whiteCell);
}
}
}
grid.setVisible(true);
} // end of constructor
} // end of Grid class
You can add a component to your GUI only once. If you add it to another component, it will be removed from the previous component. You're trying to add the same JButtons several times, and that won't work. Instead you're going to have to create more JButtons. Consider having your buttons share Actions which is allowed.
If you need more help, consider posting compilable code (your current code is not), a small runnable, compilable program that demonstrates your problem, in other words, an sscce.
Edit
You comment:
But don't these count as instances of a JButton not the same JButton? (I don't understand what your answer meant...)
Think of it mathematically... how many JButtons do you create in your code above? Well, this is easy to figure, exactly 4:
blueCell = new JButton("BLUE CELL");
redCell = new JButton("RED CELL");
greenCell = new JButton("GREEN CELL");
whiteCell = new JButton("WHITE CELL");
So, now ask yourself, how many JButtons are you trying to display in your GUI with these four JButtons? If it's four, then you're possibly OK (as long as you use each button), but if it's more, then you're in trouble. From your 6x6 grid, board = new JButton [6][6];, it looks like you're trying to display 36 JButtons, and if this is true, you've got problems.
But again, if still stuck, please consider creating and posting an sscce.

JList - use a vertical scrollbar instead of horizontal with a vertical wrap orientation?

I'm trying to place a JList inside of a JScrollPane and have it alphabetically list the entries in vertical columns like this:
A D G
B E H
C F
However when the JList runs out of space to display more entries, I'd like the JScrollPane to scroll only in the vertical direction.
This works when I use VERTICAL_WRAP. However, it seems like when I use vertical wrap I get a horizontal scrollbar and when I use HORIZONTAL_WRAP I get the scrollbar I want, but the items get placed in an order that I don't like. Can I have my cake and eat it too? Here's a simple example of what I'm trying to do.
This is the closest I could get, but I'd like to be able to scroll vertically while maintaining the vertical alphabetical ordering.
public class ScrollListExample {
static List<String> stringList = new ArrayList<String>();
static {
for (int i = 0; i < 500; i++) {
stringList.add("test" + i);
}
}
public static void main(final String[] args) {
final JFrame frame = new JFrame();
final Container contentPane = frame.getContentPane();
final JList list = new JList(stringList.toArray());
list.setLayoutOrientation(JList.VERTICAL_WRAP);
list.setVisibleRowCount(0);
final JScrollPane scrollPane = new JScrollPane(list);
contentPane.add(scrollPane);
frame.setPreferredSize(new Dimension(800, 400));
frame.pack();
frame.setVisible(true);
}
}
One solution I've though of is:
If the cell size is known I can create a component listener, and listen for a resize event. When that event is triggered I can calculate the desired row count in order to prevent horizontal scrolling. This just seems like a hack, and I'm not sure how it could work with variable sized text components.
I think your solution is just fine, and not a hack at all. Any built-in feature would have to do basically the same thing anyways.
Here's a modification to your example that does what you want.
public class ScrollListExample {
static List<String> stringList = new ArrayList<String>();
static {
for (int i = 0; i < 500; i++) {
stringList.add("test" + i);
}
}
public static void main(final String[] args) {
final JFrame frame = new JFrame();
final Container contentPane = frame.getContentPane();
final JList list = new JList(stringList.toArray());
list.setLayoutOrientation(JList.VERTICAL_WRAP);
final JScrollPane scrollPane = new JScrollPane(list);
contentPane.add(scrollPane);
frame.setPreferredSize(new Dimension(800, 400));
frame.pack();
list.addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
fixRowCountForVisibleColumns(list);
}
});
fixRowCountForVisibleColumns(list);
frame.setVisible(true);
}
private static void fixRowCountForVisibleColumns(JList list) {
int nCols = computeVisibleColumnCount(list);
int nItems = list.getModel().getSize();
// Compute the number of rows that will result in the desired number of
// columns
int nRows = nItems / nCols;
if (nItems % nCols > 0) nRows++;
list.setVisibleRowCount(nRows);
}
private static int computeVisibleColumnCount(JList list) {
// It's assumed here that all cells have the same width. This method
// could be modified if this assumption is false. If there was cell
// padding, it would have to be accounted for here as well.
int cellWidth = list.getCellBounds(0, 0).width;
int width = list.getVisibleRect().width;
return width / cellWidth;
}
}
Is this what you're going for? (Might need to change the preferred size...)
public class ScrollListExample {
static List<String> stringList = new ArrayList<String>();
static {
for (int i = 0; i < 500; i++) {
stringList.add("test" + i);
}
}
public static void main(final String[] args) {
final JFrame frame = new JFrame();
final Container contentPane = frame.getContentPane();
final JList list = new JList(stringList.toArray());
final JScrollPane scrollPane = new JScrollPane(list);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
contentPane.add(scrollPane);
frame.setPreferredSize(new Dimension(200,200));
frame.pack();
frame.setVisible(true);
}
}
Brilliant Code #Kevin K... I suggest a small modification to avoid ArithmeticException (Divide by zero)
private int computeVisibleColumnCount(JList list)
{
int cellWidth = list.getCellBounds(0, 0).width;
int width = list.getVisibleRect().width;
return width == 0 ? 1 : width / cellWidth;
}

Categories