Access a public non-static object from another separate class [closed] - java

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I am trying to create my own Font Chooser class in another separate class from the file where I have my main class (a JFrame application), and I would like to access to the textArea object of the main JFrame, in order to modify its font properties, but I am not able to do it, because the textArea is a non-static object.
To solve this problem, I have thought to make the separate class ("Font Chooser") an inner class. In this the only solution?
EDIT
The Font Chooser object is instantiated after the creation of the main Frame, in fact the instantiation is done by the main JFrame class, and apparently I cannot access to the main JFrame public members.
Thanks.

My main recommendation: don't ignore OOP practices to solve your problem, such as by using public fields and such. Don't have another class directly manipulate the state of your JTextArea which should be private anyway. Instead, give the class that holds the JTextArea a public setFont method that other classes can call on valid instances of the containing class.
public class MyGui {
private JTextArea textarea = .....;
public void setTextAreaFont(Font font) {
textarea.setFont(font);
}
So for an object to call this method, all it needs is a valid reference to the MyGui class, with valid being the key term here. This may require that you pass the reference into the object that needs it by a setter method or a constructor parameter. There is no need to use an inner class here, none at all.
And of course, the JTextArea field should never be static as that would throw all OOP to the wind, making it very difficult maintaining, enhancing or testing your code.
Edit
You now state:
The "Font Chooser" object is instantiated after the creation of the main Frame, in fact the instantiation is done by the main JFrame class, and apparently I cannot access to the main JFrame public members.
Then what is stopping you from passing the GUI class into your font chooser on its creation?
MyFontChooser myFontChooser = new MyFontChooser(this); // ???
Again, please tell the details of your problem.
class MyFontChooser {
private MyGui myGui;
public MyFontChooser(MyGui myGui) {
this.myGui = myGui;
}
// some event caused method
public void changeFont() {
myGui.setTextAreaFont(someFont);
}

What you need is to have a reference to the JFrame you want to modify. I'm assuming your code looks something like this:
class MyFrame extends JFrame{
public JTextArea textArea = new JTextArea();
public MyFrame(){
super();
FontChooser fc = new FontChooser();
fc.applyFont();
}
}
class FontChooser{
public void applyFont(){
Font f;
//code to set font values
MyFrame.textArea.setFont(f);//Won't work, because textArea isn't static
}
}
What you need is something like this
class MyFrame extends JFrame{
public JTextArea textArea = new JTextArea();
public MyFrame(){
super();
fc.applyFont(textArea)
}
}
class FontChooser{
public void applyFont(JTextArea textArea){//Notice the added parameter
Font f;
//code to set font values
textArea.setFont(f);//Will work, because we have an instance of the object we want to modify.
}
}
Obviously this needs to be modified for your code, but that's the idea. You need to pass a reference to the Object you want to modify.

Related

Cannot change public variable type in a subclass

I need to make a subclass changing variable type.
My purpuse is to create a class that dynamically loads objects onto a form. This form can be a JFrame or JInternalFrame, so I want a class leading a property form that can be one of JFrame / JInternalFrame, so I can write methods and functions without duplicate code.
Something like
public class form {
public javax.swing.JFrame frm;
...... methods and functions.
public void init(String title)
{
frm = new JFrame(title);
}
}
and
class form_children extends form {
public javax.swing.JInternalFrame frm;
public void init(String title)
{
frm = new JInternalFrame(title);
}
}
so that when I use them I can do something like this
public form_to_create (String title, Boolean mdi_child)
{
if (mdi_child)
frm = new form_children();
else
frm = new form();
frm.init();
frm.dosomething -----> error for null object
}
but when I use an mdi_child, it gives me error for null object.
It seems that frm variable for super class is present, but frm for subclass is not.
Why?
I need to make a subclass changing variable type.
My purpose is create a class that dynamically loads objects onto a form. This form can be a JFrame or JInternalFrame, so I want a class leading a property Form that can be one of JFrame / JInternalFrame, so I can write methods and functions without duplicate code.
You are painting yourself in a corner by having your class extend JFrame, JInternalFrame or other top-level (or internal top-level) window, as this forces you to create and display these types of windws, when often more flexibility is called for. In fact, I would venture that most of the Swing GUI code that I've created and that I've seen does not extend JFrame, and in fact it is rare that you'll ever want to do this. More commonly your GUI classes will be geared towards creating JPanels, which can then be placed into JFrames, JInternalFrames or JDialogs, or JTabbedPanes, or swapped via CardLayouts, wherever needed. This will greatly increase the flexibility of your GUI coding.
Your child object has two "frm" properties. The JInternalFrame frm you added in its own definition and the Frame frm it inherited from its father.
Because of polymorphism in form_to_create you are accessing the frm from the superclass, which is not initialized, instead of the JInternalFrame one.
A solution would be to encapsulate the behaviour in methods.
public class Form {
JFrame frm;
public void init(String title){
frm = new JFrame(title);
}
public void doSomething(){
frm.doSomething();
}
}
public class Form_child{
JInternalFrame frm;
public void init(String title){
frm = new JInternalFrame(title);
}
public void doSomething(){
frm.doSomething();
}
}
And your form_to_create would look like this now:
public static void form_to_create(String title, Boolean mdi_child){
Form frm;
if (mdi_child) {
frm = new Form_child();
}else{
frm = new Form();
}
frm.init(title);
frm.doSomething();
}
By doing it this way, you are only exposing the behaviour through the doSomething() method, and the rest of the program doesn't care if a JFrame or a JInternalFrame is the one behind.
Even better, make an Interface that defines the common behaviour and have both form classes implement it. That way Form_child doesn't inherit a JFrame property it doesn't use.
Thanks.
I want to dynamically create my form, and view that as mdichild window or not child window.
Read an file from disk, analyze it and add panels, controls to my form, so decide if my form has to be a child in a jDesktopPanel as JInternalFrame or simply a JFrame without dependencies.
I thought Java was powerful... but I guess it is not possible.

Java: Cannot be Referenced From a Static Context

I'm trying to make a frame with a panel consisting of two buttons which reside at the bottom of the frame.
public class ControlledBall extends JPanel {
public static void main(String[] args) {
JFrame Frame = new Viewer();
Frame.setSize(1000, 500);
Frame.setTitle("Bouncing Ball");
Frame.setDefaultCloseOperation((JFrame.EXIT_ON_CLOSE));
Frame.setVisible(true);
}
public class Viewer extends JFrame {
JButton buttonGo = new JButton("GO");
JButton buttonStop = new JButton("STOP");
JPanel aPanel = new JPanel();
public Viewer() {
aPanel.add(buttonGo);
aPanel.add(buttonStop);
this.add(aPanel, BorderLayout.SOUTH);
}
}
}
The problem here is this:
JFrame Frame = new Viewer();
It is telling me
ControlledBall.this cannot be referenced from a static context
How do I fix it?
You could do something like:
JFrame Frame = new ControlledBall().new Viewer();
instead of:
JFrame Frame = new Viewer();
But I'm not sure this is really what you want since ControlledBall is a JPanel...
Instances of non static inner classes hold a pointer to their enclosing object to be able to reference its members. See for example Java inner class and static nested class One side effect is that they cannot be instatiated from static methods, which have no relation to an actual instance of the enclosing class except by instatiating an intermediate object of your ControlledBall class.
PS: Another side effect to keep in mind (not so relevant for your use case) of this implicit this pointer is that it may cause resource leaks because it keeps the outer instance alive as long as the inner one lives.
You've created an public inner class inside the ControlledBall class, which is why you can't access it, as you don't have an instance of the ControlledBall class.
Guessing from the indentation and your code though, what you probably meant to do was create two seperate classes and instantiate the Viewer class from the main method of ControlledBall. To do that, move the Viewer class to its own file named Viewer.java and it should work.
The "main" method is static and when executed, its "containing" class might not yet been instantiated and so class Viewer might not yet exist. Since this example is apparently the program's entry point, "Viewer" most certainly does not yet exist.
There are many ways to resolve this, such as creating an instance of ControlledBall and then use that instance to create "Viewer".
It is my personal style to "get out of static" ASAP in a Java program by instantiating an instance of "main"s container and then running from there. I was taught that "main" is static so it exists to be called by the parent system and not much more use than that, I'm sure there are other opinions. Here is a brief example, which lacks many details:
public static void main(String[] args) {
// Pass 'args' to which ever method you prefer
ControlledBall app = new ControlledBall(args);
app.run(args);
}
private void run(String[] args) {
JFrame Frame = new Viewer();
}
I use 'run' because of Thread. I know many darts can be thrown at this, its just an example.
Make the inner class (Viewer) static
public static class Viewer extends JFrame
you can not acces non-static things from static methods

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!");
}
}

No enclosing instance of type mainframeclass is accessible [duplicate]

This question already has answers here:
What causes error "No enclosing instance of type Foo is accessible" and how do I fix it?
(11 answers)
Closed 6 years ago.
I get the error No enclosing instance of type mainframeclass is accessible when I try to compile/launch my program in Eclipse. Here is the code:
public class mainframeclass {
public static Object mainframemenuitem1;
public static void main(String[] args) {
JFrame mainframe = new JFrame(variables.mainframename);
mainframe.setLayout(new GridLayout());
mainframe.setSize(variables.mainframewith, variables.mainframeheight);
mainframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainframe.setVisible(variables.mainframevisible);
mainframe.setResizable(variables.mainframeresizable);
JMenuBar mainframemenubar = new JMenuBar();
JMenu mainframemenu = new JMenu("File");
JMenuItem mainframemenuitem1 = new JMenuItem("Exit");
mainframe.setJMenuBar(mainframemenubar);
mainframemenubar.add(mainframemenu);
mainframemenu.add(mainframemenuitem1);
actionlistener listen = new actionlistener();
mainframemenuitem1.addActionListener(listen);
runningclass.running();
}
public class actionlistener implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == mainframemenuitem1)
System.out.println("Test");
}
}
}
It seems that I have done something wrong with the:
actionlistener listen = new actionlistener();
but I don't know what. I am new to Java and would appreciate any insight into this problem. Thanks.
Your actionlistener class (which should be renamed to follow Java naming conventions and with a more meaningful name) is an inner class (as opposed to a static nested class), which means it's only valid with an enclosing instance of mainframeclass to refer to... which it doesn't actually need, given that it refers to mainframemenuitem1 which is static anyway.
So you can just change it to:
public static class actionlistener implements ActionListener
and it should work. Well, it will compile, anyway. It won't actually do what you want because you've got two mainframemenuitem1 variables - the static one, and then a local one within your main method, so the static one never gets assigned a non-null value.
I would either pass mainframemenuitem1 into the constructor of actionlistener and still make it a static nested class, or just make mainframemenuitem1 final within the main method and create an anonymous inner class for the action listener.
Having said that:
i am kinda new to java
In that case, I would actually stop with GUIs entirely for the moment. It's much simpler to learn about a new language without the complications introduced by GUIs. Writing console applications allows you to concentrate on learning just one thing at a time.

Making objects for each button

I need to make objects for my buttons in my typing tutor.
I have made a class:
public class KeyLabel extends JLabel {
public KeyLabel(String name) {
setText(name);
}
this is my subclass
my superclass is the keyboard class
and I need to make objects for each button on my keyboard for my typing tutor, so the a is a label its the keyboard
but I don't know how to do this?
I don't know why are you extending JLabel if you are to create Buttons. Extending JLabel will create a JLabel which will be wasted as in your code. More relavent code would be like
public class KeyLabel {
public KeyLabel(String name) {
JButton buttonOK = new JButton("OK"); //creates OK button
}
}
Moreover, i think you should look here, for details.
In most cases, you'll want to use inheritance (i.e. subclass JButton). For instance,
public abstract JKeyboardButton extends JButton{
public JKeyboardButton(final String key){
super(key);
// include other stuff, if necessary
}
// include other methods common to all JKeyboardButton instances
}
And then for each concrete button, you'll want to subclass JKeyboardButton, like so
public final class JKeyboardAButton extends JKeyboardButton{
public JKeyboardAButton(){
super("a");
}
// override/implement other methods..
}
And then in order to obtain a keyboard key of, let's say a, all you have to do is create an instance of JKeyboardAButton, like so
final JKeyboardButton aButton = new JKeyboardAButton();
And then obviously you'll have to create a class for each key and throw all these instances into a Keyboard class. But I'll leave the "heavier" coding to you.
Also, please note that the final modifier is not required, but rather is a personal preference of mine (i.e. to prevent subclassing and to ensure that a variable (even local ones) are only assigned once).

Categories