Calling Java Interface functions : any other way possible? - java

I want to have a JPanel respond to a MouseEvent, such as, mousePressed(), but not others.
I can do it via the following code added to the JPanel object:
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent me) {
//Some action here
}
});
However, the anonymous function requires that I use final variables inside there. And my program specifications do not allow me to that.
I can also define the MouseEvents not as an inner class, but outside, but then I have to provide implementations for all the functions in the MouseListener interface, such as mouseClicked(), mouseEntered(), mouseExited(), etc.
Is there any other way of achieving what I'm trying to do, i.e. define the mousePressed() function without having to use final variables inside it, and also without having to define the other functions in the interface ?
Thanks a lot !
EDIT: I realize that the code I have provided runs without error because the inner class is creating an object of MouseAdapter which is an abstract class.
However, my question still remains : if I dont want to define all methods of the abstract class, and also not have to use inner classes, is there any way of doing so ?

One of the examples:
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainClass extends JPanel {
public MainClass() {
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent me) {
System.out.println(me);
}
});
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.getContentPane().add(new MainClass());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(200, 200);
frame.setVisible(true);
}
}
Also, you can use official tutorial here.

Related

Why isn't my code being read after the Frame construction?

Right after I create a new Frame object to attach future JPanels to, the references to the object "j" aren't recognized.
package engine;
import javax.swing.*;
public class GamePanel extends JFrame{
final int HEIGHT=700, WIDTH=500;
JFrame j= new JFrame("LittleRPG");
j.setSize(HEIGHT, WIDTH);
}
the j.setSize(); isn't accepted and an error appears (this applies to all object references after the initial construction of them). I need help identifying why; fresh eyes always help. -Thank you
You dont need to create separate object of JFrame to set size because you already extended the GamePanel Class From JFrame. So, You can directly set it in the constructor GamePanel as your code look like:
package engine;
import javax.swing.*;
public class GamePanel extends JFrame
{
final int HEIGHT=700, WIDTH=500;
GamePanel ()
{
setSize(HEIGHT, WIDTH);
}
}
Your setSize(HEIGHT, WIDTH); method has to be inside of a constructor or another method. Like #Vikas Suryawanshi said, you could just call the methods of JFrame, you dont need to create a new Object of it.
The answers of #Tupfer and #Vikas are correct.
Still you want to do it using the object of Jframe then
package engine;
import javax.swing.*;
import java.awt.Color;
public class GamePanel extends JPanel{
final int HEIGHT=700, WIDTH=500;
public static void main(String[] args){
JFrame j= new JFrame("LittleRPG");
j.setSize(HEIGHT, WIDTH);
j.getContentPane().add(new GamePanel());
j.setVisible(true);
j.setLocationRelativeTo(null);
j.setBackground(Color.BLUE);
j.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Also you do not need to extend JFrame

How to add an anonymous instance off a class as an ActionListener

Im working on a lab that requires me to make a JFrame with 2 inner classes. One that entends JPanel, has a text area and a jbutton. And another that implements action listener. How do i add an anonymouse instance of the second class to my JButton that is already in an inner class. Here is the brief to get a better understanding.
here is the code i have written so far. I can get the Frame to appear, but the JPanel doesnt appear, nor does the JButtons or JTextArea.
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
#SuppressWarnings("serial")
public class FormFrame extends JFrame
{
public static void main(String[] args)
{
JFrame frame = new FormFrame();
frame.setLocationRelativeTo(null);
}
public FormFrame()
{
Container contentPane = getContentPane();
RegisterPanel p = new RegisterPanel();
p.button.addActionListener(new SubmitResponder());
//
// Here is where im lost...
//
contentPane.add(p);
setSize(300, 200);
setVisible(true);
}
class RegisterPanel extends JPanel
{
JPanel panel = new JPanel();
JTextField text = new JTextField();
JButton button = new JButton("Submit");
}
class SubmitResponder implements ActionListener
{
#Override
public void actionPerformed(ActionEvent e)
{
if(e.getSource()== RegisterPanel.button) //Asks me to make button static here
{
//Shows "No enclosing instance of the type FormFrame.RegisterPanel is accessible in scope"
RegisterPanel.this.text.setText("Submit Complete");
}
}
}
}
Any help with this would be much appreciated
You could pass the RegisterPanel instance to the action listener:
class SubmitResponder implements ActionListener {
private final RegisterPanel rp;
public SubmitResponder(RegisterPanel rp) {
this.rp = rp;
}
#Override
public void actionPerformed(ActionEvent e) {
rp.text.setText("Submit Complete");
}
}
There's no need to check the source btw. The AL is only listening to 1 source.
RegisterPanel p = new RegisterPanel();
p.button.addActionListener(new SubmitResponder(p));
p.button.addActionListener(new SubmitResponder());
Here the SubmitResponder is already an anonymous instance, quite literally, because it has no name.
Your error about "no enclosing instance" is unrelated. Since SubmitResponder is not an inner class of RegisterPanel (it's a sibling) it doesn't belong to an instance of RegisterPanel and so it cannot logically refer to RegisterPanel.this. How would it know which instance that is? There might be many, or even zero, depending on how many the parent FormFrame decides to create. It so happens that there's only one, but that's not the point. On the other hand if you said FormFrame.this there would be no doubt what that meant no matter the code did, unless RegisterPanel stopped being an inner class or it became static. Does that make sense?
To do what you want, the SubmitResponder needs to talk to RegisterPanel via a method in FormFrame. Incidentally you don't actually need to say FormFrame.this.doSomething() unless SubmitResponder also has a method called doSomething.
The instructions tell you that the RegisterPanel should be a field in the FormFrame class, which you haven't done. Something like this:
public class FormFrame extends JFrame
{
RegisterPanel panel;
...
public FormFrame()
{
panel = new RegisterPanel();
...
}
...
class SubmitResponder implements ActionListener
{
#Override
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == panel.button)
{
panel.text.setText(...);
}
}
}
}
Now you can access panel from inside the SubmitResponder class.
As a side note, the instructions are using some terminology in an ambiguous and incorrect way:
"Anonymous instance" is not an official term with a precise meaning.
Using official definitions, "class field" would imply the static modifier. Given the context of the assignment, I doubt that's correct. It should probably have said "instance field".

Separate my ActionListener from my GUI class, doesn't work properly

This is how my code looked in the beginning: https://gist.github.com/anonymous/8270001
Now I removed the ActionListener to a separate class: https://gist.github.com/anonymous/8257038
The program should give me a little UI, but it just keeps running without any UI popup or errors.
Someone told me this:
In your GUI class constructor, you are creating a new nupuVajutus object, but since nupuVajutus extends the GUI class, when you create a nupuVajutus, you are also inherently calling the GUI class constructor by default, thus creating an infinite loop
If this is really the problem, then I have to say I am not that good and could use some help getting this program working with the classes separated.
You have indeed already been given the answer, although what you have is not an infinite loop, but infinite recursion, which will eventually cause a StackOverflowError.
Here's what happens:
new GUI() calls new nupuVajutus(). This creates a new nupuVajutus object by calling its constructor. Because nupuVajutus extends GUI, this means a nupuVajutus object is a GUI object with additional functionality. Therefore, because it is a GUI object, a GUI constructor needs to be called. The nupuVajutus constructor does not explicitly call a super constructor, so it implicitly calls the GUI() (no argument) constructor before executing. In this new call to the GUI() constructor, another new nupuVajutus() call is encountered, and so on, ad infinitum...
It seems to me you need to do some more research around Object Oriented Programming, in particular the topics of sub-classing, inheritance, object instances, and encapsulation. There are plenty of resources available to help you.
After you extracted your ActionListener into a separate file, you should not have changed it to extend GUI. That extends the class (which is like a blueprint) not an instance (which is like a something built using that blueprint) - remember: you can create multiple instances of a class.
Previously, the "nupuVajutus" ActionListener was an inner class, so it had access to all of the enclosing class' fields and methods. Now that it is no longer an inner class, it needs to be passed a reference to the GUI instance so that it can access its methods. Something like this:
public class NupuVajutus implements ActionListener {
private final GUI gui;
public NupuVajutus(GUI gui) {
this.gui = gui;
}
public void actionPerformed(ActionEvent e) {
// The GUI instance can now be accessed through the gui field, for example:
gui.something();
// ...
}
}
And in the GUI() constructor:
NupuVajutus nV = new NupuVajutus(this);
To be honest, though, there is nothing wrong with keeping your ActionListener as an inner class. If you're never going to use that class outside of the GUI class, then it is probably preferable for it to remain as an inner class.
What you are doing it extending the GUI class. This Does Not make then share the Same Fields Say you have a field field in your GUI class
public class GUI {
String field = "Hello";
}
Just because your Listener class extends GUI doesn't mean they will share the exact same field object. I think that's what you think is supposed to occur
public class Listener extends GUI implements ActionListener {
public void actionPerformed(ActionEvent e) {
field = "World";
}
}
The above does nothing the field in GUI. If you were to do this, you would need to access in a static way like line GUI.field = "World";. The above is also what causes in an infinite loop, as you need to instantiate the Listener in the GUI class. This is not really good practice or design.
One option would to use some sort of MVC pattern.
Another option would be to pass the values you need, to a constructor in your Listener class, and instantiate it in your GUI class with those values.
Run this example to see what I'm talking about. I have a MyListener class that I pass a Jlabel to, the same JLabel in the GUI class
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class FieldTest {
private JLabel label = new JLabel(" ");
private JButton button = new JButton("Set Text");
public FieldTest() {
MyListener listener = new MyListener(label);
button.addActionListener(listener);
JFrame frame = new JFrame();
frame.add(label, BorderLayout.CENTER);
frame.add(button, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new FieldTest();
}
});
}
}
class MyListener implements ActionListener {
JLabel label;
public MyListener(JLabel label) {
this.label = label;
}
#Override
public void actionPerformed(ActionEvent arg0) {
label.setText("Hello, FieldTest!");
}
}

Methods in built-in classes

I am kinda new to java. I was reading java codes to learn more about it, and this had me confused. A method would only be performed if only it is called, right? But how about those methods of built-in classes like paint(), paintComponent(), run() in Runnable class, etc. Are these methods performed without explicitly calling them, once a class that implements these methods is used to instantiate an object? Is that really how it works?
Like for example in this code, method paint() was not really called.
import javax.swing.*;
import java.awt.*;
public class FrameExampleTest{
public static void main(String args[]){
FrameExample frame = new FrameExample();
frame.setSize(500,500);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
class FrameExample extends JFrame{
PanelExample panel;
public FrameExample(){
Container c = getContentPane();
panel = new PanelExample();
c.add(panel,BorderLayout.CENTER);
}
}
class PanelExample extends JPanel{
public PanelExample(){
setSize(300,200);
}
public void paint(Graphics g){
g.fillArc(20,20,30,30,0,360);
}
}
You don't call paint or run yourself, but other code in the JVM does call it for you. For instance code inside the Thread class will call your run method. Code inside the event loop will call paint or paintComponent. Over time, you will see that there's nothing magical. Whenever a method is called, some other code calls it.
Yes. The window framework calls paint and paintComponent methods for you. It figures out when the paint/repaint is required (e.g. when window is moved, opened, re-opened, resized, etc). Javadoc to these methods sometimes mentions it isn't advised/not required to call them directly, but is required to implement them to do such and such things.

how to connect multiple classes?

I am newbie in java
package assigment;
import java.awt.*;
import java.sql.*;
import javax.swing.*;
public class view extends JFrame {
public static void main(String[] args) {
new view();
}
public view(){
JFrame f = new JFrame("WELCOME");
f.setSize(400, 300);
f.setVisible(true);
f.setLocationRelativeTo(null);
controller cl = new controller();
JButton btnCompany = new JButton ("COMPANY");
f.add(btnCompany);
f.setLayout(null);
btnCompany.setBounds(50, 50, 100, 50);
btnCompany.addActionListener (cl);
}
}
contoller class
package assigment;
import java.awt.event.*;
public class controller {
public static void actioncompany(ActionEvent a,view view) {
if (a.getSource() == view.btnCompany) {
System.out.print ("test");
}
}
}
Problem:
Cannot use controller class
Cannot access btnCompany in controller class
That code shouldn't even compile since there isn't a field, view.btnCompany. The btnCompany variable is local to the constructor and thus invisible everywhere else. Also, as MadProgrammer notes, your controller class (re-name it Controller) doesn't implement ActionListener and so cannot be used as an ActionListener.
I have other issues with your code:
Don't use null layout and absolute positioning.
Do abide by Java naming rules including starting class and interface names with an upper case letter so that others can more easily understand your code.
Yes, separate out your control from your view.
Most all fields should be private, and so view.BtnCompany shouldn't be visible, even if the field existed.
ActionListeners must implement the ActionListener interface or extend a class that implements the interface such as AbstractAction.

Categories