Comparing/Switching Selected JButtons within a 2D Array - java

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.

Related

How to change an Icon when JButton is Pressed

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.

changing attributes to a JButton created by a method without variable name

I create some JButtons with a method, but I don't give them a variable i can call them with. i was wondering if it is possible to change the text somehow, after the button is created from another method. I am aware of that i can get the action command when the button is pressed but i want to change the button text, without it being pressed. I can give the buttons names like but would prefer not to. since I am only going to call half of them, and then I don't think its a good idea. or is it?
JButton button1 = buttons(0,0,0);
public JButton buttons(int coord, int coord1, int number) {
JButton box = new JButton("");
box.setFont(new Font("Tahoma", Font.PLAIN, 60));
box.setBounds(coord, coord1, 100, 100);
contentPane.add(box);
box.addActionListener(this);
box.setActionCommand(Integer.toString(number));
return box;
}
public static void main(String[] args) {
buttons(0,0,0);
buttons(98,0,1);
buttons(196,0,2);
buttons(0,98,3);
addText();
}
public void addText() {
//help me guys
button.setText("Please fix me");
}
You can get pressed button from actionEvent
#Override
public void actionPerformed(ActionEvent e) {
JButton button = (JButton)e.getSource();
}
Why not just have them in a public arraylist?
ArrayList<JButton> buttons = new ArrayList<JButton>();
public JButton buttons(int coord, int coord1, int number) {
JButton box = new JButton("");
box.setFont(new Font("Tahoma", Font.PLAIN, 60));
box.setBounds(coord, coord1, 100, 100);
contentPane.add(box);
box.addActionListener(this);
box.setActionCommand(Integer.toString(number));
buttons.add(box);//Add it here
return box;
}
This way you can loop through them later and change something if you want to,
for(JButton b : buttons){
if(/*Whatever*/){
b.setText("New name");
}
}
I can give the buttons names like but would prefer not to. since I am only going to call half of them, and then I don't think its a good idea. or is it?
You are creating problems for yourself. Even if you may only need the call a few/none of them, there is significant advantage for not keeping a reference for them.
If you have too many JButtons and you do not want to have a separate variable name for each of them, you can have an array/collection of JButtons.
JButton[] btns = new JButton[size];
//or
ArrayList<JButton> btns= new ArrayList<JButton>();
To change text for all buttons:
for(JButton b : btns)
btns.setText("whatever here");
To change text for a specific button:
btns[x].setText("whatever here"); //from array
btns.get(x).setText("whatever here"); //from list
Alternatively, if you do not keep a reference. You can get the list of buttons from the content pane:
Component[] components = myPanel.getComponents();
for(Component c : components)
if(c instanceof JButton)
((JButton)c).setText("whatever here");

how do you change the color of a jbutton after it is clicked?

I am making a jFrame that represents a go board. I want a click of a given button to change the color to represent placing a piece on the board. In my code below, I show a method that should be able to change the color of a button (it only changes the background of the whole frame). First question: Why is the button color not changing (this is not my bigger problem about changing color after click occurs, my preliminary issue is that the button color will not change). I do not get any errors, the button color just never changes.
public static void showBoard()
{
JFrame frame2 = new JFrame("Go Board");
frame2.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
for(int i = 19*19; i > 0; i--)
{
JButton firstButton = new JButton("");
firstButton.setBackground(Color.blue);
firstButton.setVisible(true);
firstButton.setContentAreaFilled(true);
firstButton.setOpaque(true);
firstButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run()
{
System.out.println("ddsd");
//int[] arr = findMove(0);
}
});
}
});
frame2.getContentPane().add(firstButton);
}
frame2.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
frame2.setLayout(new GridLayout(19,19));
frame2.pack();
frame2.setVisible(true);
}
My second problem, getting the button to change color after being clicked, is presumably affected by the fact that I am not able to even change the button color. To get the button to change color after a click, I plan to put the button color change code inside the action listener.
So in summation, how can I change the color of the button after a click?
ANSWER:
The problem was the look and feel of my mac. Look to the checked answer for how to fix this if you have similar problem on your mac.
You don't need to call SwingUtilities.invokeLater inside your ActionListener, as the actionPerformed(ActionEvent) method will be invoked on the Event Thread already.
The following example demonstrates how to change a Button's background color when it's clicked on:
public class ChangeButtonColor implements Runnable {
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(new javax.swing.plaf.metal.MetalLookAndFeel());
} catch (UnsupportedLookAndFeelException e) {
System.err.println("Cannot set LookAndFeel");
}
SwingUtilities.invokeLater(new ChangeButtonColor());
}
#Override
public void run() {
JFrame frame = new JFrame();
frame.setLayout(new FlowLayout());
JButton button1 = new JButton("click me");
JButton button2 = new JButton("click me too");
ActionListener listener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
if (source instanceof Component) {
((Component)source).setBackground(Color.RED);
}
}
};
button1.addActionListener(listener);
button2.addActionListener(listener);
frame.add(button1);
frame.add(button2);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
Please note that the ActionListener used here can be used for all buttons. There is no need to create a new instance of it for every button.

A main menu for class A extends Applet

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.

Manipulating buttons in different Jpanel

I have a various panels with various buttons. Some buttons should call a method initiating a search through an array list, other buttons should call methods that send information to different JTextArea boxes.
After adding an event listener for each button, how do I create specific actions depending on the button clicked in my actionPerformed method? Below is my code for various gui properties, as you can see there are 3 different JPanels, the buttons of each needing to perform different functions. I just need to know how to determine which button was clicked so I can link it to the appropriate method (already written in another class). Does this require an if statement? Can my other class access the buttons on the GUI if I make them public, or is there a more efficient way to do this.
JPanel foodOptions;
JButton[] button= new JButton[4]; //buttons to send selected object to info panel
static JComboBox[] box= new JComboBox[4];
JPanel search;
JLabel searchL ;
JTextField foodSearch;
JButton startSearch; //button to initialize search for typed food name
JTextArea searchInfo;
JPanel foodProfile;
JLabel foodLabel;
JTextArea foodInfo;
JButton addFood; //but to add food to consumed calories list
JPanel currentStatus;
JLabel foodsEaten;
JComboBox foodsToday;
JLabel calories;
JTextArea totalKCal;
JButton clearInfo; //button to clear food history
As per people's comments, you need to use listeners of some sort, here is a real basic example to get you started, however I would define your listeners elsewhere in most cases, rather than on the fly:
JButton startSearch = new JButton("startSearch");
JButton addFood = new JButton("addFood");
startSearch.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
//DO SEARCH RELATED THINGS
}
});
addFood.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
//DO FOOD ADD RELATED THINGS
}
});
Something like this:
JButton searchButton = new JButton("Start search");
searchButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// do some search here
}
});
JButton addFoodButton= new JButton("Add food");
addFoodButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// add your food
}
});
and so on. If you need to reuse an behaviour through multiple buttons, create a ActionListener instance instead of using anonymous classes and assign it multiple times to your buttons.
Well there any many ways to do that I guess. I suppose you can do the following:
public class Myclass implements ActionListener
{
private JButton b1,b2;
private MyClassWithMethods m = new MyClassWithMethods();
// now for example b1
b1 = new JButton("some action");
b1.setActionCommand("action1");
b1.addActionListener(this);
public void actionPerformed(ActionEvent e) {
if ("action1".equals(e.getActionCommand()))
{
m.callMethod1();
} else {
// handle other actions here
}
}
}
And you can do the same for more buttons and test which action triggered the event and then call the appropriate methods from you class.

Categories

Resources