I have a matrix of JToggleButton as components of a JPanel.
I want to call setSelected() for a group of those buttons
but I want the changes to be visually simultaneous.
How can I achieve this?
Consider the following code:
import java.awt.EventQueue;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
public class Main {
private static final JToggleButton buttons[][] = new JToggleButton[8][8];
public static void main(String args[]){
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JPanel panel = new JPanel();
panel.setLayout(new java.awt.GridLayout(8, 8, 0, 0));
//Initialize buttons and add them to panel
for(int i = 0; i < 8; ++i){
for(int j = 0; j < 8; ++j){
buttons[i][j] = new JToggleButton(){
public JToggleButton setRowAndColumn(int row, int column){
addMouseListener(new MouseAdapter(){
#Override
public void mouseClicked(MouseEvent evt){
onClick(row, column);
}
});
return this;
}
}.setRowAndColumn(i, j);
buttons[i][j].setPreferredSize(new java.awt.Dimension(40, 40));
panel.add(buttons[i][j]);
}
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(panel);
frame.pack();
frame.setVisible(true);
}
});
}
//This method is called when the JToggleButton at [row][column] is clicked
private static void onClick(int row, int column){
//In this example all other buttons at the same row or column
//as the clicked one, are also selected
for(int i = 0; i < 8; ++i){
buttons[i][column].setSelected(true);
buttons[row][i].setSelected(true);
//I don't want to see visual changes yet
}
//All changes should be visualized now
}
}
Basically I want onClick to be executed as a transaction (visually).
Thanks in advance.
Related
I am trying to make minesweeper. When I click on the JButton I want the button to hide. I have accomplished this but the button does not cover the entire JPanel. It always leaves some of the panel on the top visible.
I have tried setting the preferred size, vertical and horizontal alignment.
Why is it doing this? How can I fix it?
class canvas extends JFrame {
public static JPanel[] panels;
public static Tile[] tiles;
canvas(int size){
JFrame theGUI = new JFrame();
panels = new JPanel[size*size]; //creates panels and tiles, the tiles contain color, if it is
a bomb ect.
tiles = new Tile[size*size];
Container con = theGUI.getContentPane();
Graphics g;
for(int i = 0; i < panels.length; i++) {
JPanel temp = new JPanel();
temp.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));//adds borders
temp.setBorder(BorderFactory.createLineBorder(Color.black,1));
JButton button = new JButton();
button.setBackground(Color.GRAY);
button.setAlignmentY(0.0f);//tried to see if vertical align would fix it, it didnt
button.setPreferredSize(new Dimension(70,70));
button.addActionListener(new Action() {
public void actionPerformed(ActionEvent event) {
button.setVisible(false);
}
});
temp.add(button);
Tile tempTile = new Tile();
panels[i] = temp;
tiles[i] = tempTile;
tiles[i].color = Color.green;
panels[i].setBackground(tiles[i].color);
con.add(panels[i]);
}
con.setLayout(new GridLayout(size,size));
theGUI.setTitle("mine sweeper");
theGUI.setSize(size*40, size*40);
theGUI.setVisible(true);
}
}
The problem I am trying to fix:
I think you can achieve your goal with simpler code. You just need to add the JButtons directly to a JPanel that uses GridLayout as its layout manager. Consider the following code.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
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;
import javax.swing.WindowConstants;
public class MineSweeper implements ActionListener, Runnable {
private JFrame frame;
public void actionPerformed(ActionEvent event) {
Object obj = event.getSource();
if (obj instanceof JButton) {
JButton button = (JButton) obj;
button.setVisible(false);
}
}
public void run() {
showGui();
}
private JButton createButton() {
JButton button = new JButton();
button.setPreferredSize(new Dimension(40, 40));
button.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
button.addActionListener(this);
return button;
}
private JPanel createMineField() {
JPanel mineField = new JPanel(new GridLayout(10, 10));
mineField.setBackground(Color.GREEN);
for (int i = 0; i < 100; i++) {
mineField.add(createButton());
}
return mineField;
}
private void showGui() {
frame = new JFrame("Mine Sweeper");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(createMineField(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
/**
* Start here.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new MineSweeper());
}
}
I have a problem with my TicTacToe game.
I want to write a method to check the winner condition.
In my Arbiter class,hasWinner() method i want to check the text value from JButton from the TicTacToeGUI. For example if the JButton[0][0], JButton[0][1],JButton[0][2] are equals. We will have a message that someone won the game.
But i don't have idea how to pass the JButton array to this hasWinner().
I try to keep my game logic in the Arbiter class.
I have three classes. Main class, TicTacToeGUI and Arbiter.
TicTacToeGUI:
import javax.swing.*;
import javax.swing.border.LineBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class TicTacToeGUI implements ActionListener {
private JFrame frame;
private JButton[][] board;
private JMenuBar menuBar;
private JMenu menu;
private JMenuItem newGame;
private JMenuItem quit;
private Arbiter arbiter;
public TicTacToeGUI() {
super();
this.arbiter = new Arbiter();
initializeMenuBar();
initializeBoard();
}
public void initializeBoard() {
frame = new JFrame();
frame.setTitle("Tic Tac Toe v0.1");
frame.setBounds(100, 100, 600, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new BorderLayout(0, 0));
frame.setResizable(false);
//Creating MENU
frame.setJMenuBar(menuBar);
frame.setVisible(true);
JPanel panel = new JPanel();
panel.setBorder(new LineBorder(new Color(0, 0, 0), 2));
frame.getContentPane().add(panel, BorderLayout.CENTER);
panel.setLayout(new GridLayout(3, 3, 2, 2));
//Add a JButton[3][3] array and actionListener
board = new JButton[3][3];
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board.length; j++) {
board[i][j] = new JButton("");
panel.add(board[i][j]);
board[i][j].addActionListener(this);
}
}
}
public void initializeMenuBar() {
//Create menu Bar
menuBar = new JMenuBar();
menu = new JMenu("MENU");
menuBar.add(menu);
newGame = new JMenuItem("New Game");
menu.add(newGame);
quit = new JMenuItem("Quit");
menu.add(quit);
//Add functionality to newGame menu item.
newGame.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent actionEvent) {
arbiter.setGame();
}
});
//Add functionality to quit menu item.
quit.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent actionEvent) {
System.exit(0);
}
});
}
#Override
public void actionPerformed(ActionEvent e) {
JButton pressed = (JButton) e.getSource();
arbiter.setText(pressed);
}
public void winner(){
JOptionPane.showMessageDialog(frame,
"Mamy zwycięzcę!!!",
"A winner is:",
JOptionPane.PLAIN_MESSAGE);
}
}
Arbiter:
import javax.swing.*;
import java.awt.*;
public class Arbiter {
private int player = 1;
private boolean winner = false;
public void setGame(){
}
public void reset(){
setGame();
}
public void hasWinner(JButton btn){
TicTacToeGUI win = new TicTacToeGUI();
if((btn[0][0] == btn[0][1]) && (btn[0][0] == btn[0][2])){
win.winner();
}
}
public void setText(JButton btn){
if (btn.getText().length() == 0){
btn.setFont(new Font("Comic Sans MS", Font.PLAIN, 60));
btn.setText(player == 1 ? "O" : "X");
switchPlayer(player);
}
hasWinner();
}
private void switchPlayer(int currentPlayer){
this.player = player == 1 ? 0 : 1;
}
}
I think your statement I try to keep my game logic in the Arbiter class is a good way to look at it. However, in my opinion, that would mean Arbiter should never be able to directly affect the GUI.
So in this edited Arbiter class you will notice a few differences.
public class Arbiter {
private int player = 1;
private String[][] gameValues = new String[3][3];
public void setGame() {
gameValues = new String[3][3];
}
public void reset() {
setGame();
}
public boolean hasWinner() {
if((gameValues[0][0].equals(gameValues[0][1])) && (gameValues[0][0].equals(gameValues[0][2]))) {
return true;
}
return false;
}
public void setText(int x, int y) {
if(player == 0) {
gameValues[x][y] = "X";
switchPlayer(1);
} else {
gameValues[x][y] = "O";
switchPlayer(0);
}
}
public String getBoardValue(int x, int y) {
return gameValues[x][y];
}
public String[][] getBoardValues() {
return gameValues;
}
private void switchPlayer(int newPlayer) {
this.player = newPlayer;
}
}
The main ones being hasWinner now returns a boolean so it is easy for the GUI to tell if there is a winner or not and a new variable called gameValues. gameValues stores all the current values of the game and can be accessed by methods such as getBoardValue and getBoardValues. This helps the project follow the Single Responsibility Principle which basically means one class should only handle one responsibility.
Next, the GUI class. You will notice a few differences here as well.
import java.awt.BorderLayout;
import java.awt.Color;
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.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
public class TicTacToeGUI implements ActionListener {
private JFrame frame;
private JButton[][] board;
private JMenuBar menuBar;
private JMenu menu;
private JMenuItem newGame;
private JMenuItem quit;
private Arbiter arbiter;
public TicTacToeGUI() {
super();
this.arbiter = new Arbiter();
initializeMenuBar();
initializeBoard();
}
public void initializeBoard() {
frame = new JFrame();
frame.setTitle("Tic Tac Toe v0.1");
frame.setBounds(100, 100, 600, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new BorderLayout(0, 0));
frame.setResizable(false);
//Creating MENU
frame.setJMenuBar(menuBar);
frame.setVisible(true);
JPanel panel = new JPanel();
panel.setBorder(new LineBorder(new Color(0, 0, 0), 2));
frame.getContentPane().add(panel, BorderLayout.CENTER);
panel.setLayout(new GridLayout(3, 3, 2, 2));
//Add a JButton[3][3] array and actionListener
board = new JButton[3][3];
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board.length; j++) {
board[i][j] = new JButton("");
panel.add(board[i][j]);
board[i][j].addActionListener(this);
}
}
refreshBoardValues();
}
public void initializeMenuBar() {
//Create menu Bar
menuBar = new JMenuBar();
menu = new JMenu("MENU");
menuBar.add(menu);
newGame = new JMenuItem("New Game");
menu.add(newGame);
quit = new JMenuItem("Quit");
menu.add(quit);
//Add functionality to newGame menu item.
newGame.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent actionEvent) {
arbiter.setGame();
}
});
//Add functionality to quit menu item.
quit.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent actionEvent) {
System.exit(0);
}
});
}
#Override
public void actionPerformed(ActionEvent e) {
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
if(board[i][j] == (JButton) e.getSource()) {
arbiter.setText(i, j);
refereshBoardValue(i, j);
if(arbiter.hasWinner()) {
winner();
}
return;
}
}
}
}
private void refreshBoardValues() {
String[][] currentValues = arbiter.getBoardValues();
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
board[i][j].setText(currentValues[i][j]);
}
}
}
private void refereshBoardValue(int x, int y) {
board[x][y].setText(arbiter.getBoardValue(x, y));
}
private void winner(){
JOptionPane.showMessageDialog(frame,
"Mamy zwycięzcę!!!",
"A winner is:",
JOptionPane.PLAIN_MESSAGE);
}
}
The main differences are the methods refreshBoardValues and refereshBoardValue whose job is to get an up to date value from the game when an action is performed. The main actionPerformed performed logic has changed as well.
It now gets the position of a JButton and tells the arbiter that button in position xy has been pressed. This updates the game value in position xy and then that value is sent back to the GUI and reflected on the JButton. Finally the a check is carried out to see if any win conditions are made. The rest is the same.
Currently displays a GUI with an 8x8 grid of randomized colored buttons. The newButton is to reset the score display to 0 and reset the grid with a fresh like it does on startup after being clicked. I haven't been able to find many solutions other than that it's to do with the way Java displays it's buttons and the way layering works. Here are the 2 classes I'm using.
import javax.swing.JFrame;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.JPanel;
import java.awt.Color;
public class ShinyButtonsApp extends JFrame implements ActionListener {
private static byte ROWS = 8;
public int useThis;
ShinyButtons shiny = new ShinyButtons();
public static ImageIcon[] icons = {new ImageIcon("RedButton.png"),
new ImageIcon("OrangeButton.png"),
new ImageIcon("YellowButton.png"),
new ImageIcon("GreenButton.png"),
new ImageIcon("BlueButton.png"),
new ImageIcon("LightGrayButton.png"),
new ImageIcon("DarkGrayButton.png")};
public ShinyButtonsApp(String title) {
super(title); // Set title of window
setDefaultCloseOperation(EXIT_ON_CLOSE); // allow window to close
setSize(578, 634); // Set size of window
setResizable(false);
getContentPane().setLayout(null);
JLabel aLabel = new JLabel("Score: ");
aLabel.setLocation(10, 570);
aLabel.setSize(80,30);
getContentPane().add(aLabel);
JTextField scoreField = new JTextField();
scoreField.setText(Integer.toString(shiny.score));
scoreField.setEditable(false);
scoreField.setHorizontalAlignment(JTextField.RIGHT);
scoreField.setLocation(60, 570);
scoreField.setSize(120,30);
scoreField.setBackground(Color.WHITE);
getContentPane().add(scoreField);
JButton newButton = new JButton("New Game");
newButton.addActionListener(this);
newButton.setLocation(348,570);
newButton.setSize(110,30);
getContentPane().add(newButton);
JButton quitButton = new JButton("Quit");
quitButton.setLocation(468,570);
quitButton.setSize(80,30);
getContentPane().add(quitButton);
resetButtons2();
}
public void actionPerformed(ActionEvent e) {
shiny.score = 0;
shiny.resetButtons();
resetButtons2();
}
public void resetButtons2() {
for (int r=0; r<ROWS; r++) {
for (int c=0; c<ROWS; c++) {
ImageIcon image1 = icons[(int)shiny.getButton(r,c)];
JButton button = new JButton(image1);
button.setLocation(10+(69*r),10+(69*c));
button.setSize(69,69);
button.setBorder(BorderFactory.createLineBorder(Color.GRAY,1));
getContentPane().add(button);
}
}
}
public static void main(String[] args) {
ShinyButtonsApp frame;
frame = new ShinyButtonsApp("Shiny Buttons"); // Create window
frame.setVisible(true); // Show window
}
}
and
import javax.swing.JFrame;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.JPanel;
import java.awt.Color;
public class ShinyButtons extends JPanel{
public static byte RED = 0;
public static byte ORANGE = 1;
public static byte YELLOW = 2;
public static byte GREEN = 3;
public static byte BLUE = 4;
public static byte LIGHT_GRAY = 5;
public static byte DARK_GRAY = 6;
public static byte ROWS = 8;
public byte[][] buttonTable;
public int score = 0;
public ShinyButtons() {
buttonTable = new byte[ROWS][ROWS];
resetButtons();
}
public void resetButtons() {
for (int r=0; r<ROWS; r++)
for (int c=0; c<ROWS; c++)
buttonTable[r][c] = (byte)(Math.random()*7);
}
public byte getButton(int r, int c) { return buttonTable[r][c]; }
public int getScore() { return score; }
}
Building on to what this answer points out (using layout managers instead of setting size, as you should be doing) you could reset the the images just by looping through the components (JLabels) of the JPanel and changing their icons.
This particular example uses JLabels with MouseListeners but it could easily be switched to JButtons with ActionListeners
newGame.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
reset(iconPanel, icons); <--- call reset method from below
score = 0;
scoreField.setText(String.valueOf(score));
}
});
....
private void reset(JPanel panel, ImageIcon[] icons) {
Component[] comps = panel.getComponents();
Random random = new Random();
for(Component c : comps) {
if (c instanceof JLabel) {
JLabel button = (JLabel)c;
int index = random.nextInt(icons.length);
button.setIcon(icons[index]);
}
}
}
Here's the complete running code. You just need to replace the image paths.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Random;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.border.LineBorder;
public class CircleImages {
private int score = 0;
private JTextField scoreField = new JTextField(10);
public CircleImages() {
scoreField.setEditable(false);
final ImageIcon[] icons = createImageIcons();
final JPanel iconPanel = createPanel(icons, 8);
JPanel bottomLeftPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
bottomLeftPanel.add(new JLabel("Score: "));
bottomLeftPanel.add(scoreField);
JPanel bottomRightPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING));
JButton newGame = new JButton("New Game");
bottomRightPanel.add(newGame);
JButton quit = new JButton("Quit");
bottomRightPanel.add(quit);
JPanel bottomPanel = new JPanel(new GridLayout(1, 2));
bottomPanel.add(bottomLeftPanel);
bottomPanel.add(bottomRightPanel);
newGame.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
reset(iconPanel, icons);
score = 0;
scoreField.setText(String.valueOf(score));
}
});
JFrame frame = new JFrame();
frame.add(iconPanel);
frame.add(bottomPanel, BorderLayout.PAGE_END);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private void reset(JPanel panel, ImageIcon[] icons) {
Component[] comps = panel.getComponents();
Random random = new Random();
for(Component c : comps) {
if (c instanceof JLabel) {
JLabel button = (JLabel)c;
int index = random.nextInt(icons.length);
button.setIcon(icons[index]);
}
}
}
private JPanel createPanel(ImageIcon[] icons, int gridSize) {
Random random = new Random();
JPanel panel = new JPanel(new GridLayout(gridSize, gridSize));
for (int i = 0; i < gridSize * gridSize; i++) {
int index = random.nextInt(icons.length);
JLabel label = new JLabel(icons[index]);
label.addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent e) {
score += 1;
scoreField.setText(String.valueOf(score));
}
});
label.setBorder(new LineBorder(Color.GRAY, 2));
panel.add(label);
}
return panel;
}
private ImageIcon[] createImageIcons() {
String[] files = {"blackcircle.png",
"bluecircle.png",
"greencircle.png",
"greycircle.png",
"orangecircle.png",
"redcircle.png",
"yellowcircle.png"
};
ImageIcon[] icons = new ImageIcon[files.length];
for (int i = 0; i < files.length; i++) {
icons[i] = new ImageIcon(getClass().getResource("/circles/" + files[i]));
}
return icons;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new CircleImages();
}
});
}
}
You are creating a new set of buttons in resetButtons2() and placing them on top (or rather under) of the already existing set of buttons in the same locations. You should create the set of buttons once and only update their icons upon reset.
You should do a number of things:
Use a proper layout manager, e.g., GridLayout
Create the 8x8 grid of buttons only once and replace their icons when needed
Call invalidate/repaint to refresh the content pane
And for a JFrame you don't need getContentPane().add(...), you can directly do add(...)
Two things.
First, make sure you remove the existing buttons first. Alternatively, you could simply update the state of the buttons. This would require you to create an array or List of buttons first, which your reset method would then iterate over and update their properties as required.
Second, make use of an appropriate layout manager. A null layout ias a very bad idea. You do not control the font metrics of the underlying platform and this will change how your buttons look on different systems, making your UI less dynamic then it should be
I know that the same question has been asked many times, but I really don't seem to find the error in my code that hinders the object of type JPanel to be displayed in the JFrame. Here is the constructor of the class that extends JFrame:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Game extends JFrame implements ActionListener {
private static final long serialVersionUID = 1L;
private Board board;
public Game() {
super("Game");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBackground(Color.WHITE);
board = new Board();
add(board, BorderLayout.CENTER);
JButton button = new JButton("Start new game");
button.setFocusPainted(false);
button.addActionListener(this);
JPanel control = new JPanel();
control.setBackground(Color.WHITE);
control.add(button);
add(control, BorderLayout.SOUTH);
pack();
setResizable(false);
setVisible(true);
}
And this one is the constructor of the class that extends JPanel:
public class Board extends JPanel implements ActionListener {
public Board() {
setBackground(Color.WHITE);
setLayout(new GridLayout(NUMBER_OF_ROWS, NUMBER_OF_COLUMNS));
setBorder(BorderFactory.createEmptyBorder(20, 20, 0, 20));
board = new Cell[NUMBER_OF_ROWS][NUMBER_OF_COLUMNS];
for (int row = 0; row < NUMBER_OF_ROWS; row++) {
for (int column = 0; column < NUMBER_OF_COLUMNS; column++) {
board[row][column] = new Cell(this, row, column);
add(board[row][column]);
}
}
}
When I run the main method (which I didn't show here), it shows only the frame and the button. If someone could give a hint on this, I would be very thankful.
It seems to show up just fine in this close variant of the code that is runnable (a MCTaRE).
Note that I put some space in the GridLayout and changed the colors to make panel boundaries more clear.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Game extends JFrame {
private static final long serialVersionUID = 1L;
private Board board;
public Game() {
super("Game");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBackground(Color.WHITE);
board = new Board();
add(board, BorderLayout.CENTER);
JButton button = new JButton("Start new game");
button.setFocusPainted(false);
JPanel control = new JPanel();
control.setBackground(Color.GREEN);
control.add(button);
add(control, BorderLayout.SOUTH);
pack();
setResizable(false);
setVisible(true);
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
new Game();
}
};
// Swing GUIs should be created and updated on the EDT
// http://docs.oracle.com/javase/tutorial/uiswing/concurrency
SwingUtilities.invokeLater(r);
}
}
/** A pseudo Cell */
class Cell extends JButton {
Cell(JComponent parent, int row, int column) {
super(row + " " + column);
}
}
/** And this one is the constructor of the class that extends JPanel */
class Board extends JPanel {
int NUMBER_OF_ROWS=3;
int NUMBER_OF_COLUMNS=4;
Cell[][] board;
public Board() {
setBackground(Color.RED);
setLayout(new GridLayout(NUMBER_OF_ROWS, NUMBER_OF_COLUMNS, 5, 5));
setBorder(BorderFactory.createEmptyBorder(20, 20, 0, 20));
board = new Cell[NUMBER_OF_ROWS][NUMBER_OF_COLUMNS];
for (int row = 0; row < NUMBER_OF_ROWS; row++) {
for (int column = 0; column < NUMBER_OF_COLUMNS; column++) {
board[row][column] = new Cell(this, row, column);
add(board[row][column]);
}
}
}
}
I want to make an interface for a Minesweeper game in java and i have this for now:
Container pane = getContentPane();
pane.setLayout(new GridLayout(10, 10));
for (int i = 1; i <= 100; i++)
{
JButton button = new JButton();
pane.add(button);
}
I don't want the JButtons to have any text at start, but when i click on a certain button i need to get that buttons row and column in the gridview, i will call a function that will give me a number of bombs near that point and i will put that number as the text from that button that was clicked, any help? i don't know how to get a specific button from a gridview so i can change it's propreties.
An easy way to do this is to create an ActionListener class of your own that gets a row and column passed into it when these buttons are created. When their action is fired, they can just pass that in to the function you're referring to. Something like this:
package com.sandbox;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Sandbox {
public static void main(String[] args) {
Container pane = //...
pane.setLayout(new GridLayout(10, 10));
for (int r = 0; r < 10; r++) {
for (int c = 0; c < 10; c++) {
JButton button = new JButton();
button.addActionListener(new PositionAwareActionListener(r, c));
pane.add(button);
}
}
}
private static class PositionAwareActionListener implements ActionListener {
private int r;
private int c;
public PositionAwareActionListener(int r, int c) {
this.r = r;
this.c = c;
}
#Override
public void actionPerformed(ActionEvent e) {
//callYourFunction(r, c);
}
}
}