Java callback (in another class) to populate private member - java

Please forgive my Java syntax as I am a Java beginner.
I have 3 classes Main, Tool, ToolResultCallback.
class Main {
private DataList dl;
public doSomething() {
Tool t = new Tool();
ToolResultCallback TRC = new ToolResultCallback();
t.startSomething(TRC);
}
}
// in separate file
class Tool {
public void startSomething(ToolResultCallback TRC) {
}
}
// in separate file
class ToolResultCallback extends AbstractTRC {
#Override
public onEvent(SomeData d) {
// how to populate DataList of Main?
}
}
How do I populate DataList dl from callback function in another class/ file?

Pass dl to the ToolResultCallback constructor, and store it in a field.
Thanks #tgdavies

Related

Efficient Way to Pass an Object Parameter in Java Method

I'm just looking some another efficient way to pass an object parameter to method.
So I have some method like this:
private void dashboardMenu() {
Dashboard dashboard = new Dashboard();
body.removeAll();
body.add(dashboard);
dashboard.setSize(body.getWidth(), body.getHeight());
dashboard.setVisible(true);
}
private void dataMenu() {
Data data = new Data();
body.removeAll();
body.add(data);
data.setSize(body.getWidth(), body.getHeight());
data.setVisible(true);
}
And I want an efficient method to call between this two method with object parameter (dashboard = new Dashboard(), and data = new Data()).
What I think it should be like this for example:
private void dasboardMenu() {
navigateMenu(Type object);
}
private void dataMenu() {
navigateMenu(Type object);
}
private void navigateMenu(Type object) {
object menu = new object();
body.removeAll();
body.add(menu);
menu.setSize(body.getWidth(), body.getHeight());
menu.setVisible(true);
}
Is it possible to do that?
Please give me an example. I don't even know what keyword should I do.
How about this (assuming your Dashboard and Data are Swing Components)?
private void dashboardMenu() {
navigateMenu(new Dashboard());
}
private void dataMenu() {
navigateMenu(new Data());
}
private void navigateMenu(JComponent c) {
body.removeAll();
body.add(c);
c.setSize(body.getWidth(), body.getHeight());
c.setVisible(true);
}

Null pointer exception from List in constructor parameter

I'm creating a class that has a List of objects as a constructor parameter, but I'll getting a null pointer exception when I try to use the initialized List. My class
public class ControlUnit {
private List<Sensor> sensors;
public void constructor(List<Sensor> sensorList) {
sensors = sensorList;
}
public void pollSensors() {
for (Sensor sensor : sensors) {
System.out.println("do something");
}
}
}
used like this:
List<Sensor> sensors = new ArrayList<Sensor>();
sensors.add(new FireSensor());
sensors.add(new SmokeSensor());
ControlUnit unit = new ControlUnit();
unit.pollSensors();
and I'm getting the error
java.lang.NullPointerException
at ControlUnit.pollSensors(ControlUnit.java:15)
What am I missing in my constructor?
The constructor is defined completely wrong. Check the following code snippet.
public class ControlUnit {
private List<Sensor> sensors;
public ControlUnit(List<Sensor> sensorList) {
sensors = sensorList;
}
public void pollSensors() {
for (Sensor sensor : sensors) {
System.out.println("do something");
}
}
}
And use it like this.
List<Sensor> sensors = new ArrayList<Sensor>();
sensors.add(new FireSensor());
sensors.add(new SmokeSensor());
ControlUnit unit = new ControlUnit(sensors);
unit.pollSensors();
public void constructor(List<Sensor> sensorList) {
This is not a constructor declaration. You need
public ControlUnit(List<Sensor> sensorList) {
and then call it with the list you want to use.
You're constructing your class wrongly.
A constructor in Java takes the form of a method with the name of the class and without any return type:
public ControlUnit(List<Sensor> sensorList) { ... }
You need to pass the list to the object when creating an instance of it as a parameter so like this: ControlUnit unit = new ControlUnit(sensors); and also change the constructor method to
public ControlUnit(List<Sensor> sensorList) {
sensors = sensorList;
}
For your class ControlUnit you have not got a constructor, so the Idea which you use will generate an empty constructor for your class that you call when you initialize your ControlUnit object here: ControlUnit unit = new ControlUnit()
So you will not initialize your List<Sensor> sensors list and you will not be able to iterate through it because it is pointing to null.
In order to do it properly, you have to write your constructor in the right way like this:
public class ControlUnit {
private List<Sensor> sensors;
public void pollSensors() {
for (Sensor sensor : sensors) {
System.out.println("do something");
}
}
public void ControlUnit (List<Sensor> sensorList) {
sensors = sensorList;
}
}
Your constructor method has to be the same name as your class.
When you call new ControlUnit(), you will call that constructor. But in this case, you have a parameter there, so we have to pass it at the calling like this: ControlUnit unit = new ControlUnit(sensors);
So when the constructor will run, it will assign the value to your list, so you can iterate through it.

Access arraylist from another class

I am a newbie to Java and I have a gui class which has a GUI component and it takes the input from the text field and should pass it to another class. The action listener of the button is below.
public void actionPerformed(ActionEvent action) {
arraylist.add(textField_1.getText());
arraylist.add(textField_2.getText());
arraylist.add(textField_3.getText());
arraylist.add(textField_4.getText());
}
since it is a void method I cannot return the array list so that Ii cannot construct a getter.
public ArrayList<String> getList(){
return this.arraylist;
}
Could anyone please tell me how to access this arraylist from the another class without passing it through the constructor? I am sorry if i asked anything wrong. Thanks in advance.
This is one of the many possible approaches.
Just define another class and call the setter from your actionPerformed(..) method.
public class YourOtherClass {
private static ArrayList<String> arraylist;
public void setList(arrayList) {
this.arraylist = arraylist;
}
public ArrayList<String> getList() {
return this.arraylist;
}
}
Now you can simply set this arraylist as:
public void actionPerformed(ActionEvent action) {
arraylist.add(textField_1.getText());
arraylist.add(textField_2.getText());
arraylist.add(textField_3.getText());
arraylist.add(textField_4.getText());
YourOtherClass.setList(arraylist);
}
Now when you want to access the contents of this list, simply use:
...
//any other method
ArrayList<String> arraylist = YourOtherClass.getList();
System.out.println(arraylist.get(0)); //or whatever
...
You can make that arraylist as Static and access it.
To access that particular arraylist use the below syntax
classNameThatContainArraylist.yourArrayList
be careful while using static.
If you want to use to set and get data then there are many approaches and two of them are follow
public class SetDataInArrayList {
//Aproach one by using object
private List<ActionEvent> list;
public SetDataInArrayList() {
list = new ArrayList();
}
public void setDataInList(ActionEvent e) {
list.add(e);
}
public List<ActionEvent> getList() {
return list;
}
//Approach two by using static reference
private static List<ActionEvent> newList;
static {
newList = new ArrayList<>();
}
public static void add(ActionEvent e) {
newList.add(e);
}
public static List<ActionEvent> returnList() {
return newList;
}
if you use either of approach you will need reference variable in both of cases to fetch data
If I understood, you want to do it:
public class A {
private ArrayList<String> arrayList;
public ArrayList<String> getArrayList() {
return this.arrayList;
}
}
public class B {
private A a = new A();
public void actionPerformed(ActionEvent action) {
a.getArrayList().add(textField_1.getText());
a.getArrayList().add(textField_2.getText());
a.getArrayList().add(textField_3.getText());
a.getArrayList().add(textField_4.getText());
}
}

Intellij IDEA plugin - PersistentStateComponent loadState not called

I am trying to develop a plugin for Intellij IDEA, I am working with SDK 129.451.
The issue I have is that I can't persist the user data like some list items he can input in the plugin and have the data back after the IDE restarts..
I am using PersistentStateComponent to persist the data, the getState() method seems to be called but the loadState() method doesn't.
Here is a sample class that extends PersistentStateComponent:
#State(name = "Test", storages = {#Storage(file = StoragePathMacros.APP_CONFIG+"/other.xml"
)})
public class Test implements PersistentStateComponent<Element> {
String ceva;
public Test() {
ceva = "sad";
System.out.println("constr");
}
public String getCeva() {
return ceva;
}
public void setCeva(String ceva) {
this.ceva = ceva;
}
public void loadState(Element state) {
System.out.println("cstate load");
ceva = (String) state.getContent().get(0);
}
public Element getState() {
System.out.println("cstate retu");
Element configurationsElement = new Element("testtt");
configurationsElement.addContent(ceva);
return configurationsElement;
}
}
Also I added this class in plugin.xml here:
<extensions defaultExtensionNs="com.intellij">
<applicationService serviceImplementation="ro.catalin.prata.testflightuploader.controller.Test"/>
<!-- Add your extensions here -->
<toolWindow id="TF Uploader" secondary="true" icon="/general/add.png" anchor="right"
factoryClass="ro.catalin.prata.testflightuploader.view.TFUploader">
</toolWindow>
</extensions>
And I also have a tool window class:
public class TFUploader implements ToolWindowFactory {
private JButton buttonAction;
private ToolWindow myToolWindow;
final Test test = ServiceManager.getService(Test.class);
public TFUploader() {
// I assume it should print the saved string but it doesn't
System.out.println(test.getCeva());
buttonAction.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// if I click a button I am setting some new value to the string I want to save
test.setCeva(test.getCeva() + "-dddddd+");
}
});
}
Ok so, if I close the app or minimize it, the getState method gets called as I expected.. but when I open the app, the loadState method doesn't get called.. can somebody help me how I can solve this?
I already read this but it doesn't seem to help me to much. Also I want to use PersistentStateComponent as I want to save objects more complex than a simple String.
Thank you in advance!
Ok, I made it! :)
I don't know exactly what the issue was but I changed the Test class to this:
#State(
name = "Test", storages = {
#Storage(
id = "other",
file = "$APP_CONFIG$/testpersist.xml")
})
public class Test implements PersistentStateComponent<Test> {
String ceva;
public Test() {
ceva = "sad";
System.out.println("constr");
}
public String getCeva() {
return ceva;
}
public void setCeva(String ceva) {
this.ceva = ceva;
}
public void loadState(Test state) {
System.out.println("cstate load");
XmlSerializerUtil.copyBean(state, this);
}
public Test getState() {
System.out.println("cstate retu");
return this;
}
}
And in the TFUploader I changed the way I loaded the Test class to this:
final Test test = ServiceManager.getService(Test.class);
I hope it helps others..
I have already commented here but will say again that in my case loadState(MyService state) wasn't called because of lack of getter and setter for stateValue from this example:
class MyService implements PersistentStateComponent<MyService> {
public String stateValue;
public MyService getState() {
return this;
}
public void loadState(MyService state) {
XmlSerializerUtil.copyBean(state, this);
}
}
In my case I was getting a NullPointerException even before loadState was getting called. Similar to your code above I used an Element class as the state class. I had a constructor with some parameters in Element class. This was the problem as the framework could not create an instance of my state class. I tried to add a blank constructor without any parameters. This worked.

Using Reflection to Build a Text Based Menu

I'm using a modified version of JosAH's text-based menu system and am trying to figure out how to use reflection to create a list of items from a class' declared subclasses. Because different menu items use different parameters in order to manipulate the underlying data, I'm having a problem generalizing their instantiation.
For example, the assignment was to create a custom linked list, so the menu options would consist of Print, Insert, Save, Quit etc. Printing and insertion just require a reference to the linked list in order to parse the input and call the appropriate functions in the linked list. Save additionally requires the file to save to while Quit doesn't require any additional arguments.
public class MenuList extends TextMenu { //TextMenu extends MenuItem
List<MenuItem> items;
public MenuList (Object data, File file) {} //calls fillList
//calls createList which fills a List<MenuItem> and copies it to this.items
protected void fillList(Object data, File file) {
this.items.addAll( createList(this.getClass(), ... args?) );
}
private static class MenuQuit extends MenuItem {
public MenuQuit() {} //does not need data
}
private static class MenuOne extends MenuItem {
public MenuOne(Object data) {} //manipulates data
}
private static class MenuTwo extends MenuItem {
public MenuOne(Object data) {} //also manipulates data
}
private static class MenuThree extends MenuItem {
//manipulates data and saves to file
public MenuThree(Object data, File file) {}
}
private static class NestedMenu extends MenuList {
//needs parameters to pass to it's own menuItems
public NestedMenu(Object data, File file) {}
}
}
public static List<MenuItem> createList(Class cls, ...args? ) {
List<MenuItem> items = new ArrayList<MenuItem>();
try {
Classes<?>[] param = { parse(args)? };
Class<?>[] menuList = cls.getDeclaredClasses();
for(Class<?> c : menuList) {
if(MenuItem.class.isAssignableFrom(c)) {//only adding the MenuItems
Constructor<?> ct = c.getConstructor(param);
Object menuItem = ct.newInstance( ...args? );
items.add( (MenuItem) menuItem );
}
}
} catch (Exception e) { }
}
Is there any way to generalize createList so that the menu items are created with the necessary parameters?
Also, because of how long I've been working on this, I'm completely open to the possibility that this is a completely overengineered solution and that I should scrap large parts, or perhaps the entirety, of this idea.
Edit: I don't know if this is best place to add this piece information-
This was a solution I had been thinking about, and after reading through some responses and comments, it might be the correct one. If MenuItem always accepts a single Object as a parameter, I can make that assumption when calling getConstructor and newInstance. Afterwards, I'll just leave it up the specific class to cast Object into something useful that they can pull their on data from.
public class MenuItem {
Object data;
public MenuItem(Object data) {
this.data = data;
parseData();
}
protected abstract void parseData();
}
private static class MenuQuit extends MenuItem {
public MenuQuit(Object data) { super(data) } //nothing additional needed
protected void parseData() {} //does nothing
}
private static class MenuSave extends MenuItem { //as outlined above
private CustomLinkedList list;
private File saveFile;
public MenuSave(Object data) {
super(data);
}
//may be able to use reflection to generalize this
protected void parseData() {
this.list = ((MyCustomData) data).list;
this.saveFile = ((MyCustomData) data).saveFile;
}
}
public class MyCustomData {
public CustomLinkedList list;
public File saveFile;
public int otherData;
public MyCustomData(CustomLinkedList a, File b, int c) {} //assignment
}
I was trying to avoid this method because it starts adding complexity to the subclassed MenuItems, which I was hoping to keep as simple as possible. Is there a way to improve this solution?
Not exactly an answer,
but since I'm generally not a big fan of reflection here is another idea:
You could add data and file to your base class MenuItem and leave them null where they are not applicable.
Hmmm. What would happen if you had arguments in the cases that don't need data and just ignore them?

Categories