I am a beginner java programmer, trying to implement ActionListener through an Inner class. Following is the simple code where I want to change label text on button click but instead of using getSource for more than one components I want to use Inner Class. Here is my code :
public class InnerClasses extends JPanel {
static JFrame frame ;
static JButton button ;
static JLabel label ;
public static void main(String[] args) {
InnerClasses i= new InnerClasses();
frame= new JFrame("Inner class");
frame.setSize(400,400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(i);
label = new JLabel(BorderLayout.NORTH);
label.setText("I m label");
i.add(label);
button = new JButton(BorderLayout.SOUTH);
button.setText("Click me ");
button.addActionListener(new innerclass() );
i.add(button);
frame.setVisible(true);
}
class innerclass implements ActionListener {
#Override
public void actionPerformed(ActionEvent arg0) {
label.setText("i have been changed");
}
}
now when i try to register listener to button it gives error
No enclosing instance of type InnerClasses is accessible. Must qualify
the allocation with an enclosing instance of type InnerClasses (e.g.
x.new A() where x is an instance of InnerClasses).
Please help me with it if i am doing something agaisnt the syntax or whats wrong here
Your inner class is not static, so you cannot instantiate it from a static method, and in general, it is better to define inner classes as static, otherwise a new class (not instance) will be created for each instance of the enclosing class:
static class Innerclass implements ActionListener
to create any GUI required some hierarchy, based on Oracle tutorials and good practicies, code ordering could be important
don't to create any Swing GUI Objects inside main methods
I can't found any reason to declare anything static in Java
for example
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class InnerClasses {
private JFrame frame;
private JPanel panel;
private JButton button;
private JLabel label;
public InnerClasses() {
label = new JLabel();
label.setText("I m label");
button = new JButton();
button.setText("Click me ");
button.addActionListener(new MyActioListener());
panel = new JPanel();
panel.add(label);
panel.add(button);
frame = new JFrame("Inner class");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel);
frame.setSize(400, 400);
frame.setVisible(true);
}
class MyActioListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent arg0) {
label.setText("i have been changed");
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
InnerClasses innerClasses = new InnerClasses();
}
});
}
}
Related
my code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Events1 extends JFrame {
private JLabel label;
private JButton button;
public Events1() {
setLayout(new FlowLayout());
label = new JLabel("");
button = new JButton("Click for text");
add(button);
add(label);
event e = new event();
button.addActionListener(e);
}
public class event implements ActionListener {
public void actionPerfomed(ActionEvent e) {
label.setText("See motherfucker it does do stuff");
}
}
public static void main(String[] args) {
Events1 window = new Events1();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(500, 500); //.pack();
window.setVisible(true);
window.setTitle("Attempt 2");
}
}
Basically I'm new to GUI's and get the error message when I try to compile the above code:
Events1.java:25: error: Events1.event is not abstract and does not override abstract method actionPerformed(ActionEvent) in ActionListener
public class event implements ActionListener {
^
1 error
I basically made this code based on the information on the Oracle Docs and and pretty confused of why this doesn't work/how to fix it.
Any help is greatly appreciated thanks.
You have a typo in overriden method
public void actionPerformed(ActionEvent e)
That's why you should use #Override annotation for overriden methods and IDE support for this kind of operations.
today i try to do a example of a "Window" on Java. I try to Concat the Title but my "GetTitle()" don't work! Anyone can help me with this?
And why "public class MiVentana extends JFrame {" and "MiVentana Frame = new MiVentana("Titulo");" says warning?
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MiVentana extends JFrame {
public MiVentana (String Titulo){
this.setTitle(Titulo);
this.setSize(300,400);
this.setLocation(160,80);
this.setLayout(new FlowLayout());
this.ConfigurarVentana();
this.setVisible(true);
}
public void ConfigurarVentana(){
JPanel panel = new JPanel();
JButton boton = new JButton ("OK");
boton.addActionListener(new EscuchadorBoton());
panel.add(boton);
this.add(panel);
}
class EscuchadorBoton implements ActionListener{
public void actionPerformed(ActionEvent a){
this.setTitle(this.getTitle().concat(this.getTitle()));
}
}
public static void main(String[] args) {
MiVentana Frame = new MiVentana("Titulo");
//frameTest.setVisible(true);
}
}
EDIT: I'm working on Ubuntu 14.04 IDE Eclipse 3.8
Using this inside the ActionListener refers to the EscuchadorBoton listener, not the instance of MiVentana - your JFrame.
Using MiVentana.this should refer to the window, not the listener and you'll be able to get and set the title with that.
This post describes what is happening a bit better - basically you want this from the enclosing class, not the enclosed class.
Basically instead of doing this:
this.setTitle(this.getTitle().concat(this.getTitle()));
You need to do this:
MiVentana.this.setTitle(MiVentana.this.getTitle().concat(MiVentana.this.getTitle()));
I have a program which displays two buttons and changes the image of one of the buttons on roll over. I am getting an error on my
press.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
part, And it looks like this: The method setDefaultCloseOperation(int) is undefined for the type ButtonClass. Even with the exit on close commented out there are more errors, please help.
Main class (with error):
package Buttons;
import javax.swing.JFrame;
public class Main_buttons{
public static void main(String[] args) {
ButtonClass press = new ButtonClass();
press.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
press.setSize(300,200);
press.setVisible(true);
}
}
ButtonClass class:
package Buttons;
import java.awt.FlowLayout; //layout proper
import java.awt.event.ActionListener; //Waits for users action
import java.awt.event.ActionEvent; //Users action
import javax.swing.JFrame; //Window
import javax.swing.JButton; //BUTTON!!!
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane; //Standard dialogue box
public class ButtonClass extends JButton {
private JButton regular;
private JButton custom;
public ButtonClass() { // Constructor
super("The title"); // Title
setLayout(new FlowLayout()); // Default layout
regular = new JButton("Regular Button");
add(regular);
Icon b = new ImageIcon(getClass().getResource("img.png"));
Icon x = new ImageIcon(getClass().getResource("swag.png"));
custom = new JButton("Custom", b);
custom.setRolloverIcon(x); //When you roll over the button that says custom the image will change from b to x
add(custom);
Handlerclass handler = new Handlerclass();
regular.addActionListener(handler);
custom.addActionListener(handler);
}
private class Handlerclass implements ActionListener { // This class is inside the other class
public void actionPerformed(ActionEvent eventvar) { // This will happen
// when button is
// clicked
JOptionPane.showMessageDialog(null, String.format("%s", eventvar.getActionCommand()));//Opens a new window with the name of the button
}
}
}
I have searched everywhere for this problem and found nothing. Please tell me how to resolve this issue about exiting my window.
Thanks!
You're a little confused as you're creating a class that extends JButton, and calling setVisible(true) on it as if it were a top-level window such as a JFrame or JDialog, and that doesn't make sense. Since it isn't a top-level window it also makes sense to not have a default close operation or understand what that means.
I suggest that you call this method only on top-level windows such as on a JFrame or JDialog and the like. As a side recommendation, I usually avoid setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); and instead more often do setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); which gives it a little more flexibility.
Edit: actually, just change your class to extends JFrame not extends JButton.
Make sure your image path to your resources is correct. For example:
that method is defined for JFrame, not JButton. You're calling it on an instance of a class that extends JButton
The JFrame.Exit_on_close must be used in a JFrame, and you are extending from JButton.
To set a JButton to close a JFrame its something like this.
public class MyClass extends JFrame implements ActionListener{
private JButton button = new JButton("Button");
private JPanel panel = new JPanel();
public static void main(String args[]) {
new MyClass();
}
public MyClass() {
setSize(300, 300);
button.addActionListener(this);
panel.add(button);
add(panel);
setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
this.dispose();
}
}
My problem is quite hard to word but here is the basic outline:
I have an interface:
public interface TheInterface {
/**
*
* Returns a string
*/
public String getStuff();
}
I have an abstract class that implements this interface:
public abstract class GenericClass implements TheInterface {
public GenericClass() {
// TODO Auto-generated constructor stub
}
#Override
public String getStuff() {
return "Random string";
}
}
I then have a class that extends GenericClass
public class GUIClass extends GenericClass {
private myFrame myNewFrame;
public GUIClass() {
super();
myNewFrame = new myFrame();
}
}
As you can see, the GenericClass has a frame:
import javax.swing.JFrame;
public class myFrame extends JFrame {
private myPanel topPanel;
public myFrame() {
topPanel= new myPanel();
add(topPanel);
setSize(400,200);
//setLocation(200,200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("Test Program");
setVisible(true);
}
}
And inside that frame is a panel which contains a label:
import java.awt.GridLayout;
import java.awt.Label;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class myPanel extends JPanel {
private JLabel myLabel;
public myPanel() {
setLayout(new GridLayout(0,2));
add (new Label("This label should contain the content of getStuff(): "));
myLabel=new JLabel();
add (myLabel);
}
}
And what I want to do here is to call getStuff() from the GenericClass and have it displayed inside that label. However at the moment I have no access to it and it seems that my design is flawed. I would appreciate it if anyone could help to rearrange or change this so that it would be possible to call that method in the label in the most efficient way without multiple cases of the same code.
Thanks.
You could use the Observer pattern:
public interface StuffObserver {
/**
*
* Pass whatever you want, perhaps getStuff(),
* but that method might be removed by the time we're done here
* (depends on what else might need to query/track it without,
* an observer)
*/
private void onStuffChanged(String newStuff);
}
Your Panel class is now
public class myPanel extends JPanel implements StuffObserver
which contains
private void onStuffChanged(String newStuff)
{
Runnable changeText = new Runnable() {
public void run() {
myLabel.setText(newStuff);
}
};
SwingUtilities.invokeLater(changeText);
}
make sure you have myLabel referencing the actual label you added to panel (your current code around that might not be what you want?)
From here, have perhaps GenericClass or it's subclass GUIClass can have a List of StuffObservers (with methods to add or delete from)
private List<StuffObservers> stuffObservers = new ArrayList<>();
public void addStuffObserver(StuffObserver ob)...
// looks familar? Same way Swing has addActionListener() on some components
public void deleteStuffObserver(StuffObserver ob)...
GUIClass can simply call something like:
myNewFrame = new myFrame();
addStuffObserver(myNewFrame.getPanel());
Your GenericClass or GUIClass can also do the following whenever it changes what the outcome of getStuff() can be:
for (StuffObserver ob : stuffObservers)
{
ob.onStuffChanged(someStringRepresentingWhatYouWouldChangeGetStuffTo);
}
And get rid of getStuff() now. Anytime you change the state that getStuff() would have returned, your JLabel will now auto update to display that data.
I would suggest you construct and manage your GUI components directly in GUIClass instead of auto-managing them in custom subclasses.
public class GUIClass extends GenericClass {
private JFrame frame;
private JPanel panel;
private JLabel label;
public GUIClass() {
super();
initialisation();
setLabelText(getStuff());
}
private void initialisation() {
// Label
this.label = new JLabel();
this.label.setText(getStuff());
// Panel
this.panel = new JPanel();
this.panel.setLayout(new GridLayout(0, 2));
this.panel.add(this.label);
// Frame
this.frame = new JFrame();
this.frame.add(this.panel);
this.frame.setSize(400, 200);
this.frame.setLocation(200, 200);
this.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.frame.setTitle("Test Program");
this.frame.setVisible(true);
}
private void setLabelText(String text) {
this.label.setText(text);
}
}
This is a design suggestion, so I might have forgotten some elements from your original code, but I think you can get the idea!
I'm new to java coming from C# so I'm not familiar with java best practices.
I have a main class that opens a JFrame to get several input strings from a user. When the user clicks submit the GUI should close and the main class continue processing using the input.
This is the main class:
public class Main {
FInput fInput;
public void main(String[] args) {
if(args.length==0)
{
fInput = new FInput();
fInput.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fInput.pack();
fInput.setVisible(true);
}
else
startProcess(args);
}
public void startProcess(String[] args) {
// Do stuff
}
The main class will use this frame to get input from the user:
public class FInput extends JFrame{
private JTextField txtSourceDirectory;
private JTextField txtTargetDirectory;
private JTextField txtDefectNumber;
private JTextField txtSliceTokens;
private JButton btnStart;
public FInput() {
// Initialize text fields and button
JButton.addActionListener(something);
}
}
In all the examples I could find, the listener would be a FMain itself. However in this case I want Main to listen and use the input in method startProcess.
Would having Main implement ActionListener, and passing it to FMain constructor is the way to go?
Yes, that is the right idea. You must do two things in order to be able to do that, though:
Put this at the beginning of the FInput class:
Main m = new Main(this);
Then, put these lines somewhere in the Main class...
FInput gui;
public Main(FInput in) { gui = in; }
Now you can refer to any component in the FInput class from the Main class by doing something like this.
gui.someComponent ...
To set up listeners just write someComponent.addItemListener(m); or something of the sort.
Hope this helps!
#Yoav In response to your latest comment...
You don't have to separate the listening class from the GUI class; you can combine the two into one class...
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Main extends JFrame implements ActionListener {
private JTextField txtSourceDirectory;
private JTextField txtTargetDirectory;
private JTextField txtDefectNumber;
private JTextField txtSliceTokens;
private JButton btnStart;
public Main() {
txtSourceDirectory = new JTextField(40); //change this to the amount of characters you need
txtTargetDirectory = new JTextField(40);
txtDefectNumber = new JTextField(40);
txtSliceTokens = new JTextField(40);
btnStart = new JButton("Start");
add(txtSourceDirectory);
add(txtTargetDirectory);
add(txtDefectNumber);
add(txtSliceTokens);
add(btnStart);
btnStart.addActionListener(this);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setVisible(true);
}
public void actionPerformed(ActionEvent event) {
//do stuff
}
static void startProcess(String[] ARGS) {
//do stuff
}
public static void main(String[] args) {
if (args.length == 0) {
Main frame = new Main();
} else {
startProcess(args);
}
}
}
Also consider using JOptionPane, shown here, in your Main class. You can customize the appearance, including button text, as shown in How to Make Dialogs.
First main method in java always must be public static void. Below is example how this can be done.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
/**
* Main class is frame but also implements ActionListener interface.
*/
public class Main extends JFrame implements ActionListener {
private JButton btnStart;
private static Main frame;
public Main() {
JPanel panel = new JPanel();
btnStart = new JButton("Press me");
// Add action listener. Listener could be any class that implements
// ActionListener
btnStart.addActionListener(this);
// This means add button btnStart to panel
panel.add(btnStart);
// This means add panel to frame
this.add(panel);
}
// main method in java always must be public, static and void. You forgot to
// put static.
public static void main(String[] args) {
if (args.length == 0) {
frame = new Main();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
} else
frame.startProcess(args);
}
public void startProcess(String[] args) {
// TODO
}
#Override
public void actionPerformed(ActionEvent arg0) {
// Here you put your code that is executed every time you press button.
// For example you just want to show message.
JOptionPane.showMessageDialog(this, "You pressed Button.");
}
}
But it is much better to have special class. For example:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
public class ButtonListener implements ActionListener {
JFrame parent;
public ButtonListener(JFrame parent) {
this.parent = parent;
}
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(parent, "You pressed Button");
}
}
And in the main class you just add action listener to button:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
/**
* Main class is frame but also implements ActionListener interface.
*/
public class Main extends JFrame {
private JButton btnStart;
private static Main frame;
public Main() {
JPanel panel = new JPanel();
btnStart = new JButton("Press me");
ButtonListener listener = new ButtonListener(this);
// Add action listener. Listener could be any class that implements
// ActionListener
btnStart.addActionListener(listener);
// This means add button btnStart to panel
panel.add(btnStart);
// This means add panel to frame
this.add(panel);
}
// main method in java always must be public, static and void. You forgot to
// put static.
public static void main(String[] args) {
if (args.length == 0) {
frame = new Main();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
} else
frame.startProcess(args);
}
public void startProcess(String[] args) {
// TODO
}
}