So, I have a JTextArea. I have added keyboard action to it's input/action maps.
On enter press, JDialog is supposed to be created, along with it's contents. And I need to add keyListener to a button it will contain, which i can't, because that button doesn't ahve final modifier. If I set it to final, I can't edit it's properties.
Here's a snippet of the code:
class blabla extends JTextArea
{
getInputMap.put(KeyStroke.getKeyStroke("ENTER"), "pressedEnter");
getActionMap.put("pressedEnter", new AbstractAction()
{
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e)
{
JDialog dialog;
JButton confirm;;
//JDialog
dialog = new JDialog(Main.masterWindow, "newTitle", true);
dialog.getContentPane().setLayout(new BoxLayout(dialog.getContentPane(), BoxLayout.Y_AXIS));
dialog.addWindowListener(new WindowAdapter()
{
public void windowActivated(WindowEvent e)
{
//this doen't work, it asks me to declare confirm as final
//and I have to request focuse here due to Java bug
confirm.requestFocus();
}
});
//JButton for confirming
confirm = new JButton(lang.getString("ok"));
confirm.setAlignmentX(Component.CENTER_ALIGNMENT);
confirm.addKeyListener(new KeyAdapter()
{
#Override
public void keyPressed(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_ENTER)
{
//this doen't work, it asks me to declare confirm as final
confirm.doClick();
}
}
});
dialog.add(confirm);
dialog.pack();
dialog.setLocationRelativeTo(Main.masterWindow);
dialog.setVisible(true);
}
How can I make this work?
Option 1: make confirm a class field.
Option 2: You could create a dummy final JButton variable, final JButton finalConfirm = confirm; and pass in the confirm reference, and then work on this variable inside of the inner class.
Option 3: don't use an anonymous inner class for your Key Binding's AbstractAction, but rather a private inner class with a constructor that takes the JButton instance.
Related
How to place Action Listener directly in definition of class that extends Button ?
If object of class Button is created then we could simply use anonumous inner class :
b = new Button("Click me");
b.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent e){
System.out.println("stringToPrint");
}
}
);
how to do the same in below :
class CustomizedButton extends Button{
String customClass;
Button(String stringToPrint){
super(customClass); //customClass is also button name
this customString = stringToPrint;
}
/*this.addActionListener( //don't work this way
new ActionListener(){
public void actionPerformed(ActionEvent e){
System.out.println(customClass);//use outer(?) field
}
}
);*/
}
I need to create 20 almost identical but slightly different buttons, so anonymous inner is too long
You could declare a private nested class, like so:
public class CustomizedButton extends Button{
String customClass;
CustomizedButton(String stringToPrint){
super(customClass); //customClass is also button name
this.customString = stringToPrint;
addActionListener(new MyListener());
}
private class MyListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
// TODO: listener code here
}
}
}
But it's not much different from using an anonymous inner class or lambda:
public class CustomizedButton extends Button{
String customClass;
CustomizedButton(String stringToPrint){
super(customClass); //customClass is also button name
this.customString = stringToPrint;
addActionListener(e -> myListenerCode(e));
}
private void myListenerCode(ActionEvent e) {
// TODO: listener code here
}
}
Having said this, other issues come to mind:
Usually it's best to favor composition over inheritance. I would bet that what you really want is some sort of factory method that creates your button complete with listener
Why use AWT components such as the java.awt.Button class when it is 20+ yrs out of date? Why not Swing JButtons instead?
If you were using Swing JButtons, best would be to create a custom Action rather than extend JButton. Actions can hold and change many button properties, including a listener, the displayed text, icons, the tool tip text (displayed on hover)....
For that matter, you should favor JavaFX if this is a new project, since this is the current best-supported Java GUI library.
For example an AbstractAction class could look something like:
public class CustomizedAction extends AbstractAction{
String text;
CustomizedAction(String text, int mnemonic){
super(text); //text is also button name
this.text = text;
putValue(MNEMONIC_KEY, mnemonic); // for alt-key short cut if desired
}
#Override
public void actionPerformed(ActionEvent e) {
String currentName = getValue(NAME); // same value as the text field
System.out.println(currentName);
// TODO: more listener code here
}
}
and could be used like so:
JButton button = new JButton(new CustomizedAction("Foo", KeyEvent.VK_F));
How to check from a class ModalDialog extends JDialog implements ActionListener if actionPerformed(ActionEvent e) method ocurred in another class (Connect extends JFrame implements ActionListener)? And one step further, how to check which of two buttons that I have in ModalDialog fired ActionPerformed method? (I know about event.getSource, but I need to check it from another class).
public ModalDialog()
{
btn8 = new Button("human");
btn8.setMaximumSize(new Dimension(60,40));
btn8.addActionListener(this);
btn9 = new Button("robot");
btn9.setMaximumSize(new Dimension(60,40));
btn9.addActionListener(this);
}
public void actionPerformed(ActionEvent e)
{
}
class Connect extends JFrame implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
ModalDialog md = new ModalDialog();
if(md.ActionPerformed(e)....)...something like that...
}
}
How to check from a class ModalDialog extends JDialog implements ActionListener if actionPerformed(ActionEvent e)
This is a basic problem of how to return information from one class to another. The simple answer is to provide a getter method, which returns the selected value.
Start by defining the value to be returned, here I used a enum, as it clearly defines what could be returned
public enum Option {
HUMAN, ROBOT;
}
Update your ModalDialog to provide a getter to return the selected value
public class ModalDialog extends JDialog implements ActionListener {
private Option selection;
public ModalDialog() {
setModal(true);
Button btn8 = new Button("human");
btn8.addActionListener(this);
Button btn9 = new Button("robot");
btn9.addActionListener(this);
setLayout(new GridBagLayout());
add(btn8);
add(btn9);
pack();
}
public Option getSelection() {
return selection;
}
public void actionPerformed(ActionEvent e) {
//...
}
}
When the dialog is closed, the caller can now call getSelection to get the selected value (or null if the user closed the dialog via the [X] button
And one step further, how to check which of two buttons that I have in ModalDialog fired ActionPerformed method?
This is not an uncommon problem, and there a number of ways you might implement it. Since you've already implemented ActionListener at the class level, you could just make use of the actionCommand support available in buttons, which defaults to the text of the button
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
switch (cmd) {
case "human":
selection = Option.HUMAN;
break;
case "robot":
selection = Option.ROBOT;
break;
}
setVisible(false);
}
So now, when the dialog is closed, you can just request the selected value...
ModalDialog dialog = new ModalDialog();
dialog.setLocationRelativeTo(null);
dialog.setVisible(true);
Option selection = dialog.getSelection();
System.out.println("You choose " + selection);
I'm writing a pretty big class and don't want to post it here. The question is the following, how do I refer to the button that was pressed in the constructor of a different class? Let's say, I want to disable it after some actions in the listener. If the listener were anonymus or were an inner class of the SomeClass, I would just use the name of the variable like this:
button.setEnabled(false);
But how can I do it when my listener is a separate class? Tried using e.getModifiers().setEnabled(false) and e.getSource().setEnabled(false), didn't work.
public class SomeClass extends JPanel {
private JButton button = new JButton("Button");
public SomeClass() {
button.setActionCommand("button");
button.addActionListener(new ButtonListener());
}
public static void main(String[] args) {
// TODO code application logic here
}
}
class ButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
String src = e.getActionCommand();
if (src.equals("button")) {
//some actions here
//then
}
}
}
Try this ((JButton)e.getSource()).setEnabled(false)
It must work)
e.getSource() return component to which this event refers( docs)
Hey all I can change the text of 1 single button easily with "final" but I need to create lots of buttons for a flight booking system, and when the buttons are more, final doesnt work ...
JButton btnBookFlight;
eco = new EconomyClass();
eco.setSeats(5);
for(int i=0;i<20;i++){
btnBookFlight = new JButton("Book" +i);
btnBookFlight.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
btnBookFlight.setBackground(Color.RED);
btnBookFlight.setOpaque(true);
btnBookFlight.setText("Clicked");
}
});
btnBookFlight.setBounds(77, 351, 100, 23);
contentPane.add(btnBookFlight);
}
I would be glad if you can suggest me any trick to get over this.I want to change a buttons color or text when it is clicked or maybe some other cool effects when mouse over but for now only text or color will be enough =).Thanks for your time!
Use the source of the ActionEvent in the ActionListener
btnBookFlight.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
JButton button = (JButton)event.getSource();
button.setBackground(Color.RED);
...
}
});
btnBookFlight has to be final for the inner class (ActionListener) to access it.
From JLS 8.1.3
Any local variable, formal parameter, or exception parameter used but not declared in an inner class must be declared final.
If this is not permitted, then the JButton may be accessed using the source component of the ActionEvent itself using getSource.
However, that said, the simplest solution would be to move the JButton declaration within the scope of the for loop and make it final:
for (int i = 0; i < 20; i++) {
final JButton btnBookFlight = new JButton("Book" + i);
btnBookFlight.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
btnBookFlight.setBackground(Color.RED);
...
}
});
}
Just avoid using anonymous classes for your action listener and the final constraint will disappear.
What I mean is use:
class MyActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
JButton src = (JButton)e.getSource();
// do what you want
}
}
Is there a way to get the propery value we declared this way?
JButton button = new javax.swing.JButton(){
public int value=0;
}
button.addActionListener(listener);
//in action listener
public void ActionPerformed(ActionEvent evt){
JButton btn = (JButton)evt.getSource();
btn.value =2; //error
}
You cannot access properties / methods of annonymous class outside of the instance itself.
The reason is that the compiler knows that btn is a JButton, not your extension, and you can't cast to this extension, as it doesn't have a name.
You need to create an internal class or class in a separate file and instantiate it, for example:
static class MyButton extends JButton {
public int value=0;
}
// ....
MyButton btn = new MyButton();
btn.addActionListener(listener);
// ....
#Override public void actionPerformed(ActionEvent evt){
MyButton btn = (MyButton)evt.getSource();
btn.value = 2;
}
What you can do is use Component.setName() to save at least a string with your Component.