Drawing a line at a specific point in JFrame - java

So here is my code, which displays a 9x9 grid:
import javax.swing.*;
import java.awt.*;
public class SudokuGrid extends JFrame {
private static final int ROWS = 9;
private static final int COLUMNS = 9;
int fontSize = 30;
public static void main(String[] args) {
SudokuGrid makeSudokuGrid = new SudokuGrid();
} // end of main
// constructor SudokuGrid
public SudokuGrid() {
JTextField[][] inputBoxes = new JTextField[ROWS][COLUMNS];
Font font = new Font("Helvetica", Font.BOLD, fontSize);
setLayout(new GridLayout(ROWS, COLUMNS));
// set frame size
setSize(400, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// outer loop to create the rows
for (int rows = 0 ; rows < ROWS ; rows++) {
// inner loop to create the columns
for (int columns = 0 ; columns < COLUMNS ; columns++) {
// make text fields empty
inputBoxes[rows][columns] = new JTextField("");
// add text fields to the frame
add(inputBoxes[rows][columns]);
// center text in each text box
inputBoxes[rows][columns].setHorizontalAlignment(JTextField.CENTER);
// apply font to each text box
inputBoxes[rows][columns].setFont(font);
} // end of columns loop
} // end of rows loop
// make frame visible
getContentPane().setBackground(Color.RED);
setVisible(true);
} // end of constructor SudokuGrid
} // end of class SudokuGrid
What I am trying to do is to draw a line every third row. So every third text box, there should be a thick line spanning all columns. Hope that makes sense.
Any help is greatly apprecaited. Thank you!

The simple answer is, GridLayout isn't going to do what you want, it's simply not flexible enough, instead...
You could...
Change the layout manager and make use of a JSeparator
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class SudokuGrid {
public static void main(String[] args) {
new SudokuGrid();
}
public SudokuGrid() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class TestPane extends JPanel {
private static final int ROWS = 9;
private static final int COLUMNS = 9;
int fontSize = 30;
public TestPane() {
JTextField[][] inputBoxes = new JTextField[ROWS][COLUMNS];
Font font = new Font("Helvetica", Font.BOLD, fontSize);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.BOTH;
gbc.weightx = 1;
gbc.weighty = 1;
gbc.gridy = 0;
GridBagConstraints split = new GridBagConstraints();
split.fill = GridBagConstraints.BOTH;
split.weightx = 1;
split.gridx = 0;
split.gridwidth = GridBagConstraints.REMAINDER;
// outer loop to create the rows
for (int rows = 0; rows < ROWS; rows++) {
gbc.gridy++;
// inner loop to create the columns
for (int columns = 0; columns < COLUMNS; columns++) {
gbc.gridx = columns;
// make text fields empty
inputBoxes[rows][columns] = new JTextField(1);
// add text fields to the frame
add(inputBoxes[rows][columns], gbc);
// center text in each text box
inputBoxes[rows][columns].setHorizontalAlignment(JTextField.CENTER);
// apply font to each text box
inputBoxes[rows][columns].setFont(font);
} // end of columns loop
if ((rows + 1) % 3 == 0) {
System.out.println("Split");
split.gridy = gbc.gridy + 1;
gbc.gridy += 2;
JSeparator sep = new JSeparator(JSeparator.HORIZONTAL);
add(sep, split);
}
} // end of rows loop
}
}
}
You could...
Make your own "split" component through the use of custom painting
public static class HorizontalSplit extends JPanel {
public HorizontalSplit() {
setOpaque(false);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(0, 3);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int y = (getHeight() - 3) / 2;
BasicStroke stroke = new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
g2d.setStroke(stroke);
g2d.drawLine(0, y, getWidth(), y);
g2d.dispose();
}
}
Which would simply replace the JSeparator...
if ((rows + 1) % 3 == 0) {
System.out.println("Split");
split.gridy = gbc.gridy + 1;
gbc.gridy += 2;
JPanel sep = new HorizontalSplit();
add(sep, split);
}
You could...
Use a compound layout and a MatteLayout...
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.MatteBorder;
public class SudokuGrid {
public static void main(String[] args) {
new SudokuGrid();
}
public SudokuGrid() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class TestPane extends JPanel {
private static final int ROWS = 9;
private static final int COLUMNS = 9;
int fontSize = 30;
public TestPane() {
JTextField[][] inputBoxes = new JTextField[ROWS][COLUMNS];
Font font = new Font("Helvetica", Font.BOLD, fontSize);
setLayout(new GridBagLayout());
GridBagConstraints groupContraint = new GridBagConstraints();
groupContraint.fill = GridBagConstraints.BOTH;
groupContraint.weightx = 1;
groupContraint.weighty = 1;
groupContraint.gridwidth = GridBagConstraints.REMAINDER;
JPanel group = new JPanel(new GridLayout(3, COLUMNS));
group.setBorder(new MatteBorder(0, 0, 1, 0, Color.BLACK));
// outer loop to create the rows
for (int rows = 0; rows < ROWS; rows++) {
// inner loop to create the columns
for (int columns = 0; columns < COLUMNS; columns++) {
// make text fields empty
inputBoxes[rows][columns] = new JTextField(1);
// add text fields to the frame
group.add(inputBoxes[rows][columns]);
// center text in each text box
inputBoxes[rows][columns].setHorizontalAlignment(JTextField.CENTER);
// apply font to each text box
inputBoxes[rows][columns].setFont(font);
} // end of columns loop
if ((rows + 1) % 3 == 0) {
add(group, groupContraint);
group = new JPanel(new GridLayout(3, COLUMNS));
group.setBorder(new MatteBorder(0, 0, 1, 0, Color.BLACK));
}
} // end of rows loop
}
}
}

Related

Get click position in grid. Java Swing

I got this code witch creates a clickable grid that shows the mouse position, altough i am not able to get the position in the grid in where the mouse is clicked, trying to be both X and Y position. Any ideas? This is how the grid looks:
Code:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.Border;
import javax.swing.border.MatteBorder;
public class TestGrid02 {
public TestGrid02() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private static final int ROWS = 20;
private static final int COLUMNS = 20;
private static GridBagConstraints gbc;
public TestPane() {
setLayout(new GridBagLayout());
gbc = new GridBagConstraints();
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLUMNS; col++) {
gbc.gridx = col;
gbc.gridy = row;
CellPane cellPane = new CellPane();
Border border = null;
if (row < ROWS-1) {
if (col < COLUMNS-1) {
border = new MatteBorder(1, 1, 0, 0, Color.GRAY);
} else {
border = new MatteBorder(1, 1, 0, 1, Color.GRAY);
}
} else {
border = new MatteBorder(1, 1, 1, 0, Color.GRAY);
}
cellPane.setBorder(border);
add(cellPane, gbc);
}
}
}
}
public class CellPane extends JPanel {
private Color defaultBackground;
public CellPane() {
addMouseListener(new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent e) {
defaultBackground = getBackground();
setBackground(Color.RED);
}
#Override
public void mouseExited(MouseEvent e) {
setBackground(defaultBackground);
}
#Override
public void mouseClicked(MouseEvent e){
//Here is where it is supposed to be
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(30, 30);
}
}
}
In the CellPane class, witch is intended to be the one that listens to the mouse it is supposed to be the function that i need, at the mouseClicked listener, however i have tried with e.getX() or e.getLocationOnScreen() and these values were changing everytime i click in the same grid.
Well, that looks familiar 🤣
So, the basic idea would be to pass in the cell it's coordinates (ie, row/column) value via the constructor, for example...
public class CellPane extends JPanel {
private Color defaultBackground;
private Point cellCoordinate;
public CellPane(Point cellCoordinate) {
this.cellCoordinate = cellCoordinate;
addMouseListener(new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent e) {
defaultBackground = getBackground();
setBackground(Color.RED);
}
#Override
public void mouseExited(MouseEvent e) {
setBackground(defaultBackground);
}
#Override
public void mouseClicked(MouseEvent e) {
//Here is where it is supposed to be
System.out.println("Did click cell # " + getCellCoordinate().x + "x" + getCellCoordinate().y);
}
});
}
public Point getCellCoordinate() {
return cellCoordinate;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(30, 30);
}
}
The cell itself doesn't really care, not does it have any reasonable information available to it to determine how it's been laid out, so your best bet is to "tell" it the information you want it to represent.
For me, I'd just pass in the GridBagLayout row/col information, for example...
gbc.gridx = col;
gbc.gridy = row;
CellPane cellPane = new CellPane(new Point(col, row));
This way you remove all concept (and the issues associated with it) of how the cell is laid out
This approach (using buttons and action listeners) is better IMO. It uses the getButtonRowCol method to return a string indicating the button's location in an array (the buttonArray).
Use b.setBorderPainted(false); (uncomment that code line) to get rid of the borders around each button. Look to the values passed to the constructor of the GridLayout to remove the space between buttons.
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
public class GameGridLayout {
int size = 40;
int iconSize = 10;
JButton[][] buttonArray = new JButton[size][size];
ActionListener actionListener;
JLabel output = new JLabel("Click somewhere on the GUI");
GameGridLayout() {
JPanel gui = new JPanel(new BorderLayout(2,2));
gui.setBorder(new EmptyBorder(4,4,4,4));
gui.add(output,BorderLayout.PAGE_END);
JPanel gameContainer = new JPanel(new GridLayout(0,size,2,2));
gui.add(gameContainer);
actionListener = e -> output.setText(getButtonRowCol((JButton)e.getSource()));
for (int ii=0; ii<size*size; ii++) {
JButton b = getButton();
gameContainer.add(b);
buttonArray[ii%size][ii/size] = b;
}
JFrame f = new JFrame("GameGridLayout");
f.add(gui);
f.pack();
f.setMinimumSize(f.getSize());
f.setLocationByPlatform(true);
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setVisible(true);
}
private String getButtonRowCol(JButton button) {
StringBuilder sb = new StringBuilder();
for (int xx=0; xx<size; xx++) {
for (int yy=0; yy<size; yy++) {
if (button.equals(buttonArray[xx][yy])) {
sb.append("User selected button at: ");
sb.append(xx+1);
sb.append(",");
sb.append(yy+1);
break;
}
}
}
return sb.toString();
}
private JButton getButton() {
JButton b = new JButton();
b.setIcon(new ImageIcon(
new BufferedImage(iconSize,iconSize,BufferedImage.TYPE_INT_ARGB)));
b.setRolloverIcon(new ImageIcon(
new BufferedImage(iconSize,iconSize,BufferedImage.TYPE_INT_RGB)));
b.setMargin(new Insets(0,0,0,0));
//b.setBorderPainted(false);
b.setContentAreaFilled(false);
b.addActionListener(actionListener);
return b;
}
public static void main(String[] args) {
Runnable r = () -> new GameGridLayout();
SwingUtilities.invokeLater(r);
}
}

Spaces between elements in GridLayout and GridBagLayout

I am trying to create a grid of text fields which I envision would look like this:
I am trying to use Swing in order to do this but am having trouble creating the grid. I have tried both GridBagLayout and GridLayout in order to accomplish this but have had the same issue with both - I am unable to remove spaces between the text fields.
The above image is using grid bag layout. I have tried to change the insets as well as the weights of each text field but have not been able to get rid of the spaces between the fields.
The grid layout is slightly better:
But it has the same problem. I tried adding each text field to a JPanel and then created an empty border for each panel but this also did not work.
I have attached the code for both implementations. I am not committed to using a JTextField so if there is some other element that a user can type into I would be willing to try that out as well. Any help getting rid of the spaces between each text field would be greatly appreciated!
GridBagLayoutDemo
class GridBagLayoutDemo {
public static void addComponentsToPane(Container pane) {
GridBagLayout gbl = new GridBagLayout();
pane.setLayout(gbl);
GridBagConstraints c = new GridBagConstraints();
int rows = 2;
int cols = 2;
for(int i = 0; i < (rows + 1) * 3; i++){
JTextField textField = new JTextField(1);
textField.setFont( new Font("Serif", Font.PLAIN, 30) );
JPanel tempPanel = new JPanel();
tempPanel.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
tempPanel.add(textField);
c.gridx = i % (rows + 1);
c.gridy = i / (cols + 1);
c.gridheight = 1;
c.gridwidth = 1;
c.anchor = GridBagConstraints.FIRST_LINE_START;
c.fill = GridBagConstraints.HORIZONTAL;
pane.add(tempPanel, c);
}
gbl.setConstraints(pane, c);
c.insets = new Insets(0,0,0,0);
}
public void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("GridBagLayoutDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Set up the content pane.
addComponentsToPane(frame.getContentPane());
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
GridBagLayoutDemo demo = new GridBagLayoutDemo();
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
demo.createAndShowGUI();
}
});
}
}
GridLayoutDemo
class GridLayoutDemo {
public void createAndShowGUI() {
JFrame frame = new JFrame("GridLayout");
//frame.setOpacity(0L);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel parentPanel = new JPanel();
GridLayout layout = new GridLayout(3, 3, 0, 0);
layout.setHgap(0);
layout.setVgap(0);
parentPanel.setLayout(layout);
for(int i = 0 ; i < 9; i++){
JTextField textField = new JTextField();
textField.setHorizontalAlignment(JTextField.CENTER);
// JPanel tempPanel = new JPanel();
//textField.setBounds(0, 0, 10 , 10);
//textField.setFont( new Font("Serif", Font.PLAIN, 18));
//tempPanel.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
//tempPanel.add(textField);
// tempPanel.add(textField);
parentPanel.add(textField);
}
frame.add(parentPanel);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
GridLayoutDemo demo = new GridLayoutDemo();
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
demo.createAndShowGUI();
}
});
}
}
I think you will find that this is a issue with the MacOS look and feel, as it adds a empty border around the text fields to allow for the focus highlight
You can see it highlighted below
The simplest way to remove it, is to remove or replace the border, for example...
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.BOTH;
gbc.weightx = 1;
gbc.weighty = 1;
int rows = 3;
int cols = 3;
for (int index = 0; index < (rows * cols); index++) {
int row = index % rows;
int col = index / cols;
gbc.gridy = row;
gbc.gridx = col;
JTextField textField = new JTextField(4);
textField.setText(col + "x" + row);
textField.setBorder(new LineBorder(Color.DARK_GRAY));
add(textField, gbc);
}
}
}
}

Set the size of JButton to the length and width of the label

I am working on adding buttons to a button panel to be more familiar with java.swing class. Is there a way to set the size of JButton to the length and width of the button label?
Similar to setting height and width view in the xml file to wrap_content or match_parent.Setting a View or Layouts size based on either it's contents or the parent's dimensions rather than explicitly specifying a dimension.
android:layout_width="wrap_content"
android:layout_height="match_parent"
Is there a way to set the size of JButton to the length and width of the button label using button.setPreferredSize() without explicitly specifying the dimension?
button = new JButton[buttonName.length];
RadioButtonAction radioButtonEventO=new RadioButtonAction(); //O for operation
buttonPanelS=new JPanel();
buttonPanelS.setLayout(new GridLayout(4,1));
for(int i=0; i<buttonName.length;i++){
button[i]=new JButton(buttonName[i]);
button[i].setMargin(new Insets(0,0,0,0));
button[i].addActionListener(radioButtonEventO);
//button[i].setPreferredSize();
buttonPanelS.add(button[i]);
}
operationPanel.add(buttonPanelS);
I'm not 100% I understand, but GridLayout will, by design, size the all the components to occupy the available space of the container, evenly.
It sounds more like what you're after is GridBagLayout...
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
JButton[] button = new JButton[5];
JPanel buttonPanelS = new JPanel();
buttonPanelS.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
for (int i = 0; i < 5; i++) {
button[i] = new JButton(random());
button[i].setMargin(new Insets(0, 0, 0, 0));
buttonPanelS.add(button[i], gbc);
}
add(buttonPanelS);
}
private Random rnd = new Random();
public String random() {
int length = rnd.nextInt(20) + 1;
StringBuilder sb = new StringBuilder(length);
for (int index = 0; index < length; index++) {
sb.append(('a' + rnd.nextInt(52)));
}
return sb.toString();
}
}
}
If that's not what you're after either, then consider providing a drawing, to better illustrate your question

How to add zooming and panning functions to a JPanel?

So I have a program in Java which uses a grid bag layout to create cells(like graph paper), and if a mouse is over one of the cell said cell will change its color. I would like to implement a zoom function, using mouse scroll wheel. Also I would like to add a function that, when your zoomed in, you can pan around by clicking and dragging the zoomed in canvas. To specify panning around, think of clicking and dragging to move around a zoomed in map, like google maps.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.Border;
import javax.swing.border.MatteBorder;
public class Testing {
public int RowI = 10;
public int ColI = 10;
public static void main(String[] args) {
new Testing();
}
public Testing() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
for (int row = 0; row < RowI; row++) {
for (int col = 0; col < ColI; col++) {
gbc.gridx = col;
gbc.gridy = row;
CellPane cellPane = new CellPane();
Border border = null;
if (row < 4) {
if (col < 4) {
border = new MatteBorder(1, 1, 0, 0, Color.GRAY);
} else {
border = new MatteBorder(1, 1, 0, 1, Color.GRAY);
}
} else {
if (col < 4) {
border = new MatteBorder(1, 1, 1, 0, Color.GRAY);
} else {
border = new MatteBorder(1, 1, 1, 1, Color.GRAY);
}
}
cellPane.setBorder(border);
add(cellPane, gbc);
}
}
}
}
public class CellPane extends JPanel { //The CellPane class changes the color of an individual cell based on whether or no the mouse I on a cell.
private Color defaultBackground; //This is a private color that is only used by the mouseListener.
public CellPane() {
addMouseListener(new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent e) { //If mouse is on cell turn cell the given color(in this case green).
defaultBackground = getBackground();
setBackground(Color.GREEN);
}
#Override
public void mouseExited(MouseEvent e) { //If mouse is not on cell revert to default background.
setBackground(defaultBackground);
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(50, 50); //Cell size on x and y axis.
}
}
}
Maybe this question will answer what you're looking for.

Filling Frame with Buttons Using GridBagLayout

I am trying to build a matching game with icons attached to each button. Although, this isn't close to being finished, I have a problem with filling the panel with buttons.
With this code I get a grey colored frame. If i comment out the 3 methods i use under "//execution" the panel will be all black (which is how i am testing to see if the buttons are filling the space or not.)
For some reaso,n my buttons aren't being populated onto the panel.
I need some help!!! Where am I going wrong?
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MemoryMainFrame extends JFrame implements ActionListener {
JButton button[] = new JButton[16];
private static final int SIXTEEN_BUTTONS = 16;
JPanel mainPanel = new JPanel();
double dim = Math.sqrt(SIXTEEN_BUTTONS);
int numOfColumns = (int) (dim);
int numOfRows = (int) (dim);
public static void main(String[] args) {
new MemoryMainFrame();
}
public MemoryMainFrame() {
this.setTitle("MemoryGame!!!");
this.setSize(400, 400);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
mainPanel.setBackground(Color.BLACK);
mainPanel.setLayout(new GridBagLayout());
// execution
FillButtonArray(SIXTEEN_BUTTONS);
AddButtonListener(SIXTEEN_BUTTONS);
ButtonToPanel(SIXTEEN_BUTTONS);
this.add(mainPanel);
}
public void FillButtonArray(int numOfButtons) {
int i = 0;
while (i < numOfButtons) {
button[i] = new JButton("asdf");
}
}
public void AddButtonListener(int numOfButtons) {
int i = 0;
while (i < numOfButtons) {
button[i].addActionListener(this);
}
}
public void ButtonToPanel(int numOfButtons) {
int n = 0;
GridBagConstraints gbc = new GridBagConstraints();
for (int i = 0; i < numOfColumns; i++) {
for (int j = 0; j < numOfRows; j++) {
gbc.gridx = i;
gbc.gridy = j;
n++;
button[n].setBorder(BorderFactory.createLineBorder(
Color.DARK_GRAY, 2));
mainPanel.add(button[n]);
}
}
}
public void actionPerformed(ActionEvent arg0) {
JFrame j = new JFrame();
j.setSize(300, 300);
j.setVisible(true);
}
}
I use the "asdf" as a test to see if the buttons work as well.
also, the actionperformed was a test as well. That part of the code is irrelevant.
You're creating your GridBagConstraints but you're not using them.
Change this:
mainPanel.add(button[n]);
to this:
// passes both the component and the GBC into the container
mainPanel.add(button[n], gbc);
Edit
You've also got a never-ending loop here:
while (i < numOfButtons) {
button[i] = new JButton("asdf");
}
and likewise for the AddButtonListener(...) method.
You'll want to fix this by using either a for loop or else changing i within the loop.
Also per Andrew Thompson's comment, you're setting the JFrame visible too early, before all components have been added.
Also your use of Math.sqrt then casting the result to int is very risky and risks getting unexpected results. Just declare the side length to 8 and square the int if you need to.
For an example of GridBagLayout, please check out:
import java.awt.Color;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import javax.swing.*;
#SuppressWarnings("serial") // avoid extending JFrame if possible
public class MemoryMainPanel extends JPanel {
private static final int ROWS = 8;
private static final Color BACKGROUND = Color.black;
private static final int I_GAP = 5;
private static final Insets BTN_INSETS = new Insets(I_GAP, I_GAP, I_GAP, I_GAP);
private JButton[][] buttons = new JButton[ROWS][ROWS];
public MemoryMainPanel() {
setBackground(BACKGROUND);
setLayout(new GridBagLayout());
for (int row = 0; row < buttons.length; row++) {
for (int col = 0; col < buttons[row].length; col++) {
JButton btn = new JButton(new ButtonAction(row, col));
add(btn, createGbc(row, col));
buttons[row][col] = btn;
}
}
}
private GridBagConstraints createGbc(int y, int x) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = x;
gbc.gridy = y;
gbc.weightx = 1.0;
gbc.weighty = 1.0;
gbc.insets = BTN_INSETS;
return gbc;
}
private class ButtonAction extends AbstractAction {
private int row;
private int col;
public ButtonAction(int row, int col) {
super("asdf");
this.row = row;
this.col = col;
}
#Override
public void actionPerformed(ActionEvent e) {
String text = String.format("Column, Row: [%d, %d]", col + 1, row + 1);
Component parentComponent = MemoryMainPanel.this;
String message = text;
String title = "Button Pressed";
int messageType = JOptionPane.PLAIN_MESSAGE;
Icon icon = null;
JOptionPane.showMessageDialog(parentComponent, message, title, messageType, icon);
}
}
private static void createAndShowGui() {
MemoryMainPanel mainPanel = new MemoryMainPanel();
JFrame frame = new JFrame("MemoryMainPanel");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

Categories

Resources