My GUI is acting really weird - java

The first image shows what the GUI looks like when I just start it, the second shows what happens when I click around the board. The chess pieces show up at the top row after I click a piece and then click on a button on the top row. What is happening here?!
The code is below; this class is where I have most of my code. The rest of the classes are just loading images at this point. The Board constructor is called in the main to build the GUI.
public class BoardPanel extends JPanel {
public BoardPanel() {
createBoard();
}
private void createBoard(){
setLayout(new GridLayout(10, 10));
// Makes a 10 x 10 grid of black and white colors
for (int i = 0; i<10; i++){
for (int j = 0; j<10; j++){
square[i][j] = new JButton();
square[i][j].setRolloverEnabled(false);
if ((i+j)%2 == 0)
square[i][j].setBackground(Color.WHITE);
else
square[i][j].setBackground(Color.LIGHT_GRAY);
add(square[i][j]);
}
}
addLabels();
//Colors the corner squares
square[0][0].setBackground(new Color(155, 234, 242, 100));
square[0][9].setBackground(new Color(155, 234, 242, 100));
square[9][0].setBackground(new Color(155, 234, 242, 100));
square[9][9].setBackground(new Color(155, 234, 242, 100));
}
private void addLabels(){
//Adds labels to the ranks
for (int i =1 ; i< 9; i++){
square[i][0].setBackground(new Color(155, 234, 242, 100));
square[i][0].setText(rank[8-i]);
square[i][0].setHorizontalTextPosition(SwingConstants.RIGHT);
square[i][9].setBackground(new Color(155, 234, 242, 100));
square[i][9].setText(rank[8-i]);
square[i][9].setHorizontalTextPosition(SwingConstants.LEFT);
}
//Adds labels to the files
for (int j = 1; j<9;j++){
square[0][j].setBackground(new Color(155, 234, 242, 100));
square[0][j].setText(file[j-1]);
square[0][j].setVerticalTextPosition(SwingConstants.BOTTOM);
square[9][j].setBackground(new Color(155, 234, 242, 100));
square[9][j].setText(file[j-1]);
square[9][j].setVerticalTextPosition(SwingConstants.TOP);
}
JButton square[][] = new JButton[10][10];
String[] rank = {"1","2","3","4","5","6","7","8"};
String[] file = {"a","b","c","d","e","f","g","h"};
}
}
The main class
public class Board {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.add(new BoardPanel());
frame.setVisible(true);
frame.setSize(900, 700);
}
}

Your problem is with the button thinking that it is fully opaque when it is in fact not opaque. As per Kleopatra in this answer, you must make the button non-opaque and take over the painting mechanisms
square[i][j] = new JButton() {
#Override // !! add this:
protected void paintComponent(Graphics g) {
if (!isOpaque() && getBackground().getAlpha() < 255) {
g.setColor(getBackground());
g.fillRect(0, 0, getWidth(), getHeight());
}
super.paintComponent(g);
}
};
square[i][j].setRolloverEnabled(false);
square[i][j].setOpaque(false); // !! and also add this *******
As a side note, I wouldn't be using JButtons for this type of problem, but rather I'd be using JPanels, and would place my chess pieces as ImageIcons displayed in JLabels, labels that are added to or removed from the appropriate chess-board squares.
A board without buttons and without use of alpha colors:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import javax.swing.*;
#SuppressWarnings("serial")
public class Board2 extends JPanel {
private static final int SIDE_LEN = 80;
private static final Dimension SQUARE_SZ = new Dimension(SIDE_LEN, SIDE_LEN);
private static final Color EDGE_COLOR = new Color(165, 245, 250);
private static final Color DARK_SQR_COLOR = Color.LIGHT_GRAY;
private static final Color LIGHT_SQR_COLOR = Color.WHITE;
private JPanel[][] chessSquares = new JPanel[8][8];
public Board2() {
setLayout(new GridLayout(10, 10)); // sorry for magic numbers
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
if ((i == 0 || i == 9) && (j == 0 || j == 9)) {
add(createEdgePanel(""));
} else if (i == 0 || i == 9) {
String text = String.valueOf((char) (j + 'a' - 1));
add(createEdgePanel(text));
} else if (j == 0 || j == 9) {
String text = String.valueOf(8 - i + 1);
add(createEdgePanel(text));
} else {
JPanel panel = createSquare(i, j);
add(panel);
}
}
}
}
private JPanel createSquare(int i, int j) {
JPanel panel = new JPanel(new GridBagLayout());
Color c = (i % 2 == j % 2) ? LIGHT_SQR_COLOR : DARK_SQR_COLOR;
panel.setBackground(c);
panel.setPreferredSize(SQUARE_SZ);
panel.setBorder(BorderFactory.createLineBorder(Color.GRAY));
return panel;
}
private JPanel createEdgePanel(String text) {
JLabel label = new JLabel(text, SwingConstants.CENTER);
JPanel panel = new JPanel(new GridBagLayout());
panel.add(label);
panel.setBackground(EDGE_COLOR);
panel.setPreferredSize(SQUARE_SZ);
panel.setBorder(BorderFactory.createLineBorder(Color.GRAY));
return panel;
}
private static void createAndShowGui() {
Board2 mainPanel = new Board2();
JFrame frame = new JFrame("Board2");
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(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Which on my system looks like:
Now with some pieces added:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.*;
#SuppressWarnings("serial")
public class Board2 extends JPanel {
private static final int SIDE_LEN = 80;
private static final Dimension SQUARE_SZ = new Dimension(SIDE_LEN, SIDE_LEN);
private static final String SPRITE_PATH = "http://i.stack.imgur.com/memI0.png";
private static final int SPRITE_ROWS = 2;
private static final int SPRITE_COLS = 6;
private static final Color EDGE_COLOR = new Color(165, 245, 250);
private static final Color DARK_SQR_COLOR = Color.LIGHT_GRAY;
private static final Color LIGHT_SQR_COLOR = Color.WHITE;
private static final int ROWS = 8;
private JLabel[][] chessSquares = new JLabel[ROWS][ROWS];
private BufferedImage bigImage;
private List<Icon> icons = new ArrayList<>();
public Board2() throws IOException {
URL imgUrl = new URL(SPRITE_PATH);
bigImage = ImageIO.read(imgUrl);
int w = bigImage.getWidth() / SPRITE_COLS;
int h = bigImage.getHeight() / SPRITE_ROWS;
for (int i = 0; i < SPRITE_ROWS; i++) {
for (int j = 0; j < SPRITE_COLS; j++) {
int x = (j * bigImage.getWidth()) / SPRITE_COLS;
int y = (i * bigImage.getHeight()) / SPRITE_ROWS;
BufferedImage spriteImg = bigImage.getSubimage(x, y, w, h);
Icon spriteIcon = new ImageIcon(spriteImg);
icons.add(spriteIcon);
}
}
for (int i = 0; i < chessSquares.length; i++) {
for (int j = 0; j < chessSquares[i].length; j++) {
chessSquares[i][j] = new JLabel();
}
}
setLayout(new GridLayout(ROWS + 2, ROWS + 2)); // sorry for magic numbers
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
if ((i == 0 || i == ROWS + 1) && (j == 0 || j == ROWS + 1)) {
add(createEdgePanel(""));
} else if (i == 0 || i == ROWS + 1) {
String text = String.valueOf((char) (j + 'a' - 1));
add(createEdgePanel(text));
} else if (j == 0 || j == ROWS + 1) {
String text = String.valueOf(ROWS - i + 1);
add(createEdgePanel(text));
} else {
JPanel panel = createSquare(i, j);
panel.add(chessSquares[i - 1][j - 1]);
add(panel);
}
}
}
setPieces(0, 0, 2); // rooks
setPieces(1, 0, 3); // knights
setPieces(2, 0, 4); // bishops
// kings and queens
chessSquares[0][3].setIcon(icons.get(1));
chessSquares[7][3].setIcon(icons.get(6 + 1));
chessSquares[0][4].setIcon(icons.get(0));
chessSquares[7][4].setIcon(icons.get(6 + 0));
// pawns
for (int i = 0; i < ROWS / 2; i++) {
setPieces(i, 1, 5);
}
}
private void setPieces(int colPos, int rowPos, int pieceIndex) {
chessSquares[rowPos][colPos].setIcon(icons.get(pieceIndex));
chessSquares[rowPos][ROWS - 1 - colPos].setIcon(icons.get(pieceIndex));
chessSquares[ROWS - 1 - rowPos][colPos].setIcon(icons.get(6 + pieceIndex));
chessSquares[ROWS - 1 - rowPos][ROWS - 1 - colPos].setIcon(icons
.get(6 + pieceIndex));
}
private void setPiece(int colPos, int pieceIndex) {
chessSquares[0][colPos].setIcon(icons.get(pieceIndex));
chessSquares[ROWS - 1][ROWS - 1 - colPos].setIcon(icons.get(6 + pieceIndex));
}
private JPanel createSquare(int i, int j) {
JPanel panel = new JPanel(new GridBagLayout());
Color c = (i % 2 == j % 2) ? LIGHT_SQR_COLOR : DARK_SQR_COLOR;
panel.setBackground(c);
panel.setPreferredSize(SQUARE_SZ);
panel.setBorder(BorderFactory.createLineBorder(Color.GRAY));
return panel;
}
private JPanel createEdgePanel(String text) {
JLabel label = new JLabel(text, SwingConstants.CENTER);
JPanel panel = new JPanel(new GridBagLayout());
panel.add(label);
panel.setBackground(EDGE_COLOR);
panel.setPreferredSize(SQUARE_SZ);
panel.setBorder(BorderFactory.createLineBorder(Color.GRAY));
return panel;
}
private static void createAndShowGui() {
Board2 mainPanel = null;
try {
mainPanel = new Board2();
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
JFrame frame = new JFrame("Board2");
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(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

Related

How to make a method that disables JButton?

I am trying to make a method that disables JButtons.
The JButtons are in an array in the form of a grid, JButton [int][int] and the integers are supposed to be coordinates.
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.*;
public class BS {
public static JFrame f = new JFrame("BS");
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
initializeGui();
}
});
}
static void initializeGui() {
JPanel gui = new JPanel(new BorderLayout(3,1));
//This is the array of the JButtons in the form of a grid
final JButton[][] coordinates = new JButton[15][15];
JPanel field;
// set up the main GUI
gui.setBorder(new EmptyBorder(5, 5, 5, 5));
field = new JPanel(new GridLayout(0, 15));
field.setBorder(new CompoundBorder(new EmptyBorder(15,15,15,15),new LineBorder(Color.BLACK)));
JPanel boardConstrain = new JPanel(new GridBagLayout());
boardConstrain.add(field);
gui.add(boardConstrain);
//The making of the grid
for (int ii = 0; ii < coordinates.length; ii++) {
for (int jj = 0; jj < coordinates[ii].length; jj++) {
JButton b = new JButton();
ImageIcon icon = new ImageIcon(
new BufferedImage(30, 30, BufferedImage.TYPE_INT_ARGB));
b.setIcon(icon);
coordinates[jj][ii] = b;
field.add(coordinates[jj][ii]);
}
}
f.add(gui);
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
}
}
I did some changes in your code:
public static JFrame f = new JFrame("BS"); JFrame shouldn't be static and should have a more meaningful name (like frame for example).
final JButton[][] coordinates = new JButton[15][15]; moved this array as a class member and made it non final and also changed the name to buttons as it's easier to know what it is (coordinates to me, sounds more like an array of Point or int)
After that I added an ActionListener, see How to use Actions tutorial.
private ActionListener listener = e -> {
//Loops through the whole array in both dimensions
for (int i = 0; i < buttons.length; i++) {
for (int j = 0; j < buttons[i].length; j++) {
if (e.getSource().equals(buttons[i][j])) { //Find the JButton that was clicked
if (isStartButton) { //startButton is a boolean variable that tells us if this is the first button clicked or not
startXCoord = i;
startYCoord = j;
} else {
endXCoord = i;
endYCoord = j;
disableButtons(); //Only when we have clicked twice we disable all the buttons in between
}
isStartButton = !isStartButton; //In every button click we change the value of this variable
break; //No need to keep looking if we found our clicked button. Add another one with a condition to skip the outer loop.
}
}
}
};
And a method called disableButtons() which disables all the buttons between the 2 clicked buttons:
private void disableButtons() {
compareCoords(); //This method checks if first button clicked is after 2nd one.
for (int i = startXCoord; i <= endXCoord; i++) {
for (int j = startYCoord; j <= endYCoord; j++) {
buttons[i][j].setEnabled(false); //We disable all buttons in between
}
}
}
At the end our code ends like this:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
public class DisableButtonsInBetween {
private JFrame frame = new JFrame(getClass().getSimpleName());
private JButton[][] buttons;
private int startXCoord = -1;
private int startYCoord = -1;
private int endXCoord = -1;
private int endYCoord = -1;
private boolean isStartButton = true;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new DisableButtonsInBetween().initializeGui();
}
});
}
void initializeGui() {
JPanel gui = new JPanel(new BorderLayout(3, 1));
// This is the array of the JButtons in the form of a grid
JPanel pane;
buttons = new JButton[15][15];
// set up the main GUI
gui.setBorder(new EmptyBorder(5, 5, 5, 5));
pane = new JPanel(new GridLayout(0, 15));
pane.setBorder(new CompoundBorder(new EmptyBorder(15, 15, 15, 15), new LineBorder(Color.BLACK)));
JPanel boardConstrain = new JPanel(new GridBagLayout());
boardConstrain.add(pane);
gui.add(boardConstrain);
// The making of the grid
for (int ii = 0; ii < buttons.length; ii++) {
for (int jj = 0; jj < buttons[ii].length; jj++) {
buttons[jj][ii] = new JButton();
ImageIcon icon = new ImageIcon(new BufferedImage(30, 30, BufferedImage.TYPE_INT_ARGB));
buttons[jj][ii].setIcon(icon);
buttons[jj][ii].addActionListener(listener);
pane.add(buttons[jj][ii]);
}
}
frame.add(gui);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.pack();
frame.setMinimumSize(frame.getSize());
frame.setVisible(true);
}
//The ActionListener is what gets called when you click a JButton
private ActionListener listener = e -> {
//These for loops are done to identify which button was clicked.
for (int i = 0; i < buttons.length; i++) {
for (int j = 0; j < buttons[i].length; j++) {
if (e.getSource().equals(buttons[i][j])) {
if (isStartButton) {
//We save the coords of the 1st button clicked
startXCoord = i;
startYCoord = j;
} else {
//We save the coords of the 2nd button clicked and call the disableButtons method
endXCoord = i;
endYCoord = j;
disableButtons();
}
isStartButton = !isStartButton;
break;
}
}
}
};
//This method disables all the buttons between the 2 that were clicked
private void disableButtons() {
compareCoords();
for (int i = startXCoord; i <= endXCoord; i++) {
for (int j = startYCoord; j <= endYCoord; j++) {
buttons[i][j].setEnabled(false);
}
}
}
//This method compares the coords if the 2nd button was before (in its coords) than the 1st one it switched their coords
private void compareCoords() {
if (endXCoord < startXCoord) {
int aux = startXCoord;
startXCoord = endXCoord;
endXCoord = aux;
}
if (endYCoord < startYCoord) {
int aux = startYCoord;
startYCoord = endYCoord;
endYCoord = aux;
}
}
}
I hope this is what you were trying to do... if not please clarify.
I do not have the arrow operator, " -> ". I think it requires a higher Java. Is there a way to replace this?
For Java 7 and lower use this for the ActionListener:
private ActionListener listener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < buttons.length; i++) {
for (int j = 0; j < buttons[i].length; j++) {
if (e.getSource().equals(buttons[i][j])) {
if (isStartButton) {
startXCoord = i;
startYCoord = j;
} else {
endXCoord = i;
endYCoord = j;
disableButtons();
}
isStartButton = !isStartButton;
break;
}
}
}
}
};

put circle in middle of Jpanel

I am currently making a program that sets a checkers board with GUI. What my problem is is that I can set the board colors and make the program notify me when the mouse is clicked and where, but I can't figure out how to make the checkers appear in the middle of each spot in the right spots.
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class Main {
public static int rows = 8;
public static int colums = 8;
public static Color Col1 = Color.BLACK;
public static Color Col2 = Color.RED;
public static void main(String [ ] args){
System.out.println("Dbug3");
JFrame boardGUI = new JFrame();
boardGUI.setSize(800, 800);
boardGUI.setTitle("Checker Board");
Container pane = boardGUI.getContentPane();
pane.setLayout(new GridLayout(rows, colums));
Color tmp;
ImageIcon image = new ImageIcon("C:\\Users\\Awesome\\Desktop\\CheckerP.jpg");
JLabel label = new JLabel("", image, JLabel.CENTER);
boardGUI.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
//Board
System.out.println(e.getX() + "," + e.getY());
}
});
for (int i = 0; i < rows; i++) {
if (i % 2 == 0) {
tmp = Col1;
} else {
tmp = Col2;
}
for (int j = 0; j < colums; j++) {
JPanel panel = new JPanel();
panel.setBackground(tmp);
panel.add( label, BorderLayout.CENTER );
if (tmp.equals(Col1)) tmp = Col2;
else tmp = Col1;
pane.add(panel);
}
}
boardGUI.setVisible(true);
}
public void paint(Graphics2D g) {
g.fillOval(480,480,200,200);
g.setColor(Color.BLUE);
}
}
Try this with the drawOval before the fillOval?
public void drawCircle(Graphics2D g) {
g.drawOval(480, 480, 200, 200);
g.setColor(Color.BLUE);
g.fillOval(480, 480, 200, 200);
}

How would I fill a JFrame completely with JButtons efficiently and quickly?

So, I am working on recreating Minesweeper in Java and right now I need to place all of the buttons on the JFrame in a grid. My code is below:
import javax.swing.*;
import java.util.ArrayList;
import java.awt.*;
import javax.imageio.*;
public class Graphics{
private JFrame frame;
private JPanel panel;
private JLabel label;
private int boardSizeY;
private int boardSizeX;
private ImageIcon ImgEmpty = new ImageIcon("/Images/Empty.png");
private ImageIcon ImgFull = new ImageIcon("/Images/UnSelected.png");
public Graphics(int sizeY, int sizeX){
boardSizeX = sizeX;
boardSizeY = sizeY;
gui();
drawButtons();
}
public void gui() {
frame = new JFrame("Minesweeper");
frame.setVisible(true);
frame.setSize(boardSizeX*20, boardSizeY*20 + 2);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel = new JPanel();
panel.setLayout(null);
}
public void drawButtons(){
ArrayList<JButton> buttons = new ArrayList<>();
int x = 0;
int y = 0;
for(int t = 0; t < boardSizeX*boardSizeY; t++){
buttons.add(new JButton(ImgFull));
panel.add(buttons.get(t));
buttons.get(t).setBounds(x*20, y*20, 20, 20);
if(y == boardSizeY-1){
x++;
y = 0;
}
else y++;
}
frame.add(panel);
}
}
The code that I wrote works, however is extremely slow for board sizes greater than 10x10. What changes can I make to my drawButtons() function in order to quicken the process.
This 30 x 30 (900 buttons) version appears almost instantly on this machine. It uses JButton components and lays them out using a GridLayout.
This is what it looks like at 10 x 10 with a larger font.
import java.awt.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class MineSweeper {
public final static String BOMB = new String(Character.toChars(128163));
private JComponent ui = null;
private MineFieldModel mineFieldModel;
private final Color[] colors = {
Color.BLUE,
Color.CYAN.darker(),
Color.GREEN.darker(),
Color.YELLOW.darker(),
Color.ORANGE.darker(),
Color.PINK.darker(),
Color.MAGENTA,
Color.RED
};
private final int size = 30;
private final float fontSize = 10f;
private JButton[][] buttons;
private JLabel info = new JLabel("Enter the minefield!");
MineSweeper() {
initUI();
}
private JToolBar getToolBar() {
JToolBar tb = new JToolBar();
tb.setFloatable(false);
tb.setLayout(new FlowLayout(FlowLayout.LEADING, 4, 2));
tb.add(info);
return tb;
}
private final Point[] getExposableSquares(Point point) {
Point[] points = null;
int x = point.x;
int y = point.y;
if (mineFieldModel.isBomb(x, y)) {
}
return points;
}
public final void initUI() {
if (ui != null) {
return;
}
ui = new JPanel(new BorderLayout(4, 4));
ui.setBorder(new EmptyBorder(4, 4, 4, 4));
ui.add(getToolBar(), BorderLayout.PAGE_START);
mineFieldModel = new MineFieldModel(size, (int)(size*size*.4));
JPanel mineFieldContainer = new JPanel(new GridLayout(
size, size));
ui.add(mineFieldContainer, BorderLayout.CENTER);
int in = 5;
Insets insets = new Insets(in, in, in, in);
Font f = getCompatibleFonts().firstElement().deriveFont(fontSize);
buttons = new JButton[size][size];
for (int ii = 0; ii < size; ii++) {
for (int jj = 0; jj < size; jj++) {
JButton b = new SquareButton();
b.setMargin(insets);
b.setFont(f);
b.setText("?");
if (mineFieldModel.isExposed(ii, jj)) {
if (mineFieldModel.isBomb(ii, jj)) {
b.setForeground(Color.red);
b.setForeground(Color.BLACK);
b.setText(BOMB);
} else if (mineFieldModel.countSurroundingMines(ii, jj) > 0) {
int count = mineFieldModel.countSurroundingMines(ii, jj);
if (count > 0) {
b.setForeground(colors[count - 1]);
b.setText("" + count);
}
} else {
b.setText("");
}
}
buttons[ii][jj] = b;
mineFieldContainer.add(b);
}
}
}
private static Vector<Font> getCompatibleFonts() {
Font[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
Vector<Font> fontVector = new Vector<>();
for (Font font : fonts) {
if (font.canDisplayUpTo("12345678?" + BOMB) < 0) {
fontVector.add(font);
}
}
return fontVector;
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = () -> {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
MineSweeper o = new MineSweeper();
JFrame f = new JFrame(o.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
};
SwingUtilities.invokeLater(r);
}
}
class MineFieldModel {
public int size;
/**
* Records bomb locations.
*/
boolean[][] mineField;
/**
* Records whether this location has been exposed.
*/
boolean[][] fieldPlaceExposed;
int numberMines;
Random r = new Random();
MineFieldModel(int size, int numberMines) {
this.size = size;
this.numberMines = numberMines;
mineField = new boolean[size][size];
fieldPlaceExposed = new boolean[size][size];
ArrayList<Point> locations = new ArrayList<>();
for (int ii = 0; ii < this.size; ii++) {
for (int jj = 0; jj < size; jj++) {
mineField[ii][jj] = false;
// must change this to false for the actual game.
fieldPlaceExposed[ii][jj] = true;
Point p = new Point(ii, jj);
locations.add(p);
}
}
Collections.shuffle(locations, r);
for (int ii = 0; ii < numberMines; ii++) {
Point p = locations.get(ii);
mineField[p.x][p.y] = true;
}
}
public boolean isBomb(int x, int y) {
return mineField[x][y];
}
public boolean isExposed(int x, int y) {
return fieldPlaceExposed[x][y];
}
public int getSize() {
return size;
}
public int countSurroundingMines(int x, int y) {
int lowX = x - 1;
lowX = lowX < 0 ? 0 : lowX;
int highX = x + 2;
highX = highX > size ? size : highX;
int lowY = y - 1;
lowY = lowY < 0 ? 0 : lowY;
int highY = y + 2;
highY = highY > size ? size : highY;
int count = 0;
for (int ii = lowX; ii < highX; ii++) {
for (int jj = lowY; jj < highY; jj++) {
if (ii != x || jj != y) {
if (mineField[ii][jj]) {
count++;
}
}
}
}
return count;
}
}
class SquareButton extends JButton {
#Override
public Dimension getPreferredSize() {
Dimension d = super.getPreferredSize();
int w = d.width;
int h = d.height;
int s = w>h ? w : h;
return new Dimension(s, s);
}
}

Java MVC Pattern on a JTabbedPane

I've been trying to follow an MVC pattern on my code and I was creating a system in which I have a JTabbedPane with Jbuttons inside the panel on my View, The content's info in the Model, and a the actionlisteners on my Controller.
The problem I've been having is that I've been trying to put an actionlistener on my Jbuttons but it seems to be only working on my last tab (let's say i have 4 tabs, only the 4th tab with jbuttons work)
Oh, and I should say that I've been using Jbutton arrays
Note that I've been only using only one Jbutton array to place on my panel.
how should this work? I need a sample code for reference.
here is my sample View class
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
public class View extends JFrame
{
private static final int HEIGHT = 700;
private static final int WIDTH = 700;
private JTabbedPane tabPane = new JTabbedPane();
private JComponent tab1 = makePanel("1");
private JComponent tab2 = makePanel("2");
private JComponent tab3 = makePanel("3");
private JComponent tab4 = makePanel("4");
private JButton[] button;
private String[] buttonlabel;
public View()
{
setLayout(null);
setSize(WIDTH, HEIGHT);
setLocationRelativeTo(null);
setResizable(false);
setVisible(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
tabPane.addTab("firstTab", tab1);
tabPane.addTab("secondTab", tab2);
tabPane.addTab("thirdTab", tab3);
tabPane.addTab("fourtTab", tab4);
add(tabPane);
tabPane.setBounds(20, 20, 400, 400);
}
protected JComponent makePanel(String input)
{
JPanel panel = new JPanel(false);
panel.setLayout(null);
if(input == "1")
{
button = new JButton[4];
buttonlabel = new String[]
{
"1button1",
"2button1",
"3button1",
"4button1"
};
for(int x = 0; x < 4; x++)
{
button[x] = new JButton(buttonlabel[x]);
panel.add(button[x]);
}
int yCord = 20;
for(int x = 0; x < 4; x += 2)
{
int xCord = 20;
for(int y = x; y < (x + 2); y++)
{
button[y].setBounds(xCord, yCord, 100, 100);
xCord += 120;
}
yCord += 120;
}
}
else if(input == "2")
{
button = new JButton[4];
buttonlabel = new String[]
{
"1button2",
"2button2",
"3button2",
"4button2"
};
for(int x = 0; x < 4; x++)
{
button[x] = new JButton(buttonlabel[x]);
panel.add(button[x]);
}
int yCord = 20;
for(int x = 0; x < 4; x += 2)
{
int xCord = 20;
for(int y = x; y < (x + 2) && y < 5; y++)
{
button[y].setBounds(xCord, yCord, 100, 100);
xCord += 120;
}
yCord += 120;
}
}
else if(input == "3")
{
button = new JButton[4];
buttonlabel = new String[]
{
"1button3",
"2button3",
"3button3",
"4button3"
};
for(int x = 0; x < 4; x++)
{
button[x] = new JButton(buttonlabel[x]);
panel.add(button[x]);
}
int yCord = 20;
for(int x = 0; x < 4; x += 2)
{
int xCord = 20;
for(int y = x; y < (x + 2) && y < 5; y++)
{
button[y].setBounds(xCord, yCord, 100, 100);
xCord += 120;
}
yCord += 120;
}
}
else if(input == "4")
{
button = new JButton[4];
buttonlabel = new String[]
{
"1button4",
"2button4",
"3button4",
"4button4"
};
for(int x = 0; x < 4; x++)
{
button[x] = new JButton(buttonlabel[x]);
panel.add(button[x]);
}
int yCord = 20;
for(int x = 0; x < 4; x += 2)
{
int xCord = 20;
for(int y = x; y < (x + 2) && y < 5; y++)
{
button[y].setBounds(xCord, yCord, 100, 100);
xCord += 120;
}
yCord += 120;
}
}
return panel;
}
public void buttonListener(ActionListener buttonL)
{
for(int x = 0; x < button.length; x++)
{
button[x].addActionListener(buttonL);
}
}
public static void main(String args[])
{
View view = new View();
Controller control = new Controller(view);
view.setVisible(true);
}
}
here is my sample Controller class
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Controller
{
View view = new View();
public Controller(View view)
{
this.view = view;
this.view.buttonListener(new ButtonListener());
}
private class ButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent ae)
{
System.out.println("BUTTON WORKS!");
}
}
}
You're re-filling the button array with each creation of a JTabbedPane, and in doing so, the references for all the previous buttons have been discarded from the array and only the last remains.
I suggest that you create a class for the panel of the JTabbedPane and allow it to be injected from the control. Keep it simple.
One example:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
public class View2 extends JPanel {
private static final long serialVersionUID = 1L;
private static final String[] TAB_NAMES = {"First Tab", "Second Tab", "Third Tab", "Fourth Tab"};
private static final int PREF_W = 400;
private static final int PREF_H = 150;
private JTabbedPane tabbedPane = new JTabbedPane();
private List<MyTab> myTabs = new ArrayList<>();
private Controller2 controller2;
public View2() {
setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
setLayout(new BorderLayout());
add(tabbedPane, BorderLayout.CENTER);
for (int i = 0; i < TAB_NAMES.length; i++) {
int tabNumber = i + 1;
MyTab myTab = new MyTab(TAB_NAMES[i], tabNumber);
tabbedPane.add(myTab.getTabName(), myTab);
myTabs.add(myTab);
}
}
#Override
public Dimension getPreferredSize() {
Dimension superSz = super.getPreferredSize();
if (isPreferredSizeSet()) {
return superSz;
}
int prefW = Math.max(superSz.width, PREF_W);
int prefH = Math.max(superSz.height, PREF_H);
return new Dimension(prefW, prefH);
}
public Controller2 getController2() {
return controller2;
}
public void setController2(Controller2 controller2) {
this.controller2 = controller2;
for (MyTab myTab : myTabs) {
myTab.setController2(controller2);
}
}
private static void createAndShowGui() {
View2 viewPanel = new View2();
new Controller2(viewPanel);
JFrame frame = new JFrame("View2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(viewPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
class MyTab extends JPanel {
private static final long serialVersionUID = 1L;
private static final int BUTTON_COUNT = 4;
private String tabName;
private int tabNumber;
private List<JButton> buttons = new ArrayList<>();
private Controller2 controller2;
public MyTab(String tabName, int tabNumber) {
this.tabName = tabName;
this.tabNumber = tabNumber;
setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
setLayout(new GridLayout(2, 2, 4, 4));
for (int i = 0; i < BUTTON_COUNT; i++) {
String title = (i + 1) + " Button " + tabNumber;
JButton button = new JButton(title);
button.addActionListener(e -> {
if (controller2 != null) {
controller2.buttonAction(e);
}
});
add(button);
buttons.add(button);
}
}
public void setController2(Controller2 controller2) {
this.controller2 = controller2;
}
public String getTabName() {
return tabName;
}
public int getTabNumber() {
return tabNumber;
}
public List<JButton> getButtons() {
return buttons;
}
}
class Controller2 {
private View2 view;
public Controller2(View2 view) {
this.view = view;
view.setController2(this);
}
public void buttonAction(ActionEvent e) {
System.out.println("Button pressed! " + e.getActionCommand());
}
public View2 getView() {
return view;
}
}
This example uses a simple anonymous inner class ActionListener in the view to call a controller method.

2 Player Checkers Game (Java)

In my Springbreak holiday I started to write Checkers Game. I have created my CheckersBoard but I couldn't write MouseListener part. Can you help me with this part? I'm not pretty sure how to implement this part? Is MouseListener correct? Or should I choose another Listener? I have googled but couldn't any clue.
Thank you so much.
public class CheckersGUI {
private final JPanel gui = new JPanel(new BorderLayout(3, 3));
private JButton[][] Squares = new JButton[8][8];
private JPanel Board;
private final JLabel message = new JLabel(
"Ready to play!");
private static final String COLS = "ABCDEFGH";
private ImageIcon brown = new ImageIcon("brown.jpg");
private ImageIcon red = new ImageIcon("red.png");
CheckersGUI() {
create();
//create ButtonHandler
/* ButtonHandler handler = new ButtonHandler();
for (int i=0; i<Squares.length; i++){
for (int j=0; i<Squares[0].length; i++){
Squares[i][j].addMouseListener(handler);
}
}
}
private class ButtonHandler implements MouseListener{
public void MouseClicked ( MouseEvent event){
}*/
}
public final void create() {
// set up the main GUI
gui.setBorder(new EmptyBorder(5, 5, 5, 5));
JToolBar tools = new JToolBar();
tools.setFloatable(false);
gui.add(tools, BorderLayout.PAGE_START);
Action newGameAction = new AbstractAction("New") {
#Override
public void actionPerformed(ActionEvent e) {
setupNewGame();
}
};
tools.add(newGameAction);
// TODO - add functionality!
tools.addSeparator();
tools.add(message);
gui.add(new JLabel(""), BorderLayout.LINE_START);
Board = new JPanel(new GridLayout(0, 9)) ;
Board.setBorder(new CompoundBorder(
new EmptyBorder(8,8,8,8),
new LineBorder(Color.BLACK)
));
JPanel boardConstrain = new JPanel(new GridBagLayout());
boardConstrain.add(Board);
gui.add(boardConstrain);
// create the chess board squares
Insets buttonMargin = new Insets(0, 0, 0, 0);
for (int ii = 0; ii < Squares.length; ii++) {
for (int jj = 0; jj < Squares[ii].length; jj++) {
JButton b = new JButton();
b.setMargin(buttonMargin);
ImageIcon icon = new ImageIcon(
new BufferedImage(64, 64, BufferedImage.TYPE_INT_ARGB));
b.setIcon(icon);
if ((jj % 2 == 1 && ii % 2 == 1)
|| (jj % 2 == 0 && ii % 2 == 0)) {
b.setBackground(Color.WHITE);
} else {
b.setBackground(Color.BLACK);
}
Squares[jj][ii] = b;
}
}
/*
* fill the chess board
*/
Board.add(new JLabel(""));
// fill the top row
for (int ii = 0; ii < 8; ii++) {
Board.add(
new JLabel(COLS.substring(ii, ii + 1),
SwingConstants.CENTER));
}
// fill the black non-pawn piece row
for (int ii = 0; ii < 8; ii++) {
for (int jj = 0; jj < 8; jj++) {
switch (jj) {
case 0:
Board.add(new JLabel("" + (9-(ii + 1)),
SwingConstants.CENTER));
default:
Board.add(Squares[jj][ii]);
}
}
}
}
public final JComponent getGui() {
return gui;
}
/**
* Initializes the icons of the initial chess board piece places
*/
private final void setupNewGame() {
message.setText("Make your move!");
for (int ii = 0; ii < 8; ii++) {
Squares[ii][1].setIcon(red);
}
for (int ii = 0; ii < 8; ii++) {
Squares[ii][2].setIcon(red);
}
for (int ii = 0; ii < 8; ii++) {
Squares[ii][5].setIcon(brown);
}
for (int ii = 0; ii < 8; ii++) {
Squares[ii][6].setIcon(brown);
}
}
public static void main(String[] args) {
CheckersGUI cg = new CheckersGUI();
JFrame f = new JFrame("Checkers");
f.add(cg.getGui());
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
// ensures the frame is the minimum size it needs to be
// in order display the components within it
f.pack();
f.setResizable(false);
f.setVisible(true);
}
}
You can add an ActionListener to each button. If the button is pressed (actually, when it is released) the actionPerformed method will be called.
Add the following to your code, to make each square red after it has been clicked:
public static class ButtonHandler implements ActionListener {
private JButton b;
public ButtonHandler(JButton b) {
this.b = b;
}
#Override
public void actionPerformed(ActionEvent e) {
b.setBackground(Color.red);
}
}
This is the handler. Notice that each handler instance will be associated with a button.
Now, create and add a new ButtonHandler to each button after it has been created:
JButton b = new JButton();
...
b.addActionListener(new ButtonHandler(b));
You can change the implementation of actionPerformed.
Example: Add a method getCurrentPlayer() to actionPerformed, then, if the current player is player one, change the color to blue, else, change the color to red.
I trust this will help you to achieve what you need.

Categories

Resources