I'm looking to recall a JButton's value when clicked i.e. when the user clicks a JButton, the value of that JButton (which is a single letter) will be written to a JLabel. The user will click multiple buttons and as such, multiple values will need to be stored and printed. Finally the user will click a button and the JLabel holding all recieved JButton values will be stored (Obviously using an array).
Here is what my JButton's look like in code:
theModel.randomLetters();
for(int i=0;i<16;i++){
JButton dice = new JButton(theModel.letters.get(i));
dice.addActionListener(disableButtonListener);
boggleGrid.add(dice);
}
theModel.randomLetters(); is a reference to another class with "letters" being an array holding 16 values. Will I need to add each JButton individually to the boggleGrid so their individual names can be recalled to achieve the goal stated above, or do they have individual names and I don't know it? (I've used a for loop someone gave me so I'm not sure if there are individual names for each JButton)
Thanks, and sorry if this is elementary
Read the following code, you'll get some ideas...
I used a StringBuilder to store the values of the Button's each time they were clicked by using StringBuilder.append(JButton.getText().toString()). That was done in the actionPerformed methods of the JButtons.
Then finally in the Done buttons actionPerformed method I had stored the text the string builder held in an array.
P.S. I know you're using 16 JButton's I just used 3 for simplicity...
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.util.ArrayList;
public class GUI extends JFrame{
ArrayList<String> numbers = new ArrayList<>();
StringBuilder sb = new StringBuilder();
JButton button1;
JButton button2;
JButton button3;
JButton doneButton;
JPanel row1 = new JPanel();
JPanel textLabelRow = new JPanel();
JLabel label = new JLabel();
JPanel row3 = new JPanel();
public void create(){
setTitle("S-O");
setSize(500,200);
setLayout(new GridLayout(3,1,10,10));
button1 = new JButton("1");
button2 = new JButton("2");
button3 = new JButton("3");
doneButton = new JButton("Done");
row1.add(button1);
row1.add(button2);
row1.add(button3);
button1.addActionListener(new Button1Listener());
button2.addActionListener(new Button2Listener());
button3.addActionListener(new Button3Listener());
doneButton.addActionListener(new doneButtonListener());
textLabelRow.add(label);
row3.add(doneButton);
add(row1);
add(textLabelRow);
add(row3);
setVisible(true);
}
private class Button1Listener implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
sb.append(button1.getText().toString());
}
}
private class Button2Listener implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
sb.append(button2.getText().toString());
}
}
private class Button3Listener implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
sb.append(button3.getText().toString());
}
}
private class doneButtonListener implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
label.setText(sb.toString());
numbers.add(sb.toString());
sb = new StringBuilder();
}
}
public static void main(String[] args){
GUI start = new GUI();
start.create();
}
}
EDIT:
You could just use one class which implements ActionListener opposed to having one for each JButton.
With in the actionPerformed method "public void actionPerformed(ActionEvent ev)"
You would have to ev.getActionCommand(), that would return the text value of the JButton which caused the event. Then you could append that to the StringBuilder.
So something along the lines of this:
private ArrayList listForEdit = new ArrayList<>();
StringBuilder sbEdit = new StringBuilder();
class actionHandler implements ActionListener{
public void actionPerformed(ActionEvent ev){
if(ev.getActionCommand.equals("Done"))
listForEdit.add(sbEdit);
sbEdit = new StringBuilder();
}
else{
sbEdit.append(ev.getActionCommand());
}
}
Related
I have four buttons each on four different panels. If I press the button I would want the panel it's on to change color. The problem is I only know how to do that for one button and not all four. Here is my code so far...
public class tester implements ActionListener
{
JPanel B;
JPanel A;
public static void main(String[]args)
{
new tester();
}
public void tester()
{
JFrame test = new JFrame("tester:");
B = new JPanel();
A= new JPanel();
JPanel cc = new JPanel();
JPanel dd = new JPanel();
JButton b = new JButton("ButtonB");
JButton a = new JButton("ButtonA");
JButton c = new JButton("ButtonC");
JButton d = new JButton("ButtonD");
test.setLayout(new GridLayout(2,2));
test.setSize(600,500);
B.setBackground(Color.BLUE);
A.setBackground(Color.RED);
cc.setBackground(Color.BLACK);
dd.setBackground(Color.WHITE);
B.add(b);
A.add(a);
cc.add(c);
dd.add(d);
test.add(A);
test.add(B);
test.add(cc);
test.add(dd);
test.setVisible(true);
b.addActionListener(this);
a.addActionListener(this);
}
public void actionPerformed(ActionEvent e)
{
B.setBackground(Color.PINK);
}
}
You can use anonymously created Action listeners instead of implementing interface in your class.
b.addActionListener(new ActionListener() {
//method impl.
});
And use that to create 4 different actions.
Or you could get source of action from
e.getSource()
And then decide based on that.
Or you can skip ActionListener all the way, and use lambda
b.addActionListener(e -> someActionOrSomething(e))
You have to check the resource and can perform action based on it If you are trying to keep a common ActionListener,
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==b)//button b
B.setBackground(Color.PINK);
else if(e.getSource()==a)//button a
A.setBackground(Color.BLACK);
}
Please note you have to declare your buttons globally, If you have to use it inside the class,
public class Test implements ActionListener
{
JPanel B;
JPanel A;
JButton b;
JButton a;
Also you have created the implementation in a method called tester which should be called as,
new Test().tester();
First I am a beginner in java. I'm making a window with small button and a label (with 0 in default position), when I click on the button the label will change to 1 and when I tap another click the button will be 2. But, I have an error in calling the method.
my code:
package prototype;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Prototype {
public static int count;
public static JLabel l;
public void Proto()
{
JFrame f = new JFrame();
JButton b = new JButton("click");
JLabel lo = new JLabel("0");
JPanel p = new JPanel();
f.setBounds(120,120,500,500);
b.addActionListener(new MyAction());
p.add(lo);
p.add(b);
f.getContentPane().add(p,BorderLayout.CENTER);
f.show();}
public class MyAction implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
count++;
l.setText(Integer.toString(count));}
public static void main(String[] args) {
//I want to call the proto method but it give me an eror
new proto();
}}}
public class Prototype extends JFrame{
private static int count;
private JLabel l;
public Prototype() {
super();
JButton b = new JButton("click");
l = new JLabel("0");
JPanel p = new JPanel();
b.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
count++;
l.setText(Integer.toString(count));
}
});
p.add(l);
p.add(b);
this.getContentPane().add(p, BorderLayout.CENTER);
this.pack();
this.setVisible(true);
}
public static void main(String...args){
Prototype p=new Prototype();
}
}
I changed the method to a constructor, to have the possibility of creating a object of type Prototype and directly create a frame with it. Also I extended the class with JFrame to not need to create an extra JFrame. Next step was to remove the ActionListener class and creating a new ActionListener while adding it to the button. In my eyes this is useful if you have several buttons with different functionalities, so you can see the function of the button directly just by looking at the code of the button. and the last step was to create a new Object of type Prototype in the main method
If I we're you use a SwingWorker instead of manually setting the text of JLabel. Because this is not a proper way updating your GUI. This should be done using SwingWorker. Please read about publish and processmethod.
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.
I'm having troubles with the .getText() command trying to retrieve data from a JTextField. I've been looking for the solution but couldn't find it. Is there anybody who can see what I'm doing wrong?
What I'm trying is to make is a bouncing ball which parameters such as elasticity, gravity and initial speed can be changed.
When trying to compile the following message appears:
ERROR in BBPanel.java (at line 88) String gravityIn = gravity_input.getText();
gravity_input cannot be resolved
Thanks!
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/////////////////////////////////////////////////////////////////// BBPanel
class BBPanel extends JPanel {
BallInBox n_bb; // The bouncing ball panel
//========================================================== constructor
/** Creates a panel with the controls and bouncing ball display. */
BBPanel() {
//... Create components
n_bb = new BallInBox();
JButton startButton = new JButton("Start");
JButton stopButton = new JButton("Stop");
JButton resetButton = new JButton("Reset");
JButton gveButton = new JButton("GetData");
JLabel gravityLbl = new JLabel (" set gravity " );
JLabel velocity_yLbl = new JLabel (" set initial y-dir speed " );
JLabel elasticityLbl = new JLabel (" set elasticity [0-100%]" );
JTextField gravity_input = new JTextField(20);
JTextField velocity_y_input = new JTextField(20);
JTextField elasticity_input = new JTextField(20);
//... Add Listeners
startButton.addActionListener(new StartAction() );
stopButton.addActionListener(new StopAction() );
resetButton.addActionListener(new ResetAction() );
gveButton.addActionListener(new DataAction() );
//... Layout inner panel with three buttons horizontally
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new FlowLayout());
buttonPanel.add(startButton);
buttonPanel.add(stopButton);
buttonPanel.add(resetButton);
//
JPanel variablePanel = new JPanel();
variablePanel.setLayout(new GridLayout(0,2));
variablePanel.add(gravityLbl);
variablePanel.add(gravity_input);
variablePanel.add(velocity_yLbl);
variablePanel.add(velocity_y_input);
variablePanel.add(elasticityLbl);
variablePanel.add(elasticity_input);
variablePanel.add(gveButton);
//... Layout outer panel with button panel above bouncing ball
this.setLayout(new BorderLayout());
this.add(buttonPanel , BorderLayout.NORTH);
this.add(n_bb , BorderLayout.CENTER);
this.add(variablePanel, BorderLayout.EAST);
}//end constructor
////////////////////////////////////// inner listener class StartAction
class StartAction implements ActionListener {
public void actionPerformed(ActionEvent e) {
n_bb.setAnimation(true);
}
}
//////////////////////////////////////// inner listener class StopAction
class StopAction implements ActionListener {
public void actionPerformed(ActionEvent e) {
n_bb.setAnimation(false);
}
}
///////////////////////////////////////// inner listener class ResetAction
class ResetAction implements ActionListener {
public void actionPerformed(ActionEvent e) {
n_bb.resetAnimation(true);
}
}
////////////////////////////////////////// inner listener class GravityAction
class DataAction implements ActionListener {
public void actionPerformed(ActionEvent e) {
String gravityIn = gravity_input.getText();
//System.out.println(gravityIn);
n_bb.setData(true);
}
}
}//endclass BBPanel
The variable gravity_input is only defined locally in the scope of the constructor of BBPanel. You need to make it a class member variable if you wish to make it visible to your DataAction class.
public class BBPanel extends JPanel {
private JTextField gravity_input; // to be initialized...
...
Side note:
Java uses camel-case which would make gravity_input gravityInput.
Your problem is one of scope. The gravity_input is declared inside of a constructor or method. To be visible outside of these blocks, it should be declared in the class similar to how you declare the n_bb field.
Your variable gravity_input should be declared as an instance variable (outside the constructor), for it to be later accessed.
The way you're defining it, the name (not the text field) gravity_input dies as soon as the constructor code terminates (reaches closing brace }).
pass parameters as follows into constructor of DataAction:
class DataAction implements ActionListener {
final JTextField textField;
final BallInBox bb;
public DataAction(final JTextField textField, final BallInBox bb) {
this.textField = textField;
this.bb = bb;
}
public void actionPerformed(ActionEvent e) {
String gravityIn = textField.getText();
//System.out.println(gravityIn);
bb.setData(true);
}
}
and use it like this:
gveButton.addActionListener(new DataAction(gravity_input, n_bb));
Then refactor your other actions in a similar way.
The problem is, that your class DataAction doesn't know about your gravity_input textfield.
The textfield gravity_input is only visible to the class BBPanel. To make it visible to the class DataAction, you have to pass the textfield to that class like this:
class DataAction implements ActionListener {
private JTextField gravity_input;
public DataAction(JTextField txtField) {
gravity_input = txtField;
}
public void actionPerformed(ActionEvent e) {
String gravityIn = gravity_input.getText();
//System.out.println(gravityIn);
n_bb.setData(true);
}
}
and change your BBPanel constructor to this:
BBPanel() {
//... omitted
gveButton.addActionListener(new DataAction(gravity_input));
//... omitted
}
I use the following code to create hot keys for the java form using swing. If I press ALT+N,ALT+R,ALT+1,ALT+2 the cursor moves to correct text fields and I enter the value in corresponding Text Fields. It works properly. My problem is, I have Save and exit JButtons in this form if. I press CTRL+S means the Save button will be selected at the same time If i press CTRL+X means the exit button will be selected. How to create mnemonics for JButton? How to do CTRL+S,CTRL+X this using the following code?
Thanks in advance.
package hotkeys;
import java.awt.event.*;
import javax.swing.*;
import java.net.*;
public class hotkey extends JFrame {
public static void main(String arg[]) {
JLabel Name = new JLabel("Name");
JTextField tf1 = new JTextField(20);
Name.setLabelFor(tf1);
Name.setDisplayedMnemonic('N');
JLabel Regno = new JLabel("RegNO");
JTextField tf2 = new JTextField(20);
Regno.setLabelFor(tf2);
Regno.setDisplayedMnemonic('R');
JLabel Mark1 = new JLabel("Mark1");
JTextField tf3 = new JTextField(20);
Mark1.setLabelFor(tf3);
Mark1.setDisplayedMnemonic('1');
JLabel Mark2 = new JLabel("Mark2");
JTextField tf4 = new JTextField(20);
Mark2.setLabelFor(tf4);
Mark2.setDisplayedMnemonic('2');
JButton b1 = new JButton("Save");
JButton b2 = new JButton("eXit");
JFrame f = new JFrame();
JPanel p = new JPanel();
p.add(Name);
p.add(tf1);
p.add(Regno);
p.add(tf2);
p.add(Mark1);
p.add(tf3);
p.add(Mark2);
p.add(tf4);
p.add(b1);
p.add(b2);
f.add(p);
f.setVisible(true);
f.pack();
}
}
You need to register a keyBinding in the button's component inputmap. In code (repeating a subtle variant of what you have been told to do in your previous questions :-)
// create an Action doing what you want
Action action = new AbstractAction("doSomething") {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("triggered the action");
}
};
// configure the Action with the accelerator (aka: short cut)
action.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("control S"));
// create a button, configured with the Action
JButton toolBarButton = new JButton(action);
// manually register the accelerator in the button's component input map
toolBarButton.getActionMap().put("myAction", action);
toolBarButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
(KeyStroke) action.getValue(Action.ACCELERATOR_KEY), "myAction");
Sun has a really good Description of the whole Key Binding issue. You can find it here:
JavaSE Tutorial on Keybinding
//EDIT
Edited my example code so you can just copy + paste it and it will work. Included the points that were missing, thanks for the feedback.
KeyStroke keySave = KeyStroke.getKeyStroke(KeyEvent.VK_S, Event.CTRL_MASK);
Action performSave = new AbstractAction("Save") {
public void actionPerformed(ActionEvent e) {
//do your save
System.out.println("save");
}
};
JButton b1 = new JButton(performSave);
b1.getActionMap().put("performSave", performSave);
b1.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(keySave, "performSave");
KeyStroke keyExit = KeyStroke.getKeyStroke(KeyEvent.VK_Y, Event.CTRL_MASK);
Action performExit = new AbstractAction("Exit") {
public void actionPerformed(ActionEvent e) {
//exit
System.out.println("exit");
}
};
JButton b2 = new JButton(performExit);
b2.getActionMap().put("performExit", performExit);
b2.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(keyExit, "performExit");
Just modified your code. (inserted code in //**)
Just 1 comment... Ctrl-X is shortcut for edit command "Cut" (along with Ctrl-C & Ctrl-V). You have editable fields in frame. I used Ctrl-Q (quit) instead.
import java.awt.event.*;
import java.beans.PropertyChangeListener;
import javax.swing.*;
import javax.swing.plaf.ActionMapUIResource;
import java.net.*;
public class HotKeys extends JFrame {
public static void main(String arg[]) {
JLabel Name = new JLabel("Name");
JTextField tf1 = new JTextField(20);
Name.setLabelFor(tf1);
Name.setDisplayedMnemonic('N');
JLabel Regno = new JLabel("RegNO");
JTextField tf2 = new JTextField(20);
Regno.setLabelFor(tf2);
Regno.setDisplayedMnemonic('R');
JLabel Mark1 = new JLabel("Mark1");
JTextField tf3 = new JTextField(20);
Mark1.setLabelFor(tf3);
Mark1.setDisplayedMnemonic('1');
JLabel Mark2 = new JLabel("Mark2");
JTextField tf4 = new JTextField(20);
Mark2.setLabelFor(tf4);
Mark2.setDisplayedMnemonic('2');
JButton b1 = new JButton("Save");
JButton b2 = new JButton("eXit");
JFrame f = new JFrame();
JPanel p = new JPanel();
p.add(Name);
p.add(tf1);
p.add(Regno);
p.add(tf2);
p.add(Mark1);
p.add(tf3);
p.add(Mark2);
p.add(tf4);
p.add(b1);
p.add(b2);
// *****************************************************
ActionMap actionMap = new ActionMapUIResource();
actionMap.put("action_save", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Save action performed.");
}
});
actionMap.put("action_exit", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Exit action performed.");
}
});
InputMap keyMap = new ComponentInputMap(p);
keyMap.put(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S,
java.awt.Event.CTRL_MASK), "action_save");
keyMap.put(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_Q,
java.awt.Event.CTRL_MASK), "action_exit");
SwingUtilities.replaceUIActionMap(p, actionMap);
SwingUtilities.replaceUIInputMap(p, JComponent.WHEN_IN_FOCUSED_WINDOW,
keyMap);
// *****************************************************
f.add(p);
f.setVisible(true);
f.pack();
}
}
I provide this as much for me as a learning experience as for anyone else. I've always had difficulty applying code snippets for key binding that I've found in the past and I hope my explanation and code will be clear. Thanks to #kleopatra for her code snippet, on which I base my code below.
(I'm using CAPITAL LETTERS where I should NOT in order to more clearly show what MUST MATCH.)
The code links the Ctrl-Shift-U keystroke to the code in actionPerformed for MYACTION via the matching strings in getInputMap and getActionMap.
The three instances of MYACTION below must match, as must the four instances of MYACTIONBUTTON, as must the two instances of the string MAKE_THESE_MATCH. Call them what you will; just make them match.
The button MYACTIONBUTTON must have MYACTION as the argument to the JButton defining it AND must have getInputMap and getActionMap applied to it.
private static JButton MYACTIONBUTTON;
private static JFrame frame;
private static JPanel panel;
...
Action MYACTION = new AbstractAction()
{
#Override
public void actionPerformed(ActionEvent e)
{
// put action code here
}
};
MYACTIONBUTTON = new JButton(MYACTION);
MYACTIONBUTTON.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
.put(getKeyStroke(VK_U, CTRL_DOWN_MASK | SHIFT_DOWN_MASK),
"MAKE_THESE_MATCH");
MYACTIONBUTTON.getActionMap().put("MAKE_THESE_MATCH", MYACTION);
panel.add(MYACTIONBUTTON);
frame.add(panel);