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.
Related
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
}
}
public class ButtonsActionListener implements ActionListener {
String[] buttons = { "Button1", "Button2", "Button3", "Button4"};
for (String btn: buttons ) {
JButton button = new JButton(btn);
this.add(button);
button.addActionListener(this);
}
}
#Override
public void actionPerformed(ActionEvent e) {
JButton btn = (JButton)e.getSource();
btn.setBackground(Color.Red);
}
}
What Im trying to do is when the user clicks on for example Button1, Button1's color should turn to grey and when I click on BUtton3, Button1 color should go back to normal and Button3 should turn grey. I dont know how to check the previous click
Your actionPerformed function changes the background of what is currently clicked, so it will not allow you to change other JButton objects without a very rudimentary condition. You should store all of your buttons as unique variables for such cases.
Im looking to change an Icon when I click a Jbutton. I have button1 rigged up to an action command that prints "On" or "Off". I would like to have the button change icons from an image of an circle meaning off, to an image of a power button meaning on. I've tried many things but haven't been able to find a solution so Im wondering if there is an easy way to do this or if there isn't an easy way, and ill have to make a more complex way for each button. Any advice is greatly appreciated because Im at a dead end. Fell free to edit large blocks or add things because Im open to all ideas. The code is included below
import java.awt.*;
import javax.swing.*;
import java.io.*;
import java.awt.event.*;
public class OnandOff{
public static void main(String[] a){
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new ButtonDemo());
f.setSize(600,500);
f.setVisible(true);
}
}
class ButtonDemo extends JPanel implements ActionListener {
JTextField jtf;
public ButtonDemo() {
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
makeGUI();
}
});
} catch (Exception exc) {
System.out.println("Can't create because of " + exc);
}
}
private void makeGUI() {
setLayout(new FlowLayout());
//sets up icons
ImageIcon OnIcon = new ImageIcon(" On.jpg");
Icon OffIcon = new ImageIcon("Off.jpg");
ImageIcon BlankIcon = new ImageIcon("Blank.jpg");
//creates jbuttons with Action command
ImageIcon button1 = new ImageIcon("Off.jpg");
JButton jb = new JButton(button1);
jb.setActionCommand("On");
jb.addActionListener(this);
add(jb);
ImageIcon button2 = new ImageIcon("Off.jpg");
jb = new JButton(button2);
add(jb);
ImageIcon button3 = new ImageIcon("Off.jpg");
jb = new JButton(button3);
add(jb);
ImageIcon button4 = new ImageIcon("Off.jpg");
jb = new JButton(button4);
add(jb);
}
#Override
//prints on and off when detecting action comand from a jbutton
public void actionPerformed(ActionEvent ae) {
String action = ae.getActionCommand();
if (action.equals("On")) {
System.out.println("Yes Button pressed!");
ImageIcon button1 = new ImageIcon("On.jpg");
TicTacToe.a = 1;
}
else if (action.equals("Off")) {
System.out.println("No Button pressed!");
}
}
You're forgetting to call setIcon(...) on any button. As the AbstractButton API will tell you (this is the parent class of JButton), it is easy to change the icon of any button by simply calling its setIcon(Icon icon) method and pass in the new Icon. In the future, first go to the API as you'll learn much there, including methods that do exactly what you need.
Other suggestions: don't give your variables names that don't match what they are. For instance you're calling an ImageIcon variable "button1" as if it were a JButton, and that will confuse other coders and your future self. Instead why not call it `onIcon" or "offIcon", a name that makes the code self-commenting.
A major problem with your code, and one reason why as written, you can't make it work -- your JButton objects are assigned to local variables, variables that are only visible within the method that they were declared. If you want your JButton objects to be able to have there icons changed in different methods of the class, they must be declared at the class level, not at the method or constructor or deeper level.
Similar questions to my own have been asked, but I'm at a bit of a loss as to how to proceed. I really have a poor grasp of some of the more subtle nuances of java, so I apologize if anything isn't clear.
Say for example I wanted to compare one JButton within a 2D array with another. To be more specific, all of these JButton's would be stores within a 2D array and displayed in grid format. All of the buttons would have the same action listener that, upon the button being pressed, calls the setselected() method.
How would I go about comparing one of these selected JButton's with another selected JButton within the same array? And upon doing so, how could I swap the positions or more specifically, the icons of said buttons.
Below, I've included some example code and my own attempt on the subject. I understand that I can use .getSource() to grab a JButton object itself, but would this not only allow me to capture 1 selected button at a time. This is all considering the use of the same actionlistner code for each button, but a secular listener for each button.
The code below sets every icon to 1 of 7 randomly generated image icons. A frame is generated within secular main class. Upon being pressed or "selected" the image icons change to a selected iteration of the same image.
EDIT: Based on Ameer's suggestion, I've run into several nullpointer exceptions that are caused by my actionPerformed method. Is this as a result to my button array not being filled with button objects at this point, or am I simply presuming something within my code?
public class SButtonGame extends JFrame implements ActionListener {
public static ImageIcon[] icons={
new ImageIcon("img1.png"),
new ImageIcon("img2.png"),
new ImageIcon("img3.png"),
new ImageIcon("img4.png"),
new ImageIcon("img5.png"),
new ImageIcon("img6.png"),
new ImageIcon("img7.png"),
};
public static ImageIcon[] selectedIcons={
new ImageIcon("simg1.png"),
new ImageIcon("simg2.png"),
new ImageIcon("simg3.png"),
new ImageIcon("simg4.png"),
new ImageIcon("simg5.png"),
new ImageIcon("simg6.png"),
new ImageIcon("simg7.png"),
};
int rowNum=0;
int colNum=0;
JButton[][] Buttons;
boolean swaptf=false;
JButton CButton; // Selected button "holder". Doesn't accomplish anything I think it should
public SButtonGame(String title) {
//Constructs frame
super(title);
getContentPane().setLayout(null)
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(578,634);
int colLoc=10;
int rowLoc=10;
this.colNum=0;
this.rowNum=0;
for(int r=0; r<8; r++)
{
this.Buttons= new JButton[9][9];
this.rowNum++;
for(int c=0; c<8; c++)
{
ActionListener listner = new ActionListener(){
public void actionPerformed(ActionEvent e)
{
if(e.getSource() instanceof JButton)
{
((JButton) e.getSource()).setSelected(true);
CButton=(JButton)e.getSource();
}
}
};
int ranImg;
ranImg=0+(int)(Math.random()*7);
int sranImg=ranImg;
this.Buttons[this.colNum][this.rowNum]= new JButton(icons[ranImg]);
this.Buttons[this.colNum][this.rowNum].setSelectedIcon(selectedIcons[sranImg]);
this.Buttons[this.colNum][this.rowNum].addActionListener(listner);
this.Buttons[this.colNum][this.rowNum].setSize(59,59);
this.Buttons[this.colNum][this.rowNum].setLocation(rowLoc,colLoc);
rowLoc=rowLoc+69;
this.Buttons[this.colNum][this.rowNum].setVisible(true);
this.Buttons[this.colNum] [this.rowNum].setBorder(BorderFactory.createLineBorder(Color.black));
add(this.Buttons[this.colNum][this.rowNum]);
}
this.colNum++;
colLoc=colLoc+69;
rowLoc=10;
}
JButton Newgame;
Newgame= new JButton("NewGame");
Newgame.setSize(100, 30);
Newgame.setLocation(350, 560);
Newgame.setVisible(true);
add(Newgame);
JButton Quit;
Quit= new JButton("Quit");
Quit.setSize(60, 30);
Quit.setLocation(480, 560);
Quit.setVisible(true);
add(Quit);
New.addActionListener(new ActionListener()
{
//dispose of current frame and generates a new one;
public void actionPerformed(ActionEvent e)
{
dispose();
SButtonGame Frame;
Frame = new SButtonGame("ShinyButtons");
Frame.setVisible(true);
}
});
Quit.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
dispose();
}
});
}
#Override
public void actionPerformed(ActionEvent ae){
if(ae.getSource() instanceof JButton){
JButton sButton;
int rindex=0;
int cindex=0;
((JButton) ae.getSource()).setSelected(true);
sButton=(JButton)ae.getSource();
if(SButtonGame.this.Buttons[(int)sButton.getClientProperty("rownum")][(int)sButton.getClientProperty("colnum")].isEnabled()==true){
}
}
}
public static void main(String[] args)
{
SButtonGame Frame;
Frame = new SButtonGame("ButtonsGame");
Frame.setVisible(true);
}
}
Inside actionPerformed(ActionEvent e) method, you can access the 2D array of buttons by using SButtonGame.this.Buttons (ideally variable name should be buttons starting with small b).
You can then compare the clicked button with the buttons from array and do rest of your stuff.
Hi i have made a game in java that extends applet. The game works perfectly fine but one of the requirements of this assignment is that there should be a menu. For example: As the program is run a screen with "Play" and "Quit" Options should appear and if user clicks "Play", this should lead on to the game, etc...
Q) Is there a way to do this specifically for applets?
I have attempted to make a a menu using the following code but it doesn't work (I think this is only for extends JPanel or JFrame not extends Applet):
MainMenu.java
public class MainMenu extends JFrame {
int screenWidth = 200;
int screenHeight = 150;
int buttonWidth = 100;
int buttonHeight = 40;
JButton Play;
JButton Quit;
public MainMenu() {
addButtons();
addActions();
Play.setBounds((screenWidth - buttonWidth)/2, 5 , buttonWidth, buttonHeight); // Positions the play button
Quit.setBounds((screenWidth - buttonWidth)/2, 10 , buttonWidth, buttonHeight);
//Adding buttons
getContentPane().add(Play); //add the button to the Frame
getContentPane().add(Quit);
pack();
setVisible(true);
setLocationRelativeTo(null);
setSize(screenWidth , screenHeight);
setTitle("Drop");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
}
private void addButtons() {
Play = new JButton ("Play");
Quit = new JButton ("Quit");
}
private void addActions() {
Play.addActionListener(new ActionListener() { // takes play button, adds new actionlistener
public void actionPerformed(ActionEvent e) { // Turn actionPerformed into variable for usage
dispose(); // wipes out Jframe
Board game = new Board();
game.run();
}
}); //Play Button
Quit.addActionListener(new ActionListener() { // takes quit button, adds new actionlistener
public void actionPerformed(ActionEvent e) { // Turn actionPerformed into variable for usage
System.exit(0);
}
}); //Quit Button
}
}
Launcher.java (Where menu is run from)
public class Launcher {
public static void main (String[] args){
new MainMenu();
}
}
Any help is much appreciated (Ideas, tutorials...)
For many components in one space, use a CardLayout as see in this short example.
I just ended up making a text based menu.
Initially set a variable to true, for eg: menu = true
and make the paint method paint whatever you want on the menu, like start...
if(menu) {
paint what's on the menu
}
then when when user clicks on a certain option within the menu turn menu variable to false i.e. menu = false.
You need to get mouse input to get the user's input so use either the mouse pressed or mouse clicked methods that come with the mouselistener.
After turning it false, get the paint method to paint your game.
i.e.
if(!menu) {
paint the game
}
Pretty much a bunch of if statements.
Hope this helps someone.