Related
I am working on a simple TicTacToe game with java swing and everything works properly, but whenever the GUI updates the layout changes. This happens with the buttons getting bigger when they are pressed and change to display an 'x' or an 'o' or when the entire game stops and displays a new label saying who won. I'm pretty much a beginner when it comes to programs like this, and the code itself is a huge hodgepodge of copy-pastes from programs that I have made with each separate components, so I figure that could be a reason for this issue.
Code below:
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.Timer;
import java.text.DecimalFormat;
public class test extends JFrame {
private JButton [] buttons = new JButton[9];
private char player = 'x';
private JLabel turnLabel = new JLabel("Player turn: ");
private JLabel turn = new JLabel(Character.toString(player).toUpperCase());
private JLabel winnerLabel = new JLabel("");
private JLabel timeLabel = new JLabel("");
private byte centiseconds = 0;
private byte seconds = 0;
private short minutes = 0;
private DecimalFormat timeFormatter;
private Timer timer;
/* Constructor initializes the Frame,
creates GUI components, and adds them
using a GridBagLayout. */
test() {
GridBagConstraints layoutConst; // Used to specify GUI component layout
// Set frame's title
setTitle("TicTacToe");
// Use a GridBagLayout
setLayout(new GridBagLayout());
// Create GridBagConstraints
layoutConst = new GridBagConstraints();
createObjects(layoutConst);
timer.start();
}
public void createObjects(GridBagConstraints layoutConst) {
int i = 0;
for(int r = 0; r <= 2; r++) {
for(int c = 0; c <= 2; c++) {
buttons[i] = new JButton();
buttons[i].setText(" ");
layoutConst.gridx = r;
layoutConst.gridy = c;
layoutConst.ipadx = 70;
layoutConst.ipady = 70;
add(buttons[i], layoutConst);
buttons[i].addActionListener(e -> {
layoutConst.insets = new Insets(0, 0, 0, 0);
JButton clickedBtn = (JButton) e.getSource();
clickedBtn.setText(String.valueOf(player));
clickedBtn.setEnabled(false);
if (player == 'x')
player = 'o';
else
player = 'x';
turn.setText(Character.toString(player).toUpperCase());
findWinner();
});
i++;
}
createLabels(layoutConst);
}
}
public void createLabels(GridBagConstraints layoutConst) {
layoutConst.gridx = 5;
layoutConst.gridy = 1;
layoutConst.ipady = 0;
layoutConst.ipadx = 0;
layoutConst.insets = new Insets(10, 10, 10, 10);
add(turnLabel, layoutConst);
layoutConst.gridx = 6;
layoutConst.gridy = 1;
layoutConst.gridwidth = 1;
layoutConst.insets = new Insets(0, 0, 0, 0);
add(turn, layoutConst);
layoutConst.gridx = 6;
layoutConst.gridy = 2;
layoutConst.gridwidth = 1;
layoutConst.insets = new Insets(0, 0, 0, 0);
add(winnerLabel, layoutConst);
layoutConst.gridx = 7;
layoutConst.gridy = 0;
layoutConst.insets = new Insets(0, 0, 0, 0);
add(timeLabel, layoutConst);
timeFormatter = new DecimalFormat("00");
timer = new Timer(10, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (centiseconds >= 0 && centiseconds != 100) {
centiseconds++;
}
else if(centiseconds == 100) {
seconds++;
centiseconds = 0;
}
else if(seconds == 60 && centiseconds == 100) {
minutes++;
seconds = 0;
centiseconds = 0;
}
timeLabel.setText(timeFormatter.format(minutes) + ":"
+ timeFormatter.format(seconds) + "."
+ timeFormatter.format(centiseconds));
}
});
timeLabel.setText(timeFormatter.format(minutes) + ":"
+ timeFormatter.format(seconds) + "."
+ timeFormatter.format(centiseconds));
}
public void findWinner() {
if (checkForWinner()) {
if (player == 'x') {
player = 'o';
}
else {
player = 'x';
}
winnerLabel.setText("Player " + Character.toString(player) + " wins!");
timer.stop();
}
else if (checkIfMatchDraw()) {
winnerLabel.setText("It's a draw!");
timer.stop();
}
}
public boolean checkIfMatchDraw() {
boolean gridsFull = true;
for (int i = 0; i < 9; i++) {
if (buttons[i].getText().equals(" ")) {
gridsFull = false;
}
}
return gridsFull;
}
public boolean checkForWinner() {
return checkAllRows() || checkAllColumns() || checkTheDiagonals();
}
public boolean checkAllRows() {
int i = 0;
for (int j = 0; j < 3; j++) {
if (buttons[i].getText().equals(buttons[i + 1].getText()) && buttons[i].getText().equals(buttons[i + 2].getText())
&& !buttons[i].getText().equals(" ")) {
return true;
}
i = i + 3;
}
return false;
}
public boolean checkAllColumns() {
int i = 0;
for (int j = 0; j < 3; j++) {
if (buttons[i].getText().equals(buttons[i + 3].getText()) && buttons[i].getText().equals(buttons[i + 6].getText())
&& !buttons[i].getText().equals(" ")) {
return true;
}
i++;
}
return false;
}
public boolean checkTheDiagonals() {
if (buttons[0].getText().equals(buttons[4].getText()) && buttons[0].getText().equals(buttons[8].getText())
&& !buttons[0].getText().equals(" "))
return true;
else
return buttons[2].getText().equals(buttons[4].getText()) && buttons[2].getText().equals(buttons[6].getText())
&& !buttons[2].getText().equals(" ");
}
/* Creates a Frameand makes it visible */
public static void main(String[] args) {
// Creates Frame and its components
test myFrame = new test();
// Terminate program when window closes
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Resize window to fit components
myFrame.pack();
// Display window
myFrame.setVisible(true);
}
}
Here is my code.
It got problem on while you selete from left to right..
import javax.swing.*;
import javax.swing.event.*;
public class swingex7 extends JFrame{
swingex7(){
JFrame f = new JFrame("Table Example");
String row[][]= {{"101","Hein Htet","10000000"},{"102","Hein Htet1","20000000"},{"103","Hein
Htet2","30000000"}};
String column[]= {"Id","Name","Salary"};
final JTable jt = new JTable(row,column);
jt.setCellSelectionEnabled(true);
ListSelectionModel lsm = jt.getSelectionModel();
lsm.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
lsm.addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
String data=null;
int[] rows=jt.getSelectedRows();
int[] columns = jt.getSelectedColumns();
for(int i=0;i<rows.length;i++) {
for(int j=0;j<columns.length;j++) {
data = (String)jt.getValueAt(rows[i], columns[j]);
}
}
System.out.println("Table element seleted is "+data);
}
});
JScrollPane js = new JScrollPane(jt);
f.add(js);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(400, 400);
f.setVisible(true);
}
public static void main (String[]args) {
new swingex7();
}
}
It got problem on while you Selete from left to right.
I also want to output only once per action.
There are 2 problems in the code.
1.
First problem is ListSelectionListener is called 2 times when mouse is clicked and when mouse is released. But instead of that if you can add MouseListener to your JTable as below.
MouseListener tableMouseListener = new MouseAdapter() {
#Override
public void mouseReleased(MouseEvent e) {
String data = null;
int[] rows = jt.getSelectedRows();
int[] columns = jt.getSelectedColumns();
for (int i = 0; i < rows.length; i++) {
for (int j = 0; j < columns.length; j++) {
data = (String) jt.getValueAt(rows[i], columns[j]);
System.out.println("Table element selected is " + data);
}
}
}
};
jt.addMouseListener(tableMouseListener);
2.
Second issue is the place where you printed the data. It should be inside the for loop. Otherwise the data will be rewritten in each iteration in the loop and only last value will be printed.
for (int i = 0; i < rows.length; i++) {
for (int j = 0; j < columns.length; j++) {
data = (String) jt.getValueAt(rows[i], columns[j]);
System.out.println("Table element selected is " + data);
}
}
I'm currently working on a Sudoku Project and I'm very close to completion but I'm having an issue with a part of my code (Sorry the variable names are in French) where the line and column index of a 2D array have been exchanged somehow and I can't seem to find where this comes from. Here is the Array declaration:
int[][]sdkGrid = {
{5,3,0,0,7,0,0,0,0},
{6,0,0,1,9,5,0,0,0},
{0,9,8,0,0,0,0,6,0},
{8,0,0,0,6,0,0,0,3},
{4,0,0,8,0,3,0,0,1},
{7,0,0,0,2,0,0,0,6},
{0,6,0,0,0,0,2,8,0},
{0,0,0,4,1,9,0,0,5},
{0,0,0,0,8,0,0,7,9}};
And here is the code where the two index are being swapped somehow:
The problem is I have no idea where the two index are being swapped.
public class FenetreGrille extends JFrame implements ActionListener{
public final int [][] NOMBRES_DEBUT;
public int [][] GRILLE_MODIF = new int[9][9];
public int [][] GRILLE_FINALE = new int[9][9];
public final int TAILLE = 9; //Mettre maj sur taille etc car ce sont des constantes
public final int TAILLECASE;
public final int COTEGRILLE ;
public Grille1 Sdk;
public JPanel Container1;
public JPanel Container2;
public JPanel containermain;
public JTextField [][] cases= new JTextField [9][9];
public JLabel FOND_ECRAN;
public JButton test = new JButton("test");
public FenetreGrille(int [][] NOMBRES_DEBUT){
this.TAILLECASE = 60;
this.NOMBRES_DEBUT = NOMBRES_DEBUT;
this.GRILLE_MODIF = NOMBRES_DEBUT;
Sdk = new Grille1(NOMBRES_DEBUT);
COTEGRILLE = TAILLE * TAILLECASE;
//this.setUndecorated(true); //Remove Title Bar AND EXIT BUTTON SO ADD ONE!!!!!
this.setAlwaysOnTop(true); //This is always on top
this.setResizable(false);
Toolkit tk = Toolkit.getDefaultToolkit();
int xsize = (int) tk.getScreenSize().getWidth();
int ysize = (int) tk.getScreenSize().getHeight();
this.setSize(xsize, ysize);
Container1 = new JPanel(); //Initialisation de la grille de Sudoku
Container1.setLayout(null);
Container1.setBounds((this.getWidth()/2)-(9*TAILLECASE/2),(this.getHeight()/2)-(9*TAILLECASE/2),COTEGRILLE,COTEGRILLE);
Container1.setBackground(Color.white);
for(int li = 0; li<TAILLE; li++){ // remplissage de la grille
for (int col = 0; col<TAILLE; col++){
cases[li][col] = new JTextField(Integer.toString(NOMBRES_DEBUT[li][col]));
cases[li][col].setBounds(li*TAILLECASE,col*TAILLECASE,TAILLECASE,TAILLECASE);
cases[li][col].setHorizontalAlignment(JTextField.CENTER);
cases[li][col].getDocument().addDocumentListener(new Ecouteur());
cases[li][col].getDocument().putProperty ("owner", cases[li][col]);
Container1.add(cases[li][col]);
if( li == 2 || li == 5){
if(col == 2 || col == 5){
Border border = BorderFactory.createMatteBorder(1,1,4,4,new Color(0, 0, 0));
cases[li][col].setBorder(border);
}else{
Border border = BorderFactory.createMatteBorder(1,1,1,4,new Color(0, 0, 0));
cases[li][col].setBorder(border);
}
}else if (col == 2 || col == 5){
Border border = BorderFactory.createMatteBorder(1,1,4,1,new Color(0, 0, 0));
cases[li][col].setBorder(border);
}else{
Border border = BorderFactory.createMatteBorder(1,1,1,1,new Color(0, 0, 0));
cases[li][col].setBorder(border);
}
if(NOMBRES_DEBUT[li][col] == 0){
cases[li][col].setText("");
cases[li][col].setBackground(new Color(204,204,204));
}else{
cases[li][col].setEditable( false);
}
}
}
int xButton = 200;
int yButton = (int) ((xButton*3)/4);
ImageIcon woodTemp = new ImageIcon("C:\\Users\\Maxime\\Documents\\Perso\\Post-Bac\\INSA\\Projet Info\\unfinished-bamboo-flooring-ufc214.jpg");
Image newImg = woodTemp.getImage();
ImageIcon woodButton = new ImageIcon(newImg.getScaledInstance(xButton, yButton, Image.SCALE_SMOOTH));
/*
test.setIcon(woodButton);
test.setBorder(null);
test.setMaximumSize(new Dimension(xButton, yButton));
test.setOpaque(false);
test.setContentAreaFilled(false);
test.setBorderPainted(false);
*/
test.setBounds((xsize/4)-100, (ysize/4)-75, xButton, yButton);
test.addActionListener(this);
containermain = new JPanel();
containermain.setBounds(0,0, xsize, ysize);
containermain.setOpaque(false);
containermain.setLayout(null);
FOND_ECRAN = new JLabel ();
FOND_ECRAN.setBounds(0, 0, 1920, 1080);
containermain.add(FOND_ECRAN);
containermain.add(test);
int x = FOND_ECRAN.getWidth();
ImageIcon temp = new ImageIcon("C:\\Users\\Maxime\\Documents\\Perso\\Post-Bac\\INSA\\Projet Info\\nature-1520704451453-7117.jpg");
Image img = temp.getImage();
Image dimg = img.getScaledInstance(FOND_ECRAN.getWidth(), FOND_ECRAN.getHeight(), Image.SCALE_SMOOTH);
ImageIcon imageIcon = new ImageIcon(dimg);
FOND_ECRAN.setIcon(imageIcon);
setContentPane(containermain);
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("Menu");
menuBar.add(menu);
JMenuItem item = new JMenuItem("Exit");
item.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
menu.add(item);
this.setJMenuBar(menuBar);
containermain.add(Container1);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public class Ecouteur implements DocumentListener{
public void changedUpdate(DocumentEvent e){
action(e);
}
public void insertUpdate(DocumentEvent e) {
action(e);
}
public void removeUpdate(DocumentEvent e){
//action(e);
}
public void action (DocumentEvent e){
for(int i = 0; i<TAILLE; i++){
for (int j = 0; j<TAILLE; j++){
if(e.getDocument().getProperty("owner") == cases[i][j]){
String s = cases[i][j].getText(); //Enlever tous les i,j, n et leur donner un nom
int n = Integer.parseInt(s); // Remplace la string s en un nombre
if(n < 1 || n > 9){
JOptionPane.showMessageDialog(containermain, " entrez un nombre entre 1 et 9");
}else{
cases[i][j].setBackground(Color.white);
GRILLE_MODIF[i][j] = n;
affichage(GRILLE_MODIF);
}
}
}
}
//Verification if the grid is complete
}
}
public void append ( String s){}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == b) {
this.dispose();
}else if(e.getSource() == test) {
SudokuBackTrack sbt = new SudokuBackTrack(NOMBRES_DEBUT);
GRILLE_FINALE = sbt.grille;
for(int i = 0; i < TAILLE; i++) {
for(int j = 0; j < TAILLE; j++) {
cases[i][j].setText(Integer.toString(GRILLE_FINALE[i][j]));
}
}
}
}
public void affichage(int[][] t) {
for (int i=0; i<9; i++){
for (int j=0; j<9; j++){
System.out.print(t[i][j]+" ");
}
System.out.println();
}
System.out.println();
}
}
I think your offending line is:
cases[li][col].setBounds(li*TAILLECASE,col*TAILLECASE,TAILLECASE,TAILLECASE);
To fix, change it to:
cases[li][col].setBounds(col*TAILLECASE,li*TAILLECASE,TAILLECASE,TAILLECASE);
setBounds parameters are setBounds(x, y, width, height).
li (the vertical line index) should correspond to y, and col should correspond to the x coordinate.
One coding practice I use when managing arrays like this in GUIs is to explicitly name my iteration variables x and y, so that I do not get confused.
I am adding JLabel objects to a JPanel. Each label has a different tool tip text that I use to identify each label afterwards, the problem is that the tool tip is always showing on hover and I need it to always be hidden.
Each label has a different image icon that's why I can't use the label text.
I can't find any documentation on the label API for some function like .hidetooltip.
Edit
Each of many JLabel objects on a GridLayout holds an Image. I need to know the line and column of each image.
To hide the tool tip text to null
myComponent.setToolTipText(null);
This is described in the API for this method: "param - the string to display; if the text is null, the tool tip is turned off for this component"
EDIT: In response to your actual issue that you describe in one of your comments, there are a variety of ways association information with a JLabel. You could a) extend the class and keep instance variables defining the grid values b) use a Map key'd with the JLabel and value'd with the row/col c) use the Name of the JLabel
Each of many JLabel objects on a GridLayout holds an Image. I need to know the line and column of each image.
One way to achieve this is to store a BufferedImage[][] to check images against. E.G.
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.net.URL;
import java.util.Random;
import javax.imageio.ImageIO;
public final class ImageArray {
int r = 8;
int c = 8;
// The images in the chess board, used to check which
// image was chosen for this place on the board.
final private BufferedImage[][] chessBoardImages = new BufferedImage[r][c];
private final int rowSprite = 2;
private final int colSprite = 6;
// Holds the tile sheet images
private final BufferedImage[] chessPieceImages =
new BufferedImage[colSprite * rowSprite];
private JComponent ui = null;
private final BufferedImage chessSpriteSheet;
ImageArray(BufferedImage chessSpriteSheet) {
this.chessSpriteSheet = chessSpriteSheet;
initUI();
}
private int getImageIndex(Image img) {
for (int i = 0; i < chessPieceImages.length; i++) {
if (chessPieceImages[i].equals(img)) {
return i;
}
}
return -1;
}
public void initUI() {
if (ui != null) {
return;
}
ui = new JPanel(new BorderLayout(4, 4));
ui.setBorder(new EmptyBorder(4, 4, 4, 4));
int w = chessSpriteSheet.getWidth();
int h = chessSpriteSheet.getHeight() / rowSprite;
int wStep = chessSpriteSheet.getWidth() / colSprite;
int hStep = chessSpriteSheet.getHeight() / rowSprite;
for (int x = 0; x < colSprite; x++) {
for (int y = 0; y < rowSprite; y++) {
chessPieceImages[x + (y * colSprite)]
= chessSpriteSheet.getSubimage(
x * wStep, y * hStep, wStep, h);
}
}
JPanel grid = new JPanel(new GridLayout(r, c));
ui.add(grid, BorderLayout.CENTER);
Random rand = new Random();
for (int x = 0; x < r; x++) {
boolean oddRow = x % 2 == 0;
for (int y = 0; y < c; y++) {
boolean oddCol = y % 2 == 0;
BufferedImage img = chessPieceImages[
rand.nextInt(colSprite * rowSprite)];
JLabel l = new JLabel(new ImageIcon(img));
chessBoardImages[x][y] = img;
l.setOpaque(true);
if ((oddRow && oddCol) || (!oddRow && !oddCol)) {
l.setBackground(Color.WHITE);
} else {
l.setBackground(Color.LIGHT_GRAY);
}
grid.add(l);
}
}
JLabel htmlLabel = new JLabel(getHtml());
htmlLabel.setHorizontalTextPosition(SwingConstants.CENTER);
htmlLabel.setVerticalTextPosition(SwingConstants.BOTTOM);
ui.add(htmlLabel,
BorderLayout.LINE_END);
}
private String getHtml() {
String style = "<style type='text/css'>"
+ "body {"
+ "font-size: 36px;"
+ "}"
+ ".white {"
+ "background-color: #FFFFFF;"
+ "}"
+ ".black {"
+ "background-color: #BBBBBB;"
+ "}"
+ "</style>";
String pre = "<html><head>%1s</head><body><table border=1 cellspacing=0>";
StringBuilder sb = new StringBuilder(String.format(pre, style));
for (int y = 0; y < r; y++) {
sb.append("<tr>");
for (int x = 0; x < c; x++) {
Image img = chessBoardImages[y][x];
final int index = getImageIndex(img);
// hack to convert index to unicode codepoint..
int unicodeOffset = ((index/colSprite)*colSprite)==0 ? colSprite : -colSprite;
int unicodeIndexOffset;
switch (index) {
case 3:
unicodeIndexOffset = 4;
break;
case 4:
unicodeIndexOffset = 3;
break;
case 9:
unicodeIndexOffset = 10;
break;
case 10:
unicodeIndexOffset = 9;
break;
default:
unicodeIndexOffset = index;
}
int unicode = 9812 + unicodeIndexOffset + unicodeOffset;
// end: hack to convert index to unicode index..
String cssClass;
boolean oddCol = x%2==1;
boolean oddRow = y%2==1;
if ((oddRow && oddCol) || (!oddRow && !oddCol)) {
cssClass = "white";
} else {
cssClass = "black";
}
sb.append(String.format(
"<td class='%1s'>&#%2s;</td>", cssClass, unicode));
}
sb.append("</tr>");
}
sb.append("</table></body></html>");
return sb.toString();
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) throws Exception {
String urlString = "http://i.stack.imgur.com/memI0.png";
final BufferedImage img = ImageIO.read(new URL(urlString));
Runnable r = new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
ImageArray o = new ImageArray(img);
JFrame f = new JFrame("Image Array");
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);
}
}
You should consider storing the information elsewhere. One way would be to make a class deriving from JLabel with the purpose of storing the line and column information. Then use instances of this subclass rather than use JLabel instances. They will render as a regular JLabel would, but you can retrieve the line and column information in a way that does not pop up that information in a tooltip.
I'm making a multiplication table using swing.Its basically made up of JButtons. The table is formed from input from the user. The user selects the size of the table by entering a number. The last thing i need to do with this is create a heading that displays the numbers of the table created. Here is my sample code, if you run it, you'll see that its done for the vertical numbers. How can i get the numbers above and properly formatted to represent each column. Thank you.
package lab7;
import java.awt.BorderLayout;
import java.awt.GridBagLayout;
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.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class GUIMultiplicationTable{
JFrame theFrame;
int number = 0;
JPanel panel, answerPanel, topPanel, leftPanel;
JLabel answerLabel, topLabel, leftLabel;
private void createAndShowGui(){
String x;
do{
x = JOptionPane.showInputDialog(null, "Enter the number");
number = Integer.parseInt(x);
}while (number <= 0);
theFrame = new JFrame("Multiplication Table");
panel = new JPanel(new GridLayout(number, number));
answerPanel = new JPanel();
answerLabel = new JLabel();
topPanel = new JPanel();
topLabel = new JLabel();
leftPanel = new JPanel();
leftLabel = new JLabel();
for (int i = 0; i < number; i++){
JLabel blah = new JLabel(Integer.toString(i + 1));
panel.add(blah);//add center to label
for (int j = 0; j < number; j++){
JButton button = new JButton();
if (i == 0){
button.setText(String.valueOf(j + 1));
}
if (j == 0){
button.setText(String.valueOf(i + 1));
}
for (int k = 1; k < number; k++)
{
if (i == k)
{
button.setText(String.valueOf((j + 1) * (k + 1)));
}
}
button.addActionListener(new ButtonsTableActionListener(i, j));
panel.add(button);
}
}
answerPanel.add(answerLabel);
theFrame.add(answerPanel, BorderLayout.SOUTH);
topPanel.add(topLabel);
theFrame.add(topPanel, BorderLayout.NORTH);
theFrame.add(panel);
theFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
theFrame.pack();
theFrame.setLocationRelativeTo(null);
theFrame.setVisible(true);
}
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable(){
public void run(){
GUIMultiplicationTable h = new GUIMultiplicationTable();
h.createAndShowGui();
}
});
}
private class ButtonsTableActionListener implements ActionListener{
private int theRow, theColumn;
public ButtonsTableActionListener(int row, int column){
theRow = row;
theColumn = column;
}
#Override
public void actionPerformed(ActionEvent e){
int value = (theRow + 1) * (theColumn + 1);
answerLabel.setText("The value is: " + value + ".\nI got that by multiplying \n" + (theRow + 1) + "x" + (theColumn + 1));
}
};
}
An easy way to do this is to store the position of the button in the ActionListener, you can accomplish this by making your own class extending ActionListener, instead of doing an anonymous class. This way the code executed by the button will already have the information it needs to accomplish whatever you want.
Also you don't need the array of buttons, just add a button in the panel at a time, and at the same time add the actionListener.
This is your code cleaned up and working properly. Now, instead of showing a dialog do whatever you want to do.
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.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class GUIMultiplicationTable
{
JFrame theFrame;
int number = 0;
JPanel panel;
private void createAndShowGui()
{
String x;
do
{
x = JOptionPane.showInputDialog(null, "Enter the number");
number = Integer.parseInt(x);
} while (number <= 0);
theFrame = new JFrame("Multiplication Table");
panel = new JPanel(new GridLayout(number, number));
for (int i = 0; i < number; i++)
{
for (int j = 0; j < number; j++)
{
JButton button = new JButton();
if (i == 0)
{
button.setText(String.valueOf(j + 1));
}
if (j == 0)
{
button.setText(String.valueOf(i + 1));
}
for (int k = 1; k < number; k++)
{
if (i == k)
{
button.setText(String.valueOf((j + 1) * (k + 1)));
}
}
button.addActionListener(new ButtonsTableActionListener(i, j));
panel.add(button);
}
}
theFrame.add(panel);
theFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
theFrame.pack();
theFrame.setLocationRelativeTo(null);
theFrame.setVisible(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable() {
public void run()
{
GUIMultiplicationTable h = new GUIMultiplicationTable();
h.createAndShowGui();
}
});
}
private class ButtonsTableActionListener implements ActionListener
{
private int _row, _column;
public ButtonsTableActionListener(int row, int column)
{
_row = row;
_column = column;
}
#Override
public void actionPerformed(ActionEvent e)
{
// /do something
int value = (_row + 1) * (_column + 1);
String message = "I'm the button in the position (" + _row + ", " + _column + ")\nMy value is " + value + " = " + (_row + 1) + "*" + (_column + 1);
JOptionPane.showMessageDialog(theFrame, message);
}
};
}
Everything you need to do is just putting a JLabel somewhere.
final JLabel resultLabel = new JLabel("Select a button!");
Note that it should be final to be able to use it in the ActionListener. In the ActionListener you already had the right way, just look at these few lines to make it happen:
ActionListener first = new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
for(int i = 0; i < number; i++){
for(int j = 0; j < number; j++){
if(buttons[i][j] == e.getSource()){
// write the equation to the label
resultLabel.setText(buttons[i][j].getText()
+ " = " + (i+1) + " * "
+ (j+1));
// since you found the button you can now break
break;
}
}
}
}
};
Note the i+1 and j+1. The buttons are indexed from 0 to number-1, so the button at (0,0) actually shows the result of 1*1.
This is also important for your next two lines of code:
// you used i=1 and j=1, but you have to start with 0 to make it work for all buttons
for(int i = 0; i < number; i++){
for(int j = 0; j < number; j++){
buttons[i][j].addActionListener(first);
}
}
At a last step you also have to show the the label. If you just add it to the frame, as you do with the panel, you will see that you will not see it.
theFrame.add(resultLabel);
theFrame.add(panel);
The problem is that theFrame doesn't have a layoutmanager yet. So use a new Layout here as well:
theFrame.setLayout(new GridLayout(2,1));
Of course there will be better choices or some nice tweeks to make the layout more beautiful.
So as in sum how to change your code from top to bottom:
set a Layout for theFrame
create a new JLabel for the result of the click, make it final
set the label's text in the actionPerformed() method
add the label to theFrame
You can also consider putting the Label into a new JPanel and add that Panel to theFrame.
The loop in your actionListener is not required, the source of the event is the button that triggered it, so you can simply do...
JButton source = (JButton) e.getSource();
JOptionPane.showMessageDialog(theFrame, source.getText());
Instead.
Now having said that, I would, personally, use some kind of Map to link the JButton to the value, removing the need to have to try and cast the text of the button back to a numeric value (which I believe would be your next step), or store other information you might need to work with for the button (such as the values required to produce the answer)...
private Map<JButton, int[]> answers = new HashMap<JButton, int[]>(25);
//...
for(int i = 0; i < number; i++){
for(int j = 0; j < number; j++){
buttons[i][j] = new JButton();
if(i == 0) {
buttons[i][j].setText(String.valueOf(j+1));
}
if(j == 0) {
buttons[i][j].setText(String.valueOf(i+1));
}
for(int k = 1; k < number; k++){
if(i == k){
buttons[i][j].setText(String.valueOf((j+1) * (k+1)));
}
}
panel.add(buttons[i][j]);
// Store the answer here...
answers.put(buttons[i][j], new int[]{i, j});
}
}
//...
public void actionPerformed(ActionEvent evt) {
JButton source = (JButton) e.getSource();
int[] answer = answers.get(source);
JPanel panel = new JPanel();
JTextField[] fields = new JTextField[]{
new JTextField(2),
new JTextField(2)
};
panel.add(fields[0]);
panel.add(new JLabel("x"));
panel.add(fields[1]);
panel.add(new JLabel(" = " + source.getText()));
JOptionPane.showMessageDialog(theFrame, panel);
// check the values of the fields against the
// values of the answer
}