Change JButton text and functionality depending on a specific situation - java

Basically what I am searching for is how to make a button's text and functionality change dynamically depending on the situation. For example I am working on a card game where I save selected cards of the user into an array, and I want it so when 1 or more card is selected, the button's name should be Play, and have the player to play that move, while if 0 cards are selected, the button's name should be Pass so on click the user can pass the turn. The button's text should change itself only depending on the number of selected cards, and not on click etc.
Image

The functionality part is easy, you just add action listener to the button as usual, but do something different depend on the number of selected cards.
As for the button text, you should have a method like updateButtonText() which assign different text to the button based on currently selected cards. And you call this method at start to assign the initial text.
Then whenever you detected user has change in card selection, you simply call updateButtonText() again to have the button text updated.

You could create two separate buttons where each has its own ActionListener and change which buttons are visible depending on the situation:
JButton pass_button = new JButton("Pass");
JButton play_button = new JButton("Play");
// Loop this code on separate thread or use callback
if(num_cards_selected == 0 && panel.contains(play_button)) {
panel.remove(play_button);
panel.add(pass_button);
} else if(num_cards_selected > 0 && panel.contains(pass_button)) {
panel.remove(pass_button);
panel.add(play_button);
}
Or you could check the state of the card game and have an ActionListener that is tied to the JButton act according to the condition:
JButton button = new JButton("");
// Loop this code on separate thread or use callback
if(num_cards_selected == 0)
button.setText("Pass");
else
button.setText("Play");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(num_cards_selected == 0)
pass();
else
play();
}
});

What you need is :
check the number of cards selected
add action listener to button and change the outcome of the action as per the cards selection
Code example :
check all the comments provided in the code
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class cardGame implements ActionListener {
int cards[];
JButton b1;
JFrame f;
JPanel panel;
public cardGame(int n) { // taking input n as how many cards have been
// selected
cards = new int[n]; // number of cards selected
f = new JFrame(); // creating a jFrame
f.setPreferredSize(new Dimension(400, 400)); // size of JFrame
panel = new JPanel(); // creating a panel
b1 = new JButton("click"); // creating a JButton
b1.setSize(20, 30); // setting size of JButton
b1.addActionListener(this); // adding action listener
panel.add(b1); // adding JButton to panel
f.add(panel); // adding panel to JFrame
f.pack();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // setting default
// close operation
f.setVisible(true); // set JFrame visible
}
#Override
public void actionPerformed(ActionEvent e) {
if (cards.length >= 3) { // if cards are more than or equal to 3
// setBackground color blue
b1.setText("Play");
panel.setBackground(Color.blue);
}
// you can change the functionality as per your need
else {// else setBackground color green
b1.setVisible(true);
b1.setText("pass");
panel.setBackground(Color.green);
}
}
public static void main(String[] args) {
new cardGame(2); // providing input as number of cards selected try
// giving 2 and 3
}
}

Related

My JCheckBox program only displays one box. Why is that?

I am attempting to add another checkbox to this program but for some reason it will not display when I run the program. Only the check box for the blue pill displays. I have attempted to add a couple things or change the way the program is structured, but nothing I have done so far has helped.
Code Below:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class CMIS242WK4DonnersonAReply {
static JCheckBox red;
static JCheckBox blue;
static JButton button;
public CMIS242WK4DonnersonAReply() {
button = new JButton("submit"); // Creates submit button
widget
ButtonHandler listener = new ButtonHandler(); // Creates the handler for the button.
button.addActionListener((ActionListener) listener); // adds the handler to the button widget
JPanel content = new JPanel(); // "container"
content.setLayout(new BorderLayout());
content.add(button, BorderLayout.PAGE_END);// places submit button at the bottom of panel.
JLabel label = new JLabel("At last. Welcome, Neo. As you no doubt have guessed, I am Morpheus. This is your last chance. After this there is no turning back."); // Label in frame.
content.add(label, BorderLayout.NORTH);// places label at the top of the screen.
//Creating Check Boxes
JCheckBox red = new JCheckBox("You take the red pill, you stay in Wonderland and I show you how deep the rabbit hole goes.");
red.setBounds(100,100, 50,50);
content.add(red);
JCheckBox blue = new JCheckBox("You take the blue pill, the story ends, you wake up in your bed and believe whatever you want to believe. ");
blue.setBounds(100,100, 50,50);
content.add(blue);
//Adding Frame
JFrame window = new JFrame("Matrix Monologue"); // JFrame = Window
window.setContentPane(content);
window.setSize(750,200); // Length, Height
window.setLocation(200,200); // X/Y "OF THE ENTIRE FRAME" Not the contents
window.setVisible(true); // makes window visible
}
// Method handles what happens when button is pressed.
private static class ButtonHandler implements ActionListener{
public void actionPerformed1(ActionEvent e) {
// Checks if which pill was selected and responds to user depending on their action.
if (red.isSelected() == true) {
System.out.println("Follow me");
System.out.println();
}
if (blue.isSelected() == true) {
System.out.println("Very Well, You may go back to your world");
System.out.println();
}
else
System.out.println("You must make a choice for what pill you will take");
System.exit(0); //closes program
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}
}
// Main/driver method that runs everything.
public static void main(String[] args) {
CMIS242WK4DonnersonAReply matrixMonologue= new CMIS242WK4DonnersonAReply();
}
}
Any pointers?
When you're stuck on a problem, it never hurts to go back and consult the documentation.
You'll find information like this:
A border layout lays out a container, arranging and resizing its
components to fit in five regions: north, south, east, west, and
center. Each region may contain no more than one component, and is
identified by a corresponding constant: NORTH, SOUTH, EAST, WEST, and
CENTER. When adding a component to a container with a border layout,
use one of these five constants...
When you add your button, you do this:
content.add(button, BorderLayout.PAGE_END);
But then, when it's time to add checkboxes, you do this:
content.add(red);
...
content.add(blue);
Are you seeing what's missing? My bet is that you only see the blue checkbox because you added it on top of (or simply displaced) the red checkbox. Remember, the doc says "Each region may contain no more than one component..."
Try specifying the region of your BorderLayout where you want to see each checkbox.
If you want them to appear in the same region, put them in a JPanel of their own and lay them out at NORTH and SOUTH or EAST and WEST and then add that checkbox panel to your content panel in the region you want them to appear.
I feel that you need some guidance with your Swing programming. I have rewritten your CMIS242WK4DonnersonAReply class. Code is below. But first some comments about the code in your question.
JCheckBox red = new JCheckBox("You take the red pill, you stay in Wonderland and I show you how deep the rabbit hole goes.");
You have created a local variable which is hiding the class member. Hence static JCheckBox red; remains null and consequently the following if statement will throw NullPointerException.
if (red.isSelected() == true) {
By the way, the == true is not necessary. The following is sufficient.
if (red.isSelected()) {
Now another point.
red.setBounds(100,100, 50,50);
Since you are using a layout manager, namely BorderLayout, method setBounds will be ignored. The layout manager determines where to place the component on the screen.
window.setContentPane(content);
By default, the content pane of JFrame is a JPanel with BorderLayout so no need to replace the default content pane.
private static class ButtonHandler implements ActionListener
No need to create a nested class. Simply make class CMIS242WK4DonnersonAReply implement the ActionListener interface.
System.out.println("Follow me");
I don't think it's a good idea to involve the console in a GUI application. I would use JOptionPane to display a message to the user.
static JCheckBox blue;
I think that JRadioButton is more appropriate than JCheckBox in your situation.
Here is my code.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
public class CMIS242WK4DonnersonAReply implements Runnable, ActionListener {
private JButton button;
private JRadioButton blue;
private JRadioButton red;
private JFrame window;
#Override
public void actionPerformed(ActionEvent event) {
if (red.isSelected()) {
JOptionPane.showMessageDialog(window, "Follow me.");
}
else if (blue.isSelected()) {
JOptionPane.showMessageDialog(window, "Very Well, You may go back to your world");
}
else {
JOptionPane.showMessageDialog(window, "You must make a choice for what pill you will take");
}
}
#Override
public void run() {
createAndShowGui();
}
private void createAndShowGui() {
window = new JFrame("Matrix Monologue");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel label = new JLabel("At last. Welcome, Neo. As you no doubt have guessed, I am Morpheus. This is your last chance. After this there is no turning back."); // Label in frame.
window.add(label, BorderLayout.PAGE_START);
window.add(createCheckBoxes(), BorderLayout.CENTER);
JPanel buttonPanel = new JPanel();
button = new JButton("submit");
button.addActionListener(this);
buttonPanel.add(button);
window.add(buttonPanel, BorderLayout.PAGE_END);
window.setSize(750,200); // Length, Height
window.setLocation(200,200); // X/Y "OF THE ENTIRE FRAME" Not the contents
window.setVisible(true); // makes window visible
}
private JPanel createCheckBoxes() {
JPanel panel = new JPanel();
BoxLayout layout = new BoxLayout(panel, BoxLayout.PAGE_AXIS);
panel.setLayout(layout);
red = new JRadioButton("You take the red pill, you stay in Wonderland and I show you how deep the rabbit hole goes.");
blue = new JRadioButton("You take the blue pill, the story ends, you wake up in your bed and believe whatever you want to believe.");
ButtonGroup grp = new ButtonGroup();
grp.add(red);
grp.add(blue);
panel.add(red);
panel.add(blue);
return panel;
}
public static void main(String[] args) {
EventQueue.invokeLater(new CMIS242WK4DonnersonAReply());
}
}
Here is how the app looks when I run it.

Adding more mouselisteners to 1 JButton?

Is it possible to add more than 1 mouselistener to a JButton? You know when I click on the button it should change color and text, and do something (e.g system.out.println), and when I click it again it should go back to the previous state, and print something else.
What I've tried:
JButton b = new JButton("First");
b.setBackground(Color.GREEN);
b.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e)
{
b.setBackground(Color.RED);
b.setText("Second");
System.out.println("You've clicked the button");
}
if(b.getModel.isPressed){
b.setBackground(Color.GREEN);
b.setText("Second");
System.out.println("You're back");
}
The problem is that the button doesn't go back to the previous state with the color (green) and text, and I don't how to handle that.
First of all, you shouldn't be using a MouseListener to do these things, because a better listener, ActionListener, was built specifically to be used with JButtons and similar entities to notify programs that a button has been pressed.
Having said that, sure you can add multiple ActionListeners (or MouseListeners) to a JButton, or you can have an ActionListener change its behaviors depending on the state of the program (usually meaning the values held by fields of the class).
A problem with your code and question is that I don't see when you expect or want the button to change its color back to green. If after a certain period of time, then have your ActionListener start a Swing Timer that changes the button's color back to green after x milliseconds.
Edit: I see, you want to toggle color -- then use a boolean field that you toggle or check the button's current color and base the listener's response based on that color.
example
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
#SuppressWarnings("serial")
public class ToggleColor extends JPanel {
public ToggleColor() {
JButton button = new JButton(new MyButtonAction());
button.setBackground(Color.GREEN);
add(button);
}
private static void createAndShowGui() {
ToggleColor mainPanel = new ToggleColor();
JFrame frame = new JFrame("ToggleColor");
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(() -> createAndShowGui());
}
}
#SuppressWarnings("serial")
class MyButtonAction extends AbstractAction {
// !! parallel arrays being used below -- avoid if possible
private static final String[] TEXT = {"First", "Second", "Third"};
private static final Color[] COLORS = {Color.GREEN, Color.RED, new Color(108, 160, 220)};
private int index = 0;
public MyButtonAction() {
super(TEXT[0]);
}
#Override
public void actionPerformed(ActionEvent e) {
index++;
index %= TEXT.length;
putValue(NAME, TEXT[index]);
Component c = (Component) e.getSource();
c.setBackground(COLORS[index]);
}
}
This uses an AbstractAction class which is like an ActionListener but on "steroids"
You should only register one lister, but that listener will maintain some state regarding the number for mouse clicks. A simple if/else block will change the actions and change the text on the button label.

How do you print multiple text areas in an orderly manner in Java?

Alright, so I have a dilemma. I was wondering if there is a way for me to do the following with two text areas:
I. Print the first text area, and only the first text area.
II. Upon closing the first text area, have it so the second text area appears.
III. Do this so that both text areas do not appear at the same time.
Here is my code, sorry for all the comments, I have to teach this to fellow classmates for a project:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*; //Used for events and the Action Listener
public class ActionProgram extends JFrame /*"extends JFrame" will extend the frame into the variable used to call the class*/
{
//Declare fields (Do not require public/private identification)
JTextArea area;
JLabel instructions;
JLabel question;
JLabel ask;
JButton submitt;
JScrollPane sp;
//Create a constructor to start applying these variables in the creation of the Text Area
public ActionProgram()
{
//Create the flow layout
setLayout(new FlowLayout());
//Create the text area and set how long and wide it should be. Add it to the frame
area = new JTextArea(10,30);
add(area);
//Create scroll pane and add it to the frame
sp = new JScrollPane(area);
add(sp);
//Set the line wrap and word wrap to true for the frame
area.setLineWrap(true);
area.setWrapStyleWord(true);
//Create submitt button, and add it to the frame
submitt = new JButton ("Submitt");
add(submitt);
//Create label asking user to answer the question and add it to the frame
instructions = new JLabel("Please Answer the Following Question:");
add(instructions);
//Create label for the question and add it to the frame
question = new JLabel("-----Briefly Describe how to print something in java-----");
add(question);
//Create label telling user what to do when finished, and add it to the frame
ask = new JLabel("Please enter Submitt when you have finished");
add(ask);
//As you can tell, we do not need to put all these parts into the frame, for the class puts it all into the variable calling it
/*In order for the program to take what the user has writen into text area and make it an input, we have to create an
Action Listener. An Action Listener is a piece of code that will do a specific event when an action is done. In this case
we need the action listener to respond when the user presses "Submitt". To do this, we need to create an event class*/
//This will call the action listener class
event action = new event();
//This will add the action listener to the submitt button
submitt.addActionListener(action);
}
/*The class called event will create the aciton listener. There are two different methods for the action event, the action listener
and the action performer. The action performer is the method used to create code when the action listener is activated. The listener
waits for the submitt button to be pressed, and the performer does user-inputed code when the button is pressed*/
public class event implements ActionListener
{
public void actionPerformed(ActionEvent e) //We use a nested method to create the action performer
{
/*The following code is what the performer will do when the listner is activated. It will get the text typed in the
text area when the user hits the submitt button. The performer will then print the text obtained and close the text area*/
String text = area.getText();
System.out.println(text);
//Use System.exit(0) to close the text area
System.exit(0);
}
}
public static void main(String[] args)
{
//Call the class like you usually do, and set a variable to it
ActionProgram display = new ActionProgram();
//display also acts as the frame of the text area since the class set it equal to the JFrame
display.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Set the length and width of the text area in pixels
display.setSize(500,300);
//Set it so the text area can be seen
display.setVisible(true);
}
}
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; //Used for events and the Action Listener
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class ActionProgram extends JFrame /*
* "extends JFrame" will extend the
* frame into the variable used to call
* the class
*/
{
// Declare fields (Do not require public/private identification)
JTextArea area;
JLabel instructions;
JLabel question;
JLabel ask;
JButton submitt;
JScrollPane sp;
final int TOTAL_QUESTIONS = 5; // assuming you have 5 questions
int quizCounter = 0;
String[] quizQuestions;
// Create a constructor to start applying these variables in the creation of
// the Text Area
public ActionProgram() {
// Create the flow layout
setLayout(new FlowLayout());
// display also acts as the frame of the text area since the class set
// it equal to the JFrame
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Set the length and width of the text area in pixels
setSize(500, 300);
// Create the text area and set how long and wide it should be. Add it
// to the frame
area = new JTextArea(10, 30);
add(area);
// Create scroll pane and add it to the frame
sp = new JScrollPane(area);
add(sp);
// Set the line wrap and word wrap to true for the frame
area.setLineWrap(true);
area.setWrapStyleWord(true);
// Create submitt button, and add it to the frame
submitt = new JButton("Submit");
add(submitt);
// Create label asking user to answer the question and add it to the
// frame
instructions = new JLabel("Please Answer the Following Question:");
add(instructions);
// Create label for the question and add it to the frame
quizQuestions = questions();
question = new JLabel(quizQuestions[quizCounter]);
add(question);
// Create label telling user what to do when finished, and add it to the
// frame
ask = new JLabel("Please enter Submit when you have finished");
add(ask);
// As you can tell, we do not need to put all these parts into the
// frame, for the class puts it all into the variable calling it
/*
* In order for the program to take what the user has writen into text
* area and make it an input, we have to create an Action Listener. An
* Action Listener is a piece of code that will do a specific event when
* an action is done. In this case we need the action listener to
* respond when the user presses "Submitt". To do this, we need to
* create an event class
*/
// This will call the action listener class
event action = new event();
// This will add the action listener to the submitt button
submitt.addActionListener(action);
}
/*
* The class called event will create the aciton listener. There are two
* different methods for the action event, the action listener and the
* action performer. The action performer is the method used to create code
* when the action listener is activated. The listener waits for the submitt
* button to be pressed, and the performer does user-inputed code when the
* button is pressed
*/
public class event implements ActionListener {
public void actionPerformed(ActionEvent e) // We use a nested method to
// create the action
// performer
{
/*
* The following code is what the performer will do when the listner
* is activated. It will get the text typed in the text area when
* the user hits the submitt button. The performer will then print
* the text obtained and close the text area
*/
if (e.getSource() == submitt) {
String text = area.getText();
System.out.println(text);
dispose();
// increment the amount of times questions were asked - i.e. the frame opened
quizCounter++;
if (quizCounter < TOTAL_QUESTIONS ) {
quizQuestions = questions();
area.setText("");
question.setText(quizQuestions[quizCounter]);
setVisible(true);
} else {
System.exit(0);
}
}
}
}
public String[] questions() {
String[] newQuestion = new String[TOTAL_QUESTIONS];
switch(quizCounter) {
case 0:
newQuestion[0] = "-----Briefly Describe how to print something in java-----";
break;
case 1:
newQuestion[1] = "----- Question 2 -------";
break;
case 2:
newQuestion[2] = "Question 3";
break;
case 3:
newQuestion[3] = "Question 4";
break;
case 4:
newQuestion[4] = "Question 5";
break;
}
return newQuestion;
}
public static void main(String[] args) {
// Call the class like you usually do, and set a variable to it
ActionProgram display = new ActionProgram();
// Set it so the text area can be seen
display.setVisible(true);
}
}
The answer is laid out on the assumption that you are going to ask 5 questions. Please change the quantity for the TOTAL_QUESTIONS variable to fit with your criteria. Also, don't forget to modify the questions() method body.
It is a good practice to set up all your actions for the JFrame in the construction, rather than in the main. I have amended the code accordingly. Also, it is a good habit to use SwingUtilities to run swing applications.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new ActionProgram().setVisible(true);
}
});
If you have any queries, feel free to comment.
You can not close a JTextArea, until unless you are wrapping the JTextArea in a JScrollPane and then adding the JScrollPan to JPanel.
If you are able to perform all these steps then you can use FocusListener
which is used to shift the focus from one component to another.
You can read more about them here.

Change JButton ImageIcon on Click

I am attempting to create a JFrame Application in java that is similar to Minesweeper but with slightly different rules/goals.
I have created a grid of JButtons, 12x12 and have a JButton 2D array.
I'm trying to change the image of a button when it is clicked (make it an X or an image of a gold nugget). I know how to do this if I had an individual name for each button, but it seems not logical to create 144 individual buttons and name each of them.
So what I need to do is on the click event of that button, change/set the image of that button, but in my action listener I can only figure it out if I know the specific array coordinates of that button.
My question is how do I change the Image of that specific button? Or how do I get the values of the button[?][?] so I can change the image of that button?
Thanks!
public class GoldPanel extends JPanel{
ImageIcon xImage = new ImageIcon("x.png");
ImageIcon goldImage = new ImageIcon("");
losingButtonListener loseButton = new losingButtonListener();
winningButtonListener winButton = new winningButtonListener();
JButton[][] button = new JButton[12][12];
//creates the layout
GridLayout layout = new GridLayout(12,12);
Random myRand = new Random();
public GoldPanel(){
//creates panel for name/title/score/etc
JPanel titlePanel = new JPanel();
add(titlePanel);
JLabel title = new JLabel("Welcome to the Goldmine Game!");
titlePanel.add(title);
//creates panel for the game board
JPanel gamePanel = new JPanel();
add(gamePanel);
gamePanel.setLayout(layout);
for(int i=0;i<12;i++)
{
for(int j=0;j<12;j++)
{
button[i][j] = new JButton(" ");
gamePanel.add(button[i][j]);
button[i][j].addActionListener(loseButton);
}
}
button[0][0].addActionListener(winButton);
}//end constuctor
private class losingButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}//actionPerformed
}//buttonListener
private class winningButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
System.out.println("you win");
}//actionPerformed
}//winningButtonListener
}//end GoldPanel class
If you look at the ActionEvent Documentation Page you see that every action event is constructed with an Object source. This means that if the system registers a click on the button this button gets passed to the constructor of the ActionEvent as source.
So you're actually getting the right button by casting this object to the right class.
[...]
public void actionPerformed(ActionEvent ae) {
JButton theRightButton = (JButton) ae.getSource();
// do stuff with the button...
}
[...]
Use a toggle button
http://docs.oracle.com/javase/7/docs/api/javax/swing/JToggleButton.html
So swing keeps track of the state for you in the button model.
Extend the button to pass x,y coord in the constructor and store them as field
Attach the same event listener to all buttons, cast source to button class and retrieve x/y of the button having been clicked
Change on the fly the pressed icon to mine or number in the event
Call click to all neighbouring empty fields if you want to replicate this rule, but make sure to check the pressed state so you don't loop back over already processed neighbours.

Newly created JButton doesn't override the previously created JButtons

Essentially, what I have coded is a puzzle game.
It contains an image , and the image is further divided into 9 pieces which is placed onto JPanel containing a 3x3 JButton GridLayout. Initially, the 9 buttons are empty. When the user clicks "Start Game", the 9 buttons will then show the images on the buttons.
I used setPreferredSize() to set the size of the JPanel containing the 9 empty JButtons. After that, I used Inset ( 0,0,0,0 ) to make the button's contents fill the entire button.
But now, when I want to add the imaged buttons to replace the empty buttons when the user clicks "Start Game" , it doesn't work.
I think this is because the setPreferredSize() I set earlier on is preventing the Insets values from working.
I inserted some system.out.println values to check if the method is running, it runs, but the image still refuses to appear on the buttons when user clicks "Start Game" .
public class GameFrame extends JFrame implements ActionListener {
private JButton button1;
private JButton[] button = new JButton[9];
private Insets buttonMargin;
private boolean testImageMethod;
private JPanel puzpiece;
public GameFrame(){
//.. coding ..
// create new buttons - button1
button1 = new JButton("Start Game");
// add action event to "Start" button
button1.addActionListener(this);
// creates a new panel for the splitted puzzle pieces
puzpiece = new JPanel();
puzpiece.setLayout(new GridLayout(3,3));
// check if testImageMethod boolean ( in setupImage() ) is true,
//if it isn't, adds 9 buttons w/o images.
for(int a=0; a<9; a++){
if(testImageMethod){
}
else{
// adds 9 buttons without images
button[a] = new JButton();
puzpiece.add(button[a]);
puzpiece.setPreferredSize(new Dimension(500,200));
}
}
// adds puzpiece panel into the frame
this.add(puzpiece,BorderLayout.WEST);
//.. coding ..
}
public void actionPerformed(ActionEvent e){
if (e.getSource() == button1){
// puzpiece.button.setVisible(false);
//puzpiece.remove(button);
// call setImage() method
setImage();
for(int a=0; a<9; a++){
// adds the new 9 buttons with images into panel
puzpiece.add(button[a]);
// test if method is running
System.out.println("qq");
}
}
else{
System.out.println("bbb");
}
}
// method setImage() divides the image into subimages
public void setImage(){
//.. coding ..
// test if method is running
System.out.println("a");
setupImage( count++, sc );
}
// method setupImage() adds the subimages to the buttons
private void setupImage( int a, Image wi )
{
// test if method is running
System.out.println("d");
buttonMargin = new Insets( 0, 0, 0, 0 );
button[a] = new JButton( new ImageIcon( wi ) );
button[a].setMargin( buttonMargin );
// test if method is running
System.out.println("e");
} // end method setupImage()
}
I'm not sure I know exactly what you're doing but, ...
It appears that you are populating a JPanel with a 3x3 grid of plain JButtons,
and that on button press you are adding in JButtons that display an image.
But I don't see you removing the original buttons before adding new buttons.
Nor do I see you call revalidate() and then repaint() on the puzpiece JPanel after changing components.
And even more importantly, why swap JButtons when it's much easier to swap ImageIcons in JButtons that are already held by the puzpiece JPanel? This is something that I recommended in comment 10 minutes ago but am now making an answer.
Simply setIcon for the said JButton, don't add JButton anew to the JPanel, already visible
A small example for the same :
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* Created with IntelliJ IDEA.
* User: Gagandeep Bali
* Date: 1/19/13
* Time: 10:05 AM
* To change this template use File | Settings | File Templates.
*/
public class ButtonImageTest
{
private Icon infoIcon = UIManager.getIcon("OptionPane.informationIcon");
private Icon errorIcon = UIManager.getIcon("OptionPane.errorIcon");
private JButton button;
private int counter = 1;
private void displayGUI()
{
JFrame frame = new JFrame("Button Image Test");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel contentPane = new JPanel();
button = new JButton();
button.setBorderPainted(false);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (counter % 2 != 0)
{
button.setIcon(errorIcon);
counter = 2;
}
else
{
button.setIcon(infoIcon);
counter = 1;
}
}
});
contentPane.add(button);
frame.setContentPane(contentPane);
frame.setSize(100, 100);
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String... args)
{
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new ButtonImageTest().displayGUI();
}
});
}
}

Categories

Resources