This is copied and adapted from the example I received from an earlier question
I have 2 issues at the moment
Firstly, I can only get one JButton to appear on screen, then that JButton is not responding when I press it.
Also, how can I stop the first square from appearing?
I know the program is in one big blob ATM, I will separate into individual classes once I sort these issues out.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class SwingPaintDemo3 {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
static void createAndShowGUI() {
System.out.println("Created GUI on EDT? "+
SwingUtilities.isEventDispatchThread());
JFrame f = new JFrame("Swing Paint Demo");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new MyPanel());
f.pack();
f.setLayout(null);
JButton seed = new JButton ("Seed");
seed.setBounds(1050,50,100,50);
f.add(seed);
seed.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
System.out.println("Start");
}
});
JButton start = new JButton ("Start");
start.setBounds(1050,150,100,50);
f.add(start);
JButton stop = new JButton ("Stop");
stop.setBounds(1050,250,100,50);
//f.add(stop);
JButton reset = new JButton ("Reset");
reset.setBounds(1050,350,100,50);
//f.add(reset);
f.setVisible(true);
int lifegrid [] [] [] = new int [42] [62] [2];
for (int i=0; i<42; i++) {
for (int j=0; j<62; j++) {
lifegrid [i] [j] [0] = 0;
lifegrid [i] [j] [1] = 0;
}
}
}
}
class MyPanel extends JPanel {
int lifegrid [] [] [] = new int [62] [42] [2];
int squareX = 0;
int squareY = 0;
int gridX = 0;
int gridY = 0;
public MyPanel() {
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
squareX = e.getX();
squareY = e.getY();
if ((squareX>50 & squareX<950) & (squareY>50 & squareY <650) ){
gridX =(squareX-50)/15+1;
gridY =(squareY-50)/15+1;
squareX = (squareX -50)/15 * 15 + 50;
squareY = (squareY -50)/15 * 15 + 50;
lifegrid [gridX] [gridY] [0] = 1;
System.out.println(gridX + " " + gridY);
repaint(squareX,squareY,15,15);}
else {}
}
});
}
public Dimension getPreferredSize() {
return new Dimension(1280,800);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.RED);
g.fillRect(squareX,squareY,13,13);
g.setColor(Color.BLACK);
g.drawRect(squareX,squareY,13,13);
}
}
You have 2 buttons.
One button's face reads 'Seed'. When you press it, your action listener will print "Start".
The other button's face reads 'Start'. It has no action listener, therefore, if pressed, nothing happens.
SOURCE: Just.. read your code, it's right there.
I assume that's a bug. If not, that is quite confusing: Why would pressing the button that does NOT have 'Start' written on it, print 'Start' to sysout?
You then add both buttons to a panel with dubious layouting.
I assume you're pressing the only button you can see (With 'Start' on it), because it is right on top of the other button, and you observe nothing.
Which is exactly what you programmed.
Probable solutions:
Fix your layouting, or use a layout manager. Then press the right button (the one that reads 'Seed')
Add an action listener to your start button and make it print 'start'.
Fix the bug where clicking the Seed button prints Start. You should make that print 'Seed'.
Related
package javaapplication3;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
class BattleShip2 extends JFrame implements ActionListener {
JButton[][] array2dtop = new JButton[10][10];
BattleShip2(String title) { //Board Display
super(title);//show Title
setLayout(new FlowLayout()); // button posistion
for(int x = 0; x < array2dtop.length; x++) {
for(int y = 0; y < array2dtop.length; y++) {
array2dtop[x][y] = new JButton(String.valueOf((x * 10) + y)); //display
array2dtop[x][y].setBounds(20,40,140,20);
array2dtop[x][y].setActionCommand("x"); //itself value
array2dtop[x][y].addActionListener(this);
add(array2dtop[x][y]);
}
}
}
public void actionPerformed(ActionEvent evt) { //operation
String cmd = evt.getActionCommand();
if(cmd == "x") {
System.out.println("x");
}
}
}
public class pratice3 {
public static void main(String[] args) {
BattleShip2 board = new BattleShip2("BattleShip");
board.setSize(500, 400);
board.setLocation(250, 250);
board.setDefaultCloseOperation(board.EXIT_ON_CLOSE); //Press x to EXIT
board.setVisible(true);
}
}
Hi, i am creating a battleship game, and my idea is when the user or AI hit the button, it could show ship size
For example, there have 3 ships: ship1(size = 3), ship2(size = 2), ship3(size = 1), and when the user/AI hit the ship1, and they see 3, they will know they hit ship1
but I am having troubles on the setActioncommand
on the code,
array2dtop[x][y].setActionCommand("x")
I want to assign or declare a integer(the size of the ship) into array2dtop[x][y]
but I have no idea but assign a string and how can I use it in the actionPerformed
I want to assign or declare a integer(the size of the ship) into array2dtop[x][y]
You can just parse the string to an integer using Integer.parseInt:
class BattleShip2 extends JFrame implements ActionListener {
JButton[][] array2dtop = new JButton[10][10];
BattleShip2(String title) {
super(title);
setLayout(new GridLayout(10, 10, 5, 5));
for (int x = 0; x < array2dtop.length; x++) {
for (int y = 0; y < array2dtop.length; y++) {
array2dtop[x][y] = new JButton(String.valueOf((x * 10) + y));
array2dtop[x][y].setActionCommand(String.valueOf(3));
array2dtop[x][y].addActionListener(this);
// Force buttons to be square.
Dimension dim = array2dtop[x][y].getPreferredSize();
int buttonSize = Math.max(dim.height, dim.width);
array2dtop[x][y].setPreferredSize(new Dimension(buttonSize, buttonSize));
add(array2dtop[x][y]);
}
}
}
public void actionPerformed(ActionEvent evt) {
int cmd = Integer.parseInt(evt.getActionCommand());
if (cmd == 3) {
System.out.println(3);
}
}
}
public class pratice3 {
public static void main(String[] args) {
BattleShip2 board = new BattleShip2("BattleShip");
board.pack();
board.setLocationRelativeTo(null);
board.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
board.setVisible(true);
}
}
Notes:
I changed the layout to GridLayout with the same vertical and horizontal gaps as FlowLayout's defaults. It will assure that all button have the same size.
Don't use setBounds, let the layout manager take care of that.
I added 3 lines that make the buttons square, you can remove that.
Instead of using setSize for a JFrame, use pack.
Setting the location using board.setLocationRelativeTo(null) (After the call to pack) is usually a better idea since you don't know the size of the screen.
board.EXIT_ON_CLOSE should be accessed in a static way: JFrame.EXIT_ON_CLOSE (for example).
When calling Integer.parseInt, you might want to catch NumberFormatException.
With that being said, there are other ways to achieve this, such as using setClientProperty on the buttons, or just passing the number to the ActionListener's constructor.
I'm trying to use a timer to change the position of a JLabel, from one spot on my JPanel to another. I'm not sure if I could use say .getLocation(), then change only the horizontal x value, and finally use .setLocation() to effectively modify the JLabel. I've also used .getBounds and .setBounds, but am still unsure how I can obtain the old horizontal x value to change and reapply to the new x value.
The code I tried looks something like this, but neither is a valid way to change the position of the JLabel.
// mPos is an arraylist of JLabels to be moved.
for(int m = 0; m < mPos.size(); m++){
mPos.get(m).setLocation(getLocation()-100);
}
or
for(int m = 0; m < mPos.size(); m++){
mPos.get(m).setBounds(mPos.get(m).getBounds()-100);
}
If I could just get the position of the horizontal x value I can change the position of the label.
Try with Swing Timer if you are looking for some animation.
Please have a look at How to Use Swing Timers
Here is the sample code:
int delay = 1000; //milliseconds
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
//...Perform a task...
}
};
new Timer(delay, taskPerformer).start();
Find a Sample code here
Sample code: (Move Hello World message 10px horizontally left to right at interval of 200 ms)
private int x = 10;
...
final JPanel panel = new JPanel() {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawString("Hello World", x, 10);
}
};
int delay = 200; // milliseconds
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
x += 10;
if (x > 100) {
x = 10;
}
panel.repaint();
}
};
new Timer(delay, taskPerformer).start();
I made a similar example just so you can get the basic jest of it, try copy pasting this in a new class called "LabelPlay" and it should work fine.
import java.awt.EventQueue;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class LabelPlay {
private JFrame frame;
private JLabel label;
private Random rand;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
LabelPlay window = new LabelPlay();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public LabelPlay() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 659, 518);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
label = new JLabel("YEEEHAH!");
label.setBounds(101, 62, 54, 21);
frame.getContentPane().add(label);
JButton btnAction = new JButton("Action!");
rand = new Random();
btnAction.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
int a = rand.nextInt(90)+10;
int b = rand.nextInt(90)+10;
int c = rand.nextInt(640)+10;
int d = rand.nextInt(500)+10;
label.setBounds(a, b, c, d);
}
});
btnAction.setBounds(524, 427, 89, 23);
frame.getContentPane().add(btnAction);
}
}
If you want this to happen in a loop at certain times, you can just put it in a loop and use Thread.sleep(amount of miliseconds) in the loop before you run the code.
Why don't you create a JLabel at position a, set it to visible, and another one at position b, setting it to not visible? After the timer is up, hide the first and show the second.
Are you planning on creating some moving imageIcon for some type of game? Or some label that moves pretty much everywhere ?
I would use an Absolute Layout and set Location manually everytime.
myPanel.setLayout(null);
// an initial point
int x = 100;
int y =100;
while (
//some moving pattern
x++; // 1 pixel per loop
y+=2; // 2 pixels per loop
myLabel.setLocation(x,y);
}
I am coding a little game in which i have taken a grid of JButtons in a JFrame and i want to refresh the colors of the buttons contained in a JFrame,which is already visible.As explained below
void foo(){
mainFrame.setVisible(true);//mainFrame is defined at class level.
//color update code for the buttons.
mainFrame.setVisible(true);
}
Result i am getting is not as expected and my screen gets freeze .Isn't it the right way to achieve what i wanted?
EDIT
ok i am explaining it in detail what i want to achieve.i have a class,as:-
import javax.swing.*;
import java.awt.*;
import java.util.*;
class Brick extends JButton{
public void setRandomColors(){
int random = (int) (Math.random()*50);
if(random%13==0){
this.setBackground(Color.MAGENTA);
}
else if(random%10==0){
this.setBackground(Color.red);
}
else if(random%9==0){
this.setBackground(Color.yellow);
}
else if(random%7==0){
this.setBackground(Color.orange);
}
else if(random%2==0){
this.setBackground(Color.cyan);
}
else{
this.setBackground(Color.PINK);
}
}
public void setBlackColor(){
this.setBackground(Color.black);
}
}
class Grid {
JFrame mainGrid = new JFrame();
ArrayList<Brick> bunchOfBricks = new ArrayList<>();
int gridLength = 8;//gridlenth is equals to gridweight as i have considered a Square grid.
int totalBricks = gridLength*gridLength;
public void formBunchOfBricks(){
for(int i=0;i<totalBricks;i++){
bunchOfBricks.add(new Brick());
}
}
public void formColoredGrid(){
Brick aBrick;
mainGrid.setLayout(new GridLayout(8,8));
for(int i=0;i<totalBricks;++i){
aBrick = (bunchOfBricks.get(i));
aBrick.setRandomColors();
mainGrid.add(aBrick);
}
mainGrid.setVisible(true);//its ok upto here iam getting randomly colored Frame of Bricks or so called JButtons.
delay(15);//Sorry for this one,i warn you not to laugh after looking its defination.
}
/*
I want following function to do following things:-
1.it should firstly display the Grid whose all buttons are black Colored.
2.After some time the original colored,first Row of grid formed by formColoredGrid should be displayed and all the rest Rows should be black.
3.Then second row turns colored and all other rows should be black......and so on upto last row of Grid.
*/
public void movingRows(){
setGridBlack();
delay(1);//see in upper method,for this horrible thing.
for(int i=0;i<gridLength;++i){
setGridBlack();
for (int j=0;j<gridLength;++j){
Brick aBrick = bunchOfBricks.get((gridLength*i)+j);
aBrick.setRandomColors();//Bricks are colored Row by Row.
}
delay(5);//already commented this nonsense.
mainGrid.setVisible(true);//using setVisible again,although this frame is already visible,when i called formColoredGrid.
setGridBlack();
}
//oh! disappointing,i have almost broken my arm slamming it on table that why the function result in a screen full of black buttons.
}
public void setGridBlack(){
for(int i=0;i<totalBricks;i++){
bunchOfBricks.get(i).setBlackColor();
}
}
public void delay(int a){
for ( int i=0;i<90000000;++i){
for(int j=0;j<a;++j){
}
}
}
public static void main(String args[]){
Grid g1 = new Grid();
g1.formBunchOfBricks();
g1.formColoredGrid();
g1.movingRows();
}
}
Please Help me what is the way out?
Your problem is in code not shown here:
//color update code for the buttons.
You're likely running a loop that never ends on the Swing event thread, possibly a never-ending while loop that polls the state of something(a guess), freezing your GUI. Solution: don't do this; don't use a continuous polling loop. Instead, change the colors based on responses to events as Swing is event-driven.
For better more specific help, please show the offending code and tell us more about your program.
Edit
If you're trying to show colored rows, one by one marching down the board, then my guess is right, you'll want to use a Swing Timer, one that uses an int index to indicate which row is being displayed in color. You'd increment the index inside of the Timer's ActionPerformed class, and then when all rows have been displayed stop the Timer. For example something like so:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import javax.swing.*;
#SuppressWarnings("serial")
public class MyGrid extends JPanel {
private static final int GRID_LENGTH = 8;
private static final Color BTN_BACKGROUND = Color.BLACK;
private static final Color[] COLORS = { Color.MAGENTA, Color.CYAN,
Color.RED, Color.YELLOW, Color.ORANGE, Color.PINK, Color.BLUE,
Color.GREEN };
private static final int PREF_W = 400;
private static final int PREF_H = PREF_W;
private static final int TIMER_DELAY = 800;
private JButton[][] buttonGrid = new JButton[GRID_LENGTH][GRID_LENGTH];
private Map<JButton, Color> btnColorMap = new HashMap<>();
private Random random = new Random();
public MyGrid() {
setLayout(new GridLayout(GRID_LENGTH, GRID_LENGTH));
for (int row = 0; row < buttonGrid.length; row++) {
for (int col = 0; col < buttonGrid[row].length; col++) {
JButton btn = new JButton();
btn.setBackground(BTN_BACKGROUND);
// !! add action listener here?
add(btn);
buttonGrid[row][col] = btn;
}
}
new Timer(TIMER_DELAY, new TimerListener()).start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
public void resetAllBtns() {
for (JButton[] row : buttonGrid) {
for (JButton btn : row) {
btn.setBackground(BTN_BACKGROUND);
}
}
}
private class TimerListener implements ActionListener {
private int row = 0;
#Override
public void actionPerformed(ActionEvent e) {
resetAllBtns(); // make all buttons black
if (row != buttonGrid.length) {
for (int c = 0; c < buttonGrid[row].length; c++) {
int colorIndex = random.nextInt(COLORS.length);
Color randomColor = COLORS[colorIndex];
buttonGrid[row][c].setBackground(randomColor);
// !! not sure if you need this
btnColorMap.put(buttonGrid[row][c], randomColor);
}
row++;
} else {
// else we've run out of rows -- stop the timer
((Timer) e.getSource()).stop();
}
}
}
private static void createAndShowGui() {
MyGrid mainPanel = new MyGrid();
JFrame frame = new JFrame("MyGrid");
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();
}
});
}
}
Please have a look at the Swing Timer Tutorial as well.
Edit 2
You ask:
but what is the reason of failure of this program,is it the useless delay function?
Your delay method does nothing but busy calculations on the Swing event thread:
public void delay(int a) {
for (int i = 0; i < 90000000; ++i) {
for (int j = 0; j < a; ++j) {
}
}
}
It's little different from a crude attempt at calling Thread.sleep(...), and is crude because you can't explicitly control how long it will run as you can with thread sleep. Again, the problem is that you're making these calls on the Swing event dispatch thread or EDT, the single thread that is responsible for all Swing drawing and user interactions. Blocking this thread will block your program making it non-running or frozen.
I just need to get it to alternate between "X" and "O" for the turns but it's only giving me X's.
import java.awt.GridLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.*;
public class tictactoe {
public static final int FRAME_WIDTH = 700;
public static final int FRAME_HEIGHT = 200;
public static void main(String[] args)
{
int slots = 9;
final JButton[] gameButton = new JButton[9];
JPanel ticTacToeBoard = new JPanel();
ticTacToeBoard.setLayout(new GridLayout(3, 3));
JButton clearButtons = new JButton("New Game");
for (int i = 0; i < slots; i++)
{
gameButton[i] = new JButton();
ticTacToeBoard.add(gameButton[i]);
final int countTurns = i;
gameButton[i].addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Object clicked = e.getSource();
int turns = 1;
for (int p = 0; p < 9; p++)
{
if(clicked == gameButton[countTurns] && turns < 10)
{
if (!(turns % 2 == 0))
{
((JButton)e.getSource()).setText("X");
turns++;
}
else
{
((JButton)e.getSource()).setText("O");
turns++;
}
}
}
}
});
final int integerHack = i;
clearButtons.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
gameButton[integerHack].setText("");
}
});
}
JButton exit = new JButton("Exit");
exit.setActionCommand("EXIT");
exit.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
if (cmd == "EXIT")
{
System.exit(FRAME_WIDTH);
}
}
});
JPanel rightPanel = new JPanel();
JLabel wonLabel = new JLabel();
rightPanel.setLayout(new GridLayout(1, 3));
rightPanel.add(wonLabel);
rightPanel.add(clearButtons);
rightPanel.add(exit);
JFrame mainFrame = new JFrame();
mainFrame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
mainFrame.setVisible(true);
mainFrame.setLayout(new GridLayout(1,2));
mainFrame.add(ticTacToeBoard);
mainFrame.add(rightPanel);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Look at your actionPerformed method. Every time a click happens, you set turns to 1. As a result, !(turns % 2 == 0) will always evaluate true, and you'll always draw an X.
Just by quickly looking at your code, I would guess it is because your turn variable is local in all the ActionListener objects. Therefore, the turn variable is always 1 and you always run into the first if case. So the turn variable is always recreated on the stack as soon as you get a callback in the actionPerformed method. For a quick fix and test, try to put the turn variable in the tictactoe class and see if that helps.
The trouble is with the turns variable in your actionPerformed. If you want to keep a track of it you should move that out from your method.
Firstly, as the other people have also said, you want "turns" to be initialized outside all your loops.
Secondly, I would like to point out a typo:
if(clicked == gameButton[countTurns] && turns < 10)
should be
if(clicked == gameButton[p] && turns < 10)
...unless you really want to change each button's text from X to O nine times each time a button is clicked.
But even fixing that typo is pointless. Why loop through to find a specific button when it doesn't matter which specific button it is? All the buttons have the same action handler, anyway, just nine separate copies of it, because you are creating nine identical copies each time around.
Instead, because all the buttons do the same thing, you should have one action handler for all the buttons. If you're not sure how that's done, you create it outside your button making loop and assign it to a variable, and then you put in that variable when you assign each button's action handler, e.g.
gameButton[i].addActionListener(myActionListener);
Okay so I am making a 2d array of JToggleButtons. I got the action listener up and going, but I have no way to tell which button is which.
If I click one, all it returns is something like
javax.swing.JToggleButton[,59,58,19x14,alignmentX=0.0,alignmentY=0.5,border=javax.swing.plaf.BorderUIResource$CompoundBorderUIResource#53343ed0,flags=296,maximumSize=,minimumSize=,preferredSize=,defaultIcon=,disabledIcon=,disabledSelectedIcon=,margin=javax.swing.plaf.InsetsUIResource[top=2,left=14,bottom=2,right=14],paintBorder=true,paintFocus=true,pressedIcon=,rolloverEnabled=false,rolloverIcon=,rolloverSelectedIcon=,selectedIcon=,text=]
Is there anyway to stick some sort of item or number in the button object to associate each button?
And then when the button is clicked I can retrieve that item or number that was given to it?
Here is my button generator code. (How could I make "int l" associate (and count) to each button made, when it is called, it will return that number, or something along those lines.
JToggleButton buttons[][] = new JToggleButton[row][col];
int l = 0;
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
buttons[i][j] = new JToggleButton("");
buttons[i][j].setSize(15,15);
buttons[i][j].addActionListener(new e());
panel.add(buttons[i][j]);
l++;
}
}
ActionListner
public class e implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
System.out.println(source);
}
}
variable "source" is what I use to get my data, so how can int l, be returned through "source" (as its unique value for the unique button clicked) as a button is clicked?
Thanks,
-Austin
very simple way is add ClientProperty to the JComponent, add to your definition into loop e.g.
buttons[i][j].putClientProperty("column", i);
buttons[i][j].putClientProperty("row", j);
buttons[i][j].addActionListener(new MyActionListener());
rename e to the MyActionListener and change its contents
public class MyActionListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
JToggleButton btn = (JToggleButton) e.getSource();
System.out.println("clicked column " + btn.getClientProperty("column")
+ ", row " + btn.getClientProperty("row"));
}
EDIT:
for MinerCraft clone isn't required to implements ony of Listeners, there is only about Icon, find out that in this code (don't implement any of Listeners anf remove used ItemListener)
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ButtonsIcon extends JFrame {
private static final long serialVersionUID = 1L;
private Icon errorIcon = UIManager.getIcon("OptionPane.errorIcon");
private Icon infoIcon = UIManager.getIcon("OptionPane.informationIcon");
private Icon warnIcon = UIManager.getIcon("OptionPane.warningIcon");
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
ButtonsIcon t = new ButtonsIcon();
}
});
}
public ButtonsIcon() {
setLayout(new GridLayout(2, 2, 4, 4));
JButton button = new JButton();
button.setBorderPainted(false);
button.setBorder(null);
button.setFocusable(false);
button.setMargin(new Insets(0, 0, 0, 0));
button.setContentAreaFilled(false);
button.setIcon((errorIcon));
button.setRolloverIcon((infoIcon));
button.setPressedIcon(warnIcon);
button.setDisabledIcon(warnIcon);
add(button);
JButton button1 = new JButton();
button1.setBorderPainted(false);
button1.setBorder(null);
button1.setFocusable(false);
button1.setMargin(new Insets(0, 0, 0, 0));
button1.setContentAreaFilled(false);
button1.setIcon((errorIcon));
button1.setRolloverIcon((infoIcon));
button1.setPressedIcon(warnIcon);
button1.setDisabledIcon(warnIcon);
add(button1);
button1.setEnabled(false);
final JToggleButton toggleButton = new JToggleButton();
toggleButton.setIcon((errorIcon));
toggleButton.setRolloverIcon((infoIcon));
toggleButton.setPressedIcon(warnIcon);
toggleButton.setDisabledIcon(warnIcon);
toggleButton.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent e) {
if (toggleButton.isSelected()) {
} else {
}
}
});
add(toggleButton);
final JToggleButton toggleButton1 = new JToggleButton();
toggleButton1.setIcon((errorIcon));
toggleButton1.setRolloverIcon((infoIcon));
toggleButton1.setPressedIcon(warnIcon);
toggleButton1.setDisabledIcon(warnIcon);
toggleButton1.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent e) {
if (toggleButton1.isSelected()) {
} else {
}
}
});
add(toggleButton1);
toggleButton1.setEnabled(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setVisible(true);
}
}
Just add the row and column data to each listener. You could add an explicit constructor, but I suggest adding a little method (which may have more added to it later).
buttons[i][j].addActionListener(e(i, j));
...
private ActionListener e(final int i, final int j) {
return new ActionListener() {
// i and j available here
...
(In JDK8 you should be able to use a lambda to reduce the syntax clutter.)
And then renaming it with a better name.
I made a minesweeper game and ran into a similar problem. One of the only ways you can do it, is to get the absolute location of the clicked button, then divide that by the x and y between buttons, so for me it was
if ((e.getComponent().getX() != (randx) * 25 && e.getComponent().getY() != (randy) * 25) &&bomb[randx][randy] == false) {
This code was to check if the area had bombs. So I had 25 x and y difference between location of bombs. That will just give you a general idea on how to do this.
I believe: (x - x spacing on left side) / buffer - 1 would work.
Instead of 'e.getSource()' you can always call 'e.getActionCommand()'. For each button you can specify this by:
JButton button = new JButton("Specify your parameters here"); /*you get these from getActionCommand*/
button.setText("title here"); /*as far as I remember*/