This question already has answers here:
How can I implement ActionListener with a non abstract class? Java
(3 answers)
Closed 7 years ago.
I have this code that uses a textfield from which the program is to receive input from the user so I'm trying to add an ActionListener to my textfield input. However, when I compile I get this error:
Quiz.java:5: error: Quiz is not abstract and does not override abstract method actionPerformed(ActionEvent) in ActionListener
public class Quiz implements ActionListener {
Code:
public class Quiz implements ActionListener {
private static Label lblInput;
private static TextField tfInput;
private static String cityIn;
public void europe() {
JFrame frame = new JFrame();
frame.setLayout(null);
lblInput = new Label("Skriv in huvudstaden i : "); // Construct Label
lblInput.setBounds(40,30,300,40);
frame.add(lblInput);
tfInput = new TextField(10);
tfInput.setBounds(40,70,300,40);
frame.add(tfInput);
tfInput.addActionListener(this);
frame.setTitle("Europa");
frame.setSize(375, 150);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
You must override the actionPerformed(ActionEvent e) method :
public class Quiz implements ActionListener {
private static Label lblInput;
private static TextField tfInput;
private static String cityIn;
public void europe() {
....
}
#Override
public void actionPerformed(ActionEvent e) {
// Your code
}
}
EDIT : (Second way)
You can handle events on your textfield using a custom ActionListener:
public class Quiz implements ActionListener {
private static Label lblInput;
private static TextField tfInput;
private static String cityIn;
public void europe() {
....
tfInput.addActionListener(new CustomActionListener());
...
}
#Override
public void actionPerformed(ActionEvent e) {
// Your code
}
}
class CustomActionListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
// Your code
}
}
Related
I have a TabbedPane in a class called App and i want to run a method in this class. I added two tabs with a JPanel from the class Login and an empty one. Here is the class:
public class App {
private static JTabbedPane tabbedPane;
public JPanel mainPanel;
public App(){
tabbedPane.addTab("Login", new Login().mainPanel);
tabbedPane.addTab("test", new JPanel());
changeFocus(0);
}
public void changeFocus(int i){
//CODE HERE
}
}
Now i want to run a method called changeFocus() from an outer class. A added an actionListener to the Login class with a constructor like this:
public Login() {
logInButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
App.changeFocus(1);
}
});
}
Now i ask why this doesn´t work and changeFocus() must be static. And if i change it to static why the JTabbedPane cannot be static and throws out an error.
Simply pass App as an argument to Login's constructor:
tabbedPane.addTab("Login", new Login(this).mainPanel);
and then:
public Login(App app) {
logInButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
app.changeFocus(1);
}
});
}
I have two frames in NetBeans 9.0 as frame1.java, frame2.javaand the main class as main.java.
If I declare a public variable in frame1.java as
public String stringName;
and a function fn() which gives the value of stringName in frame1as say "abcd".
When I write this in frame2,
frame1 fm = new frame1();
String str = frame1.stringName;
System.out.print(str);
I get the output as null. But what I require is "abcd".
What am I doing wrong, and what should it be?
Thanks for help!
Edit:
I have linked frame1 and frame2 such that the GUI from frame1 leads to frame2, and so does the value.
Edit 2
The process goes like this:
GUI of frame1 is visible >> based on user's input, function fn() stores the value, say "abcd" in stringName >> a button click in frame1 leads to frame2>> variable str gets the value from stringName >> System.out.print(str) outputs the value as null .
CODE
frame1:
public class frame1 extends javax.swing.JFrame {
public String stringName;
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt){
stringName = jTextField1.getText(); // gets a not null value
}
}}
frame2:
public class frame2 extends javax.swing.JFrame {
frame1 fm = new frame1();
String str = frame1.stringName;
System.out.print(str); //outputs a null value
}
The point ist that you are crating a new Instance (frame1, fm) in your class frame2. So the value from the string in this new Instance is null. You need a reference to your old Instance which you maybe have initialised in your main method?
Something like that:
String str = myOldInstance.stringName;
But you should create getter an setter and make your var private.
But to help you exactly we need more Code.
in this case the best is Listener pattern.
Create interface of listener, which will inform about change text. In class - target of this information - create instance of this listener and return that. In class - source of information - set listener and put on field.
When you want inform of change text, you fire method of listener, and on seconde frame will execute implementation of method.
Below example - I fire on button click.
Any way, field should be private, and add getter and setter. Public fields are bad.
Main class
public class App {
public static void main(String[] args) {
Frame1 f1=new Frame1();
Frame2 f2=new Frame2();
TextListener textListener = f2.getListener();
f1.setListener(textListener);
}
}
Listener
public interface TextListener {
public void onTextPropagate(String text);
}
Frame classes
public class Frame1 extends JFrame{
private TextListener listener;
JButton button;
public Frame1() {
super("Frame1");
setBounds(200, 200, 400, 600);
button=new JButton("Action");
button.setBounds(100, 200, 200, 100);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(listener!=null) {
String text = UUID.randomUUID().toString();
System.out.println("On Frame1:\t"+text);
listener.onTextPropagate(text);
}
}
});
this.add(button);
setVisible(true);
}
public void setListener(TextListener listener) {
this.listener=listener;
}
}
public class Frame2 extends JFrame{
public Frame2() {
super("Frame2");
setBounds(100, 100, 200, 400);
setVisible(true);
}
public TextListener getListener() {
return new TextListener() {
#Override
public void onTextPropagate(String text) {
reactOnChangeText(text);
}
};
}
private void reactOnChangeText(String text) {
System.out.println("On Frame2:\t"+text);
}
}
I have the following problem: I have 2 classes in my game - CONFIGUREGAME (CG) and ROULETTETABLE (RT) - and the user is able to specify details about the game like his name or his money in the class CG. In the class RT I want the input from a JTextField from the class CG to be shown on a button in class RT.
Here's my code (I simplified it alot):
public class CONFIGUREGAME extends JFrame implements ActionListener
{
Jframe frame = new JFrame("...");
public JTextField playername1 = new JTextField();
public JButton startgame = new JButton();
public CONFIGUREGAME()
{
startgame.addActionListener(this);
}
public static void main(String (String[] args)
{
new CONFIGUREGAME();
}
public void actionPerformed(ActionEvent aEvt)
{
if(aEvt.getSource()==startgame)
{
frame.dispose();
new ROULETTETABLE();
}
}
now Class 2:
import ...;
public class ROULETTETABLE extends CONFIGUREGAME implements ActionListener
{
public player1 = new JButton();
public ROULETTETABLE()
{
String Strplayername1 = playername1.getText();
player1.setText(Strplayername1);
}
public static void main(String (String[] args)
{
new ROULETTETABLE();
}
}
I tried various ways that were supposed to help but they didn't. My UI is working totally fine so if there's a mistake in it it's because I made a mistake simplifying it.
I appreciate any from of help!
You need something like this.
public class CONFIGUREGAME extends JFrame implements ActionListener
{
Jframe frame = new JFrame("...");
public JTextField playername1 = new JTextField();
public JButton startgame = new JButton();
public CONFIGUREGAME()
{
startgame.addActionListener(this);
}
public static void main(String (String[] args)
{
new CONFIGUREGAME();
}
public void actionPerformed(ActionEvent aEvt)
{
if(aEvt.getSource()==startgame)
{
frame.dispose();
new ROULETTETABLE(playername1.getText());
}
}
}
public class ROULETTETABLE extends CONFIGUREGAME implements ActionListener
{
public JButton player1 = new JButton();
public ROULETTETABLE(String playerName)
{
player1.setText(playerName);
}
public static void main(String (String[] args)
{
new ROULETTETABLE();
}
}
P.S. Please learn the Java method and class notation. CapitalizedClassName, firstWordLowercaseMethodName, firstWordLowercaseVariableName, UPPER_CASE_CONSTANT_NAME
Option #1
Pass the result CONFIGUREGAME to ROULETTETABLE
public class CONFIGUREGAME extends JFrame implements ActionListener {
//Jframe frame = new JFrame("..."); WHY?
//...
public void actionPerformed(ActionEvent aEvt) {
if (aEvt.getSource() == startgame) {
frame.dispose();
new ROULETTETABLE(playername1.getText());
}
}
public class ROULETTETABLE extends JFrame /* CONFIGUREGAME why? */implements ActionListener
{
public JButton player1 = new JButton();
public ROULETTETABLE(String playerName)
{
player1.setText(playerName);
}
}
I'm not a fan of this because it couples of the CONFIGUREGAME class to the ROULETTETABLE
A Better Option...
Use a JDialog to collect the configuration information and then pass it to the ROULETTETABLE class
First, some reconfiguration of the classes. As a general rule, avoid extending from top level classes like JFrame, they couple the code to single access point and reduce it's flexibility and re-use
public class Roulettetable extends JPanel implements ActionListener {
private JButton player1 = new JButton();
public Roulettetable(String name) {
player1.setText(name);
}
}
public class ConfigureGame extends JPanel {
private JTextField playername1 = new JTextField();
public ConfigureGame() {
}
public String getPlayerName() {
return playername1.getText();
}
}
Then you wrap it altogether...
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
ConfigureGame configureGame = new ConfigureGame();
JOptionPane.showOptionDialog(null, configureGame, "Configure Game", JOptionPane.OK_OPTION, JOptionPane.PLAIN_MESSAGE, null, new Object[] {"Start"}, 0);
String name = configureGame.getPlayerName();
Roulettetable roulettetable = new Roulettetable(name);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(roulettetable);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
This example is pretty simple, it simply makes use of JOptionPane to display the dialog.
Have a look at How to Make Dialogs for more details
I've attached an ActionListener to a JButton in Swing.
The main class:
class MainClass {
String foo;
JButton button = new JButton("cool button");
public MainClass(String foo) {
this.foo = foo;
...
JFrame setup here
...
button.addActionListener(new MyBtnListener(frame));
System.out.println(getFoo());
}
public String getFoo() {
return this.foo;
}
}
The class that implements the ActionListener methods:
class MyBtnListener extends MainClass implements ActionListener {
private JFrame target;
public MyBtnListener(JFrame target) {
this.target = target;
}
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("button clicked");
//target.dispose();
}
}
When compiled, the code results in something like this:
foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoo (an infinite loop). I need the ActionListener class to be able to access methods in MainClass, while at the same time not repeatedly calling the constructor. How can I achieve this?
The answer to your question is pretty straight forward: what you search for is called a „reference“.
Just add a private field of the type MainClass to your listener and initialise it in the constructor:
private final JFrame frame;
private final MainClass reference;
public MyBtnListener(final JFrame frame, final MainClass reference)
{
this.frame = frame;
this.reference = reference;
}
Then you can just invoke the getFoo method like this:
final String foo = reference.getFoo();
It is also very important that the MyBtnListener class doesn't extend the MainClass class.
By having MyBtnListener extend MainClass and MainClass having creating a MyBtnListener in its constructor you have created a loop that lasts as long as there is space on the call stack.
Move the button.addActionListener(new MyBtnListener(frame)); to the constructor of MyBtnListener as button.addActionListener(this); or don't have MyBtnListener extend MainClass, just have it implement ActionListener.
class MainClass {
String foo;
JButton button = new JButton("cool button");
public MainClass(String foo) {
this.foo = foo;
...
JFrame setup here
...
button.addActionListener(new MyBtnListener());
System.out.println(getFoo());
}
public String getFoo() {
return this.foo;
}
}
class MyBtnListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("button clicked");
}
}
I was wondering how to retrieve the string textOperandValue,from this code :
final JTextField textOperand = new JTextField();
textOperand.setBounds(200,100,75,25);
//textOperand action Listener
textOperand.addActionListener( new ActionListener () {
public void actionPerformed(ActionEvent e) {
String textOperandValue = textOperand.getText();
}
});
So I can take it, and then parse it into a double to be used later in the program. I tried setting it equal to a another string
String Input = " "; but it said I had to initialize the string to a final String Input = " "; which I learned is something like a constant in C++.
Any variables you declare within an ActionListener won't be visible to the rest of your code. Either you need to set a variable (from within the listener) that has wider scope:
public class Listen
{
String usefulResult = null;
public Listen()
{
final JTextField textOperand = new JTextField();
textOperand.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
Listen.this.usefulResult = textOperand.getText();
}
});
}
}
Here we use the "OuterClass.this" trick to access the surrounding scope without needing a final variable.
or you need to perform all the necessary work from within the listener itself (i.e. you don't "retrieve" the value, you just use the value):
public void doSomethingUseful(String usefulValue) { /* add code here */ }
textOperand.addActionListener( new ActionListener ()
{
public void actionPerformed(ActionEvent e)
{
doSomethingUseful(textOperand.getText());
}
});
Or you could use this second technique to call a setter method that changes the value of a variable, avoiding the problems of accessing final variables within event listeners:
public class Listen
{
String usefulResult = null;
public void setUseful(String usefulValue){
usefulResult = usefulValue;
}
public Listen()
{
final JTextField textOperand = new JTextField();
textOperand.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
setUseful(textOperand.getText());
}
});
}
}
It depends what you want to do with the value from the TextField.
You can't access the members of anonymous classes. In this case it's even a local variable in a method, those are never accessible.
Either, you'll have to set the value of a member of the outer class, but beware of synchronization trouble.
class MyClass {
final JTextField textOperand = new JTextField();
public String textOperandValue;
public MyClass() {
textOperand.setBounds(200,100,75,25);
//textOperand action Listener
textOperand.addActionListener( new ActionListener () {
public void actionPerformed(ActionEvent e) {
textOperandValue = textOperand.getText();
}
});
}
public someOtherMethod() {
// textOperandValue available here
if (textOperandValue != null)
//is set
}
}
Or, you'll have to call a method somewhere else that can store the value.
class MyClass {
final JTextField textOperand = new JTextField();
public MyClass() {
textOperand.setBounds(200,100,75,25);
//textOperand action Listener
textOperand.addActionListener( new ActionListener () {
public void actionPerformed(ActionEvent e) {
someOtherMethod(textOperand.getText());
}
});
}
public someOtherMethod(String value) {
System.out.println(value);
}
}
Or, you create a (named) class that is an ActionListener and that can store the value in a retrievable form.
class MyClass {
final JTextField textOperand = new JTextField();
public String textOperandValue;
private class MyActionListener implements ActionListener {
String value;
public void actionPerformed(ActionEvent e) {
value =textOperand.getText();
}
}
MyActionListener l = new MyActionListener();
public MyClass() {
textOperand.setBounds(200,100,75,25);
//textOperand action Listener
textOperand.addActionListener(l);
}
public someOtherMethod() {
if (l.value != null)
//is set
}
}
Or, you just do what you need to do in the action method:
class MyClass {
final JTextField textOperand = new JTextField();
public MyClass() {
textOperand.setBounds(200,100,75,25);
//textOperand action Listener
textOperand.addActionListener( new ActionListener () {
public void actionPerformed(ActionEvent e) {
System.out.println(textOperand.getText());
}
});
}
}
it can work if textOperandValue is global(if it defined in class globally) variable.
not inside ActionListener, not inside method where you wrote this code.