import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class Concentration extends JFrame implements ActionListener {
private JButton buttons[][]=new JButton[4][4];
int i,j,n;
public Concentration() {
super ("Concentration");
JFrame frame=new JFrame();
setSize(1000,1000);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel=new JPanel(new GridLayout(4,4));
panel.setSize(400, 400);
for( i=0; i<buttons.length; i++){
for (j=0; j<buttons[i].length;j++){
n=i*buttons.length+buttons[i].length;
buttons[i][j]=new JButton();
panel.add(buttons[i][j]);
buttons[i][j].addActionListener(this);
}
}
add(panel);
pack();
setVisible(true);
}
public void actionPerformed(ActionEvent e) {
buttons[i][j].setIcon(new ImageIcon(
getClass().getResource("/images/2.jpg")));
}
public static void main(String args[]){
new Concentration();
}
}
This is my code. I am making memory game. I want to make that, each time clicked a button, that button shows image but
buttons[i][j].addActionListener(this);
in that, methot can not take i and j and doesnot show any image.
But for example when i do
buttons[2][2].addActionListener(this);
it shows only in 2x2 . image. What can i do to solve that?
Possible solutions:
Inside the ActionListener, iterate through the button array to see which JButton in the array matches the button that was pressed, obtained by calling e.getSource()
Give your JButtons actionCommand Strings that correspond to i and j
Create a separate ActionListener implementing class that has i and j fields that can be set via a constructor, and give each button a unique ActionListener with i and j set.
Try this code:
public void actionPerformed(ActionEvent e) {
if(e.getSource() instanceof JButton){
JButton pressedButton = (JButton) e.getSource();
if(pressedButton.getIcon() == null){
pressedButton.setIcon(new ImageIcon(getClass().getResource("/images/2.jpg")));
} else {
pressedButton.setIcon(null);
}
}
}
Direct form EventObject javadoc:
public Object getSource()
The object on which the Event initially occurred.
Returns:
The object on which the Event initially occurred.
This means there's no need to know the array indexes of pressed button as it could be known through getSource() method.
Related
I'm trying to update a JFrame, and all of the components in the frame, including JPanel, JLabel components, etc. I tried using revalidate(), but that didn't seem to be working. I have a JLabel in the frame displaying an int, and I have the int iterating by 1 when I click a JButton. I can see that the value of the int changes, but the actual text on the label doesn't change. I know I can use JLabel.setText(), but is there a method to use for all components, that would update the displayed text/image upon pressing a button?
Here is my code below:
package repainttest;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Window extends JFrame {
int test = 1;
JLabel label;
public Window() {
setLayout(new FlowLayout());
label = new JLabel(Integer.toString(test));
add(label);
JButton button = new JButton("Add");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
test +=1;
System.out.println(test);
refresh();
}
});
add(button);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public void refresh() {
SwingUtilities.updateComponentTreeUI(this);
revalidate();
repaint();
}
}
If you do not set the new text (test) on the JLabel, it is never going to know that the value of test is changing. So, please insert following statement:
label.setText(String.valueOf(test));
in public void actionPerformed(ActionEvent e) after following statement:
test +=1;
and see the results.
EDIT: The answer to the button generating part of this question can be found here:
Array that Holds JButton Objects
I used a for loop to generate some JButtons each labeled with their index. Within the loop, I attach an ActionListener to each button. The listener retrieves the label of the button and prints it. Currently, the only button which returns a value is the last one created, which makes sense. I'm wondering if there is a way to do this sort of mass-generation and then individual retrieval in an advantageous way.
IN SHORT:
Make a bunch of labeled JButtons in a loop.
Print the label when a button is clicked.
Here is a short, executable example of what my current process looks like:
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
public class calc {
private JFrame mainFrame;
private JPanel mainPanel;
private JButton button;
public calc(){
mainFrame = new JFrame("Calculator");
mainPanel = new JPanel();
for (int i=0; i<10; i++){
int value = i;
String number = Integer.toString(value);
button = new JButton(number);
button.addActionListener(new ButtonListener());
mainFrame.add(button);
}
mainFrame.setLayout(new FlowLayout());
mainFrame.setSize(250, 300);
mainPanel.setLayout(new FlowLayout());
mainFrame.add(mainPanel);
mainFrame.setVisible(true);
}
class ButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == button) {
System.out.println(((JButton) e.getSource()).getText());
}
}
}
}
You can create an array of buttons, for example:
JButton[] btns = new JButtons[10];
for(int x=0; x<btns.length; x++)
btns[x] = new JButton(x + "");
Create your ActionListener:
private class ButtonHandler implements ActionListener{
#Override
public void actionPerformed(ActionEvent e){
System.out.println( ((JButton)e.getSource()).getText() );
}
}
Add each button to the ActionListener:
ButtonHandler handler = new ButtonHandler();
for(int x=0=; x<btns.length; x++)
btns[x].addActionListener(handler);
When you click any of the buttons, it will trigger the ActionListener and based on the button that was clicked, print the text from the JButton to the console.
I am writing a GUI program in Java. The GUI consists of 9 buttons titled H. In run mode, when the mouse clicks on any button, that button should change the heading to T. I have a MouseListener code watching out for the clicks. But I have no way of finding out based on the mouse clicks that I need to change that particular button. Any help is appreciated.
Below is my code.
package flippingcoins;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class FlippingCoins extends JFrame
{
public FlippingCoins()
{
JPanel p = new JPanel();
p.setLayout(new GridLayout(3,3,1,1));
JButton jbt1=new JButton("H");
p.add(jbt1);
JButton jbt2=new JButton("H");
p.add(jbt2);
JButton jbt3=new JButton("H");
p.add(jbt3);
JButton jbt4=new JButton("H");
p.add(jbt4);
JButton jbt5=new JButton("H");
p.add(jbt5);
JButton jbt6=new JButton("H");
p.add(jbt6);
JButton jbt7=new JButton("H");
p.add(jbt7);
JButton jbt8=new JButton("H");
p.add(jbt8);
JButton jbt9=new JButton("H");
p.add(jbt9);
add(p);
}
public static void main(String[] args) //Main program begins here.
{
FlippingCoins frame = new FlippingCoins();//Instantiating an object.
frame.setTitle("Head or Tails");//Setting the frame title.
frame.setSize(300,300);//Setting the size.
frame.setLocationRelativeTo(null);//Setting the location.
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// Default closing options.
frame.setVisible(true);//Setting visibility to true.
}//End of main program.
static class ChangeTiles extends JPanel
{
public ChangeTiles()
{
addMouseListener(new MouseAdapter()//Creating a listener
{
public void mouseClicked(MouseEvent e)//When the mouse is clicked.
{
int x=e.getX();
int y=e.getY();
System.out.println("x= "+ x + "y= "+y);
}
}
);
}
}
That's not the good strategy. Instead, add an ActionListener to every button. Not only will it be much easier, but users will then also be able to use their keyboard to click the buttons.
Also, consider using an array or list of buttons. That will allow using loops instead of copying and pasting the same code 9 times.
public FlippingCoins() {
final JPanel p = new JPanel();
p.setLayout(new GridLayout(3, 3, 1, 1));
for (int i = 0; i < 9; i++) {
final JButton jbt = new JButton("H");
jbt.setName("" + i);
jbt.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
jbt.setText("T");
System.out.println(jbt.getName());
}
});
p.add(jbt);
}
setContentPane(p);
}
Some notes:
use loops for repetitive tasks
listeners have to be added to the widget they should listen to
do not use MouseListeners for JButton, there is ActionListener
Alternative for JLabel:
public FlippingCoins2() {
final JPanel p = new JPanel();
p.setLayout(new GridLayout(3, 3, 1, 1));
for (int i = 0; i < 9; i++) {
final JLabel jlb = new JLabel("H", SwingConstants.CENTER);
jlb.setBorder(BorderFactory.createLineBorder(Color.blue));
jlb.setName("" + i);
jlb.addMouseListener(new MouseAdapter() {
public void mouseClicked(final MouseEvent e) {
jlb.setText("T");
System.out.println(jlb.getName());
}
});
p.add(jlb);
}
setContentPane(p);
}
This is how you should do it:
JButton jbt1=new JButton("H");
jbt1.addActionListener(new ButtonListener());
//add ButtonListener to all of the other buttons
//Somewhere in your code:
public class ButtonListener extends ActionListener {
public void actionPerformed(ActionEvent e) {
JButton source = (JButton) e.getSource();
source.setText("T");
}
}
This will be easy if you add an ActionListener. Inside the actionPerformed code you can make it print out which button was clicked.
getSource()
Returns: The object on which the Event initially occurred.
you can call getSource() on the ActionEvent generated by the ActionPerformed method. I haven't tried this but sounds like you can easily find out which button was clicked.
For example, I am trying to call the setEnable method on a JButton that I constructed within the parameter parenthesis of an add method:
add(new JButton());
I know I could just do something like:
JButton button = new JButton();
button.setEnable(false);
but is there I way I can call setEnable on a JButton that I didn't assign a reference name to?
The reason why I am not assigning the JButton a reference name is because I am supposed to add an unknown number of JButtons to a JPanel. How I am doing this, is by using this for loop.
for (int i = 0; i < numberOfButtonsToAdd; i++)
{
JPanelName.add(new JButton());
}
and I want all the JButtons to be disabled.
You state in comment:
The reason why I am not assigning the JButton a reference name is because I am supposed to add an unknown number of JButtons to a JPanel. How I am doing this, is by using a for loop: for (int i = 0; i < numberOfButtonsToAdd; i++) { JPanelName.add(new JButton()); }
Then just use either an array or ArrayList of JButton.
// in your field declarations
List<JButton> buttonList = new ArrayList<JButton>();
// elsewhere in your program
for (int i = 0; i < numberOfButtonsToAdd; i++) {
JButton button = new JButton();
buttonList.add(button);
somePanel.add(button);
}
Now you have a reference to any button in the list via buttonList.get(someIndex)
Note also, that most buttons are given ActionListeners that are activated whenever the button is pressed. Without such listeners, the buttons are pretty much useless. You can also get a reference to the pressed JButton from the ActionListener via the ActionEvent object passed into its actionPerformed method:
public void actionPerformed(ActionEvent e) {
AbstractButton myButton = (AbstractButton) e.getSource();
// now you can use myButton
}
Note that this is key information that you should have shared with us up front in your original question.
Edit
You state now:
and I want all the JButtons to be disabled.
Then just make them disabled from the get-go:
for (int i = 0; i < numberOfButtonsToAdd; i++) {
JButton button = new JButton();
button.setEnabled(false);
buttonList.add(button);
somePanel.add(button);
}
Although I am curious -- why all disabled? Why no ActionListener? No text?
Edit 2
You state:
Would I still be able to access those individual buttons later on, since they are all assigned "button"?
Please understand that the variable name is of little importance, and in fact, in my example above, the variable named button does not exist outside of the for loop within which it was declared. Instead what matters is the reference to the JButton object. As has been much discussed in the other answers and as you are aware, this can be obtained by using a variable, but it doesn't have to be a variable directly to the JButton, it could, as is in this case, be the variable to the ArrayList<JButton>. That's why I suggest that you create this entity.
Edit 3
for example:
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
public class ButtonLists extends JPanel {
private static final int ROWS = 6;
private static final int COLS = 6;
private List<JButton> allButtons = new ArrayList<JButton>();
private List<JButton> evenButtons = new ArrayList<JButton>();
public ButtonLists() {
JPanel gridPanel = new JPanel(new GridLayout(ROWS, COLS));
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
int buttonInt = i * COLS + j;
String buttonString = String.valueOf(buttonInt);
JButton button = new JButton(buttonString);
button.setEnabled(false);
gridPanel.add(button);
allButtons.add(button);
if (buttonInt % 2 == 0) {
evenButtons.add(button);
}
}
}
JPanel bottomPanel = new JPanel();
bottomPanel.add(new JButton(new AbstractAction("Activate All") {
#Override
public void actionPerformed(ActionEvent e) {
for (JButton btn : allButtons) {
btn.setEnabled(true);
}
}
}));
bottomPanel.add(new JButton(new AbstractAction("Activate Even") {
#Override
public void actionPerformed(ActionEvent e) {
for (JButton btn : allButtons) {
btn.setEnabled(false);
}
for (JButton btn : evenButtons) {
btn.setEnabled(true);
}
}
}));
bottomPanel.add(new JButton(new AbstractAction("Activate Odd") {
#Override
public void actionPerformed(ActionEvent e) {
for (JButton btn : allButtons) {
btn.setEnabled(true);
}
for (JButton btn : evenButtons) {
btn.setEnabled(false);
}
}
}));
setLayout(new BorderLayout());
add(gridPanel, BorderLayout.CENTER);
add(bottomPanel, BorderLayout.PAGE_END);
}
private static void createAndShowGui() {
JFrame frame = new JFrame("ButtonLists");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new ButtonLists());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
If you added it to a panel you can get the components of that panel and looping through those components if one is a button you could call setEnabled(), but if there were more than one button you would have to determine if it was the correct one.
Edit:
Since you added that you want all the buttons disabled then this method should work nicely. Examples:
All:
for(Component c : panel.getComponents()){
c.setEnabled(false);
}
Just JButtons:
for(Component c : panel.getComponents()){
if(c instanceof JButton){
((JButton)c).setEnabled(false);
}
}
No, you can't. If setEnabled() returned the object it's enabling, you could enable-and-add the object in a single line. But as it is, setEnabled() returns void, so you have no choice but to use a local variable.
However, a JButton is enabled by default, so there's no need to explicitly call setEnabled() on it, it's already enabled!
You can call a method in a new instance like
new JButton().setEnabled(true);
But this won't allow you to access the JButton instance you create here anymore and thus you cannot call add().
This can only be possible if the method call returns the instance object on which it was called. So if for example setEnabled would return the same instance on which it was called (that is, this in setEnabled context) , you could do add(new JButton().setEnabled(true)).
Anyway in your case don't be afraid of using references:
final JButton button = new JButton();
button.setEnabled(true);
add(button);
Note that in this case 2 last methods can be called in any order, the result will be the same.
The only way this can work is if what ever you are adding it to has a get method. other than that you don't have any other options. Best way is what you showed.
JButton button = new JButton();
button.setEnable(true);
for(i=0; i<16; i++){
images[i]=new ImageIcon(getClass()
.getResource("/images/1 ("+i+").jpg"));
}
for( i=0; i<buttons.length; i++){
for (j=0; j<buttons[i].length;j++){
n=i*buttons.length+buttons[i].length;
buttons[i][j]=new JButton();
label[n].setIcon((images[i*buttons.length+j]));
buttons[i][j].add(label[n]);
label[n].setVisible(false);
panel.add(buttons[i][j]);
buttons[i][j].addActionListener(this);
}
}
public void actionPerformed(ActionEvent e) {
if(e.getSource() instanceof JButton){
JButton pressedButton = (JButton) e.getSource();
opens[open]=(JButton) e.getSource(); //i want to put label[n] into array?
if((pressedButton.getIcon() == null)){
label[n].setVisible(true);
open=open++;
} else {
//pressedButton.setIcon(null);
}
}
if (open==1){
opens[0].setVisible(false);
opens[1].setVisible(false);
}
}
hello friends.i am making a memory game, if buttons have same icon, they will stay open.
i made frame in it panel, in it buttons and each button has label. If facing is true and user click, they will open by setvisible(true)
but in void actionperformed, how can i take label[n]? Not button[][]?
label[n].setIcon((images[i*buttons.length+j]));
i think error is that.is not it correct? because it doesnot execute.
edit after suggestions:
for(i=0; i<16; i++){
images[i]=new ImageIcon(getClass().getResource("/images/1 ("+i+").jpg"));
} //adding images to local variables
for( i=0; i<buttons.length; i++){
for (j=0; j<buttons[i].length;j++){
n=i*buttons.length+buttons[i].length;
buttons[i][j]=new JButton();
//buttons[i][j].setIcon((images[i*buttons.length+j]));
//if i make this code, all icons are displayed at first?
panel.add(buttons[i][j]);
buttons[i][j].addActionListener(this);
}
}
public void actionPerformed(ActionEvent e) {
if(e.getSource() instanceof JButton){
JButton pressedButton = (JButton) e.getSource();
if(pressedButton.getIcon() == null){
pressedButton.setIcon((images[i*buttons.length+j]));
} else {
pressedButton.setIcon(null);
}
}
}
I made this code how you suggested. but now images dont display and clicks doesnot work.
I think this post is related to this question. Maybe an assignment?
Couple of tips:
label[n].setIcon((images[i*buttons.length+j]));
How many images do you have in images array? A quick math would say that if you have for instance a 4x4 array then you'll need i*buttons.lenght+j == 4*4+4 == 20 images at last iteration. And you only would need i*j/2 == 8 images, assuming is a pair match game.
if buttons have same icon, they will stay open. i made frame in it
panel, in it buttons and each button has label.
Why do you need labels? I think if two button matches you can disable those buttons so user won't be able to click them again and dispatch an actionPerformed event.
If it's not strictly necessary use arrays, you could use ArrayList instead and get benefits of its methods.
Update
I post this code because I think you still stuck using arrays. I just want to show you that there's no need to use them to keep references, you just need think a little more under objects paradigm and delegate this task to appropriate object.
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
public class Demo {
/*
* This variable will point to a pressed button to keep reference.
*/
JButton _alreadyPressedButton = null;
/**
* Initializes the GUI
*/
private void initGUI(){
/*
* Create needed icons - As this example uses 6 buttons, then I need 3 icons
*/
ImageIcon icon1 = (ImageIcon) UIManager.getIcon("OptionPane.errorIcon");
ImageIcon icon2 = (ImageIcon) UIManager.getIcon("OptionPane.informationIcon");
ImageIcon icon3 = (ImageIcon) UIManager.getIcon("OptionPane.warningIcon");
/*
* Make a list with 6 icons (add each icon twice)
*/
List<ImageIcon> iconsList = new ArrayList<>();
iconsList.add(icon1);
iconsList.add(icon1);
iconsList.add(icon2);
iconsList.add(icon2);
iconsList.add(icon3);
iconsList.add(icon3);
Collections.shuffle(iconsList); /* Shuffle the list */
ActionListener actionListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() instanceof JButton){
final JButton pressedButton = (JButton) e.getSource();
/*
* Execute this code in a SwingWorker to prevent block EDT at "Thread.sleep(500)" line
* Google for EDT (Event Dispatch Thread)
*/
SwingWorker sw = new SwingWorker() {
#Override
protected Object doInBackground() throws Exception {
if(_alreadyPressedButton != pressedButton){
pressedButton.setIcon(pressedButton.getPressedIcon());
if(_alreadyPressedButton != null){
Thread.sleep(500);
if(_alreadyPressedButton.getIcon() == pressedButton.getIcon()){
_alreadyPressedButton.setEnabled(false);
pressedButton.setEnabled(false);
} else {
_alreadyPressedButton.setIcon(null);
pressedButton.setIcon(null);
}
_alreadyPressedButton = null;
} else {
_alreadyPressedButton = pressedButton;
}
}
return null;
}
};
sw.execute();
}
}
};
JPanel panel = new JPanel(new GridLayout(3, 2));
panel.setPreferredSize(new Dimension(200, 200));
for(ImageIcon icon : iconsList){
JButton button = new JButton();
button.setPressedIcon(icon);
button.addActionListener(actionListener);
panel.add(button);
}
JFrame frame = new JFrame("Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(panel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Demo().initGUI();
}
});
}
}
You appear to be adding a JLabel to a JButton?? If this is what in fact you're doing, don't. Instead, why not simply set the JButton's ImageIcon when you desire to show or change what image the button displays, if any. You would do this simply via myButton.setIcon(fooIcon).
Edit
You state in comment:
and how will it show the image from jbutton and hide it?
You can simply swap icons. If you want to show an image, set its ImageIcon as the JButton's Icon via setIcon(myIcon). and when done, swap it out via either setIcon(otherIcon) or setIcon(null).
The link that you've provided does not put JLabels on top of JButtons which it appears that you're trying to do, and which is why I'm telling you this information.