Java GUI - Adding text field - java

I'm not really keen on Java GUI, but am learning as I go. I am in the process of making a very simple and basic Sudoku puzzle. Right now I am just on the basic layout of it.
I wanted to see if there was a simple way of adding a text field to each little rectangle that I have drawn out (81 total rectangles - 9x9 puzzle). So that a user can type something in there.
I am delving into it, but wanted to get the code up here to see if anyone had any tips, cause truth be told, I am mega lost with this.
Here is what I have so far...
import java.awt.*;
import javax.swing.*;
class MyCanvas extends JComponent {
public void paint(Graphics g) {
int coordinateX = 0;
int coordinateY = 0;
// maximum 9 rows
int rows = 9;
int columns = 1;
// make a 9x9 puzzle
while (columns <= rows) {
//for loop to increment the boxes
for (int j = 1; j <= rows; j++) {
// add and assign coordinte x... equivalent to x = x + 30
coordinateX += 30;
// where x and y determine start of the box and 30 determines the size
g.drawRect(coordinateX, coordinateY, 30, 30);
} //end of for loop
//reset the value of x to start a new row
coordinateX = 0;
coordinateY += 30;
columns++;
} //end of while loop
} //end of void paint
} //end of class
public class DrawRect {
public static void main(String[] a) {
JFrame window = new JFrame();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setBounds(100, 100, 500, 500);
window.getContentPane().add(new MyCanvas());
window.setVisible(true);
} // end of void main
} // end of class
Hopefully someone has some pointers that could help me out, cause boy oh boy do I need it. Was kinda thrown into the lion's den without prior knowledge or practice, but I'm trying hard.
Thanks guys!!

You could use a GridLayout(9,9) and an array of arrays of JTextField's
This is, of course, just an example of how I would do it. There are other ways to do this.
Find below a generic example.
Solution
public static void main(String[] args) {
JTextField[][] boxes = new JTextField[9][9];
JFrame frame = new JFrame();
frame.setLayout(new GridLayout(9,9));
frame.setSize(500, 500);
for (int i = 0 ; i < 9 ; i++){
for (int j = 0 ; j < 9 ; j++){
boxes[i][j] = new JTextField("0");
frame.add(boxes[i][j]);
}
}
frame.setVisible(true);
}
Output

Related

GridLayout not proportional to dimensions

I've been doing a CrossWord puzzle in java for a project. However I haven't been able to fix one problem I'm having with drawing the CrossWord into a JPanel
The program takes the data from a 2D array of chars and generates a grid of a custom type of JLabels with it. This is the code:
public void update(Observable o, Object o1) {
if(model.getMatrix() != null){
configurePanel(model.getRows(), model.getCols());
this.add(panel);
this.pack();
this.revalidate();
this.repaint();
}
}
private void configurePanel(int w, int h) {
if (panel!=null){
this.remove(panel);
}
panel = new JPanel();
panel.setBounds(40, 40, w*50, h*50);
panel.setLayout(new GridLayout(w, h));
labels = createLabels(model.getMatrix());
for (int i = 0; i < w; i++){
for(int j = 0; j < h; j++){
panel.add(labels[i][j]);
}
}
}
private CWlabel[][] createLabels(char[][] matrix) {
int w = matrix.length;
int h = matrix[0].length;
labels = new CWlabel[w][h];
for (int i = 0; i < w; i++){
for(int j = 0; j < h; j++){
char c = matrix[i][j];
labels[i][j] = new CWlabel();
labels[i][j].setBorder(BorderFactory.createLineBorder(Color.black));
labels[i][j].setOpaque(true);
if (c != ' '){
labels[i][j].setBackground(Color.white);
} else {
labels[i][j].setBackground(Color.black);
}
}
}
return labels;
}
My main problem is in configurePanel(), where the size of the panel are set proportional to the crossword dimensions, which should ensure every component inside it is perfectly square, however this is not the case as seen here
In the example shown the difference is subtle but still notizable. The strange part its that if I manually replace,
panel.setBounds(40, 40, w*50, h*50);
with,
panel.setBounds(40, 40, 400, 450);
the result appears to be proportional to the amount of rows and columns as shown here
By my count you have 9 rows and 8 columns so calling configurePanel like the following:
configurePanel(model.getRows(), model.getCols());
Is going to result in a width of 450 and a height of 400, but you want a width of 400 and a height of 450. Thus switch around the first and second parameters, like the following:
configurePanel(model.getCols(), model.getRows());
Note: You shouldn't use absolute positioning, it causes many formatting problems down the road (resizing components, adding components, etc.). You should instead use a layout manager with more customization like GridBagLayout or MigLayout.

Adding buttons on a paintComponent drawn shape

My program is consist of two classes(test and paintClass) in different files. In the paintClass class I draw a 5x5 square board by using paintComponent method. I want to add buttons in each small square in the big square. When I run the code I don't get any buttons. I want to have 25(5x5) buttons by using jpanel on a shape drawn by paintComponent. Is this possible? If it is, how I can do it?
EDIT : The problem was the loop. Number had a default value of 0 so the loop didn't work. I defined number at the beginning. It solved the problem. Also one of the invervals were wrong. I changed j = 0 with j = 1.
import javax.swing.*;
import java.awt.*;
public class test
{
public static void main(String[] args)
{
JFrame frame = new JFrame("buttons");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(250,250);
PaintClass paint = new PaintClass();
paint.repaint();
f1.getContentPane().add(paint);
frame.pack();
frame.setVisible(true);
}
}
import javax.swing.*;
import java.awt.*;
public class PaintClass extends JPanel
{
private Graphics g;
private int interval,side,number;
private JButton button;
public PaintClass()
{
number = 5;
button = new JButton();
setLayout(new GridLayout(5,5));
for(int i = 0; i <= number - 1; i++)
{
for(int j = 1; j <= number - 1; j++)
{
button = new JButton();//ADDED
button.setBounds(i * interval, 0, interval, interval);
add(button);
}
button = new JButton();//ADDED
button.setBounds(0, i * interval, interval, interval);
add(button);
}
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
this.repaint();
side = 250;
number = 5;
interval = side / number;
g.drawRect(0,0, side, side);
for(int i = 0; i <= number - 1; i++)
{
for(int j = 0; j <= number - 1; j++)
{
g.drawLine(i * interval, 0, i * interval, side);
}
g.drawLine(0, i * interval, side, i * interval);
}
}
}
Choose one or the other: either add the buttons using the GridLayout, or paint the buttons using paintComponent. If the former, you should a) define the loop constraint (right now it is 0) b) create a new JButton for every loop (your code currently reuses the instance) and c) register the appropriate ActionListener to respond to events. If the latter, you need to register the appropriate listener (like MouseListener) to respond to user generated events.
private int interval,side,number;
Number has a default value of 0.
for(int i = 0; i <= number - 1; i++)
Since number is 0, your loop will never execute.
Once you do this the buttons will be added to the panel but they will cover your custom painting. To see background lines you just need to set the background of the panel to Color.BLACK and then create your GridLayout with a gap between the components. Read the API for the method to use.

Making a grid, how to make each grid have its own int value? JAVA

I want to create a small grid (let's say 2 x 2) where each individual point in the grid (4 points total) will have its own value of integer. I will also want to be able to call on the values of each point by its location. This is because I want each point's integer to be affected by its neighboring points. What is the best way that I can get each point to have its own values and then be able to call upon those values?
I have this so far, which only makes the grid and displays its values. In the end, I will also want to display its neighbors' values in its location. Thanks!
edit: just looking for best approach to solving this problem to guide me in right direction to go about this.
import javax.swing.JFrame;
import javax.swing.JButton;
import java.awt.GridLayout;
public class Grid {
JFrame frame = new JFrame(); // create frame
JButton[][] grid; // name grid
// constructor
public Grid (int width, int length) {
frame.setLayout(new GridLayout(width, length));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
// create grid
grid = new JButton[width][length]; // allocate size
for (int y = 0; y < length; y++) {
for (int x = 0; x < width; x++) {
grid[x][y] = new JButton("value");
frame.add(grid[x][y]);
}
}
}
public static void main (String[] args) {
// DIMENSION
int d = 2;
// LENGTH
int l = 2;
// WIDTH
int w = 2;
new Grid(l,w); // create new Grid with parameters
}
}
Use a nested int array to make a grid.
int[][]grid = new int[2][2];
for(int x=0; x<2;x++){
for(int y=0; y<2; y++){
grid[x][y] = value;
}
}
This will return a grid you can address (call the value of) by calling int val = grid[x][y]

Resizeable Number Triangle in Java GUI

I have this assignment for a Java class I am taking. I was assigned to do this:
Write a program that displays numbers as shown below. The number of lines in the display changes to fit the window as the window resizes.
This is whats displayed in the GUI ( without the large spaces in between lines):
1
12
123
1234
12345
123456
1234567
with the numbers counting larger and the number of lines increasing as I expand the GUI window.
Heres my code that I have now:
import javax.swing.*;
import java.awt.*;
public class ResizingGUI extends JPanel{
public int width = 600;
public int height = 200;
public int x_coord = 10;
public int y_coord = 40;
public static final int point_size = 12;
public Font fontObject = new Font("SansSerif", Font.PLAIN, point_size);
public int maxLines = 16;
public ResizingGUI (){
super();
setSize(width, height);
}
public void paint(Graphics g){
super.paint(g);
g.setFont(fontObject);
x_coord = 10;
y_coord = 40;
int lineCount = 0;
int line = 1;
maxLines = (this.getHeight()-40)/10;
while(lineCount < maxLines){
while(line < maxLines){
String s = String.valueOf(line);
g.drawString(s, x_coord, y_coord);
line++;
x_coord = x_coord + 10;
if(line > 10){
x_coord = x_coord + 5;
}
line = 0;
lineCount++;
y_coord = y_coord + 10;
}
}
}
public static void main(String[]args){
JFrame frame = new JFrame();
frame.setTitle("Resizeable GUI");
frame.setSize (600,200);
frame.getContentPane().add (new ResizingGUI());
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
I think this might be the solution, but the nested loops are throwing me for a loop (hah)
If anyone could please advise on either a way to fix the nested loops or (more likely) how to achieve my goal, I would be very grateful.
Your loops are a little confusing, basically, you want to loop for the number of lines and the loop for the number columns (which is the current line number)...
int line = 0;
while (line < maxLines) {
int col = 0;
while (col < line) {
//...
col++;
}
line++;
}
You're also no resetting the x_coord back to it's initial position, meaning that each new line will start at the end of the last line...just below it.
You should also:
Override paintComponent instead of paint. Take a look at Performing Custom Painting for more details
Override getPreferredSize instead of using setSize. It will work better with the layout managers
Make use of the FontMetrics in order to determine how many pixels you need to adjust for each line/column. Take a look at Measuring Text for more details

Java for loop not completing properly

Ok, so I'm trying to add an array of 64 JButtons to a JFrame with and 8 by 8 grid layout (chess board type thing). Here's the relevant code section:
public class othello implements ActionListener{
int [][] board = new int[8][8];
JFrame window = new JFrame();
JButton[] buttons = new JButton[64];
public othello(){
window.setSize(400,400);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setLayout(new GridLayout(8,8));
window.setVisible(true);
for (int i=0;i<64;i++){
buttons[i] = new JButton("");
buttons[i].addActionListener(this);
window.add(buttons[i]);
}
for (int i=0;i<8;i++){
for (int j=0;j<8;j++){
board[i][j]=2;
}
}
board[3][3]=0;board[4][4]=0;
board[3][4]=1;board[4][3]=1;
}
public void actionPerformed(ActionEvent e){
for (int i=0;i<8;i++){
for (int j=0;j<8;j++){
if(e.getSource()==buttons[i]){
buttons[i].setEnabled(false);
board[i][j]=1;
check();
}
}
}
}
public static void main (String[] args){
new othello();
}
}
What this code results in is a seemingly random number of buttons actually being added. Occasionally it adds all 64, more commonly it adds perhaps half or so, it always starts properly but stops at an arbitrary point (I tested by having the button labels count up).
I added some println's to see if the loop itself was actually completing, no problem there, it's going round the loop all 64 times, it just stops adding buttons at some point.
I'm something of a beginner at Java so I'm sure it's something really simple and stupid, but I currently have no idea what's going wrong. Can anyone help?
Edited for more code.
Have you initializated the array? like
JButton[] buttons = new JButtons[x];
make some prints to check in what number the loop stops.
You should be adding to a ContentPane not directly to a JFrame.add()
Like all other JFC/Swing top-level containers, a JFrame contains a
JRootPane as its only child. The content pane provided by the root
pane should, as a rule, contain all the non-menu components displayed
by the JFrame.
Are you setting the layout manager to something other than the default?
The default content pane will have a BorderLayout manager set on it.
Refer to RootPaneContainer for details on adding, removing and setting
the LayoutManager of a JFrame.
the proper idiomatic code to add contents is as follows:
window.getContentPane().add(child);
Refer to the Javadoc for details on proper use.
Maybe you are not using the event dispatch thread to manipulate the UI?
From the Swing Tutorial:
The event dispatch thread, where all event-handling code is executed.
Most code that interacts with the Swing framework must also execute on
this thread.
Try to run your UI construction code using SwingUtilities.invokeAndWait().
Edit: the corrected source code would be:
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class othello implements ActionListener
{
int[][] board = new int[8][8];
JFrame window = new JFrame();
JButton[] buttons = new JButton[64];
public othello()
{
try
{
SwingUtilities.invokeAndWait(new Runnable()
{
public void run()
{
window.setSize(400, 400);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setLayout(new GridLayout(8, 8));
window.setVisible(true);
for (int i = 0; i < 64; i++)
{
buttons[i] = new JButton("");
buttons[i].addActionListener(othello.this);
window.getContentPane().add(buttons[i]);
}
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
board[i][j] = 2;
}
}
board[3][3] = 0;
board[4][4] = 0;
board[3][4] = 1;
board[4][3] = 1;
}
});
}
catch (Exception e)
{
// TODO Handle exception
e.printStackTrace();
}
}
public void actionPerformed(ActionEvent e)
{
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
if (e.getSource() == buttons[i])
{
buttons[i].setEnabled(false);
board[i][j] = 1;
// check();
}
}
}
}
public static void main(String[] args)
{
new othello();
}
}

Categories

Resources