Frage

I am trying to send two variables from one sketch to another, using the oscP5 library for processing. The message I am sending is created like this:

 OscMessage myMessage = new OscMessage("/test");
 myMessage.add(title);
 myMessage.add("Zeit");
 oscP5.send(myMessage, remoteLocation);

In the second sketch, I receive the data like that:

 void oscEvent(OscMessage theOscMessage) {
   if(theOscMessage.checkAddrPattern("/test")) {
     String title = theOscMessage.get(0).stringValue();
     String layoutType = theOscMessage.get(1).stringValue();

     addToQueue(title, layoutType);
   }
 }

And here my simplified addToQueue function:

 void addToQueue(String title, String layoutType) {
   if(!existsInQueues(title)) {
     upcomingHeadlines.add(new Headline(title, printAxis, scrollSpeed, layoutType));
   } 
 }

Every time I start the sketches, I get the error:

ERROR @ OscP5 ERROR. an error occured while forwarding an OscMessage to a method in your program. please check your code for any possible errors that might occur in the method where incoming OscMessages are parsed e.g. check for casting errors, possible nullpointers, array overflows ... . method in charge : oscEvent java.lang.reflect.InvocationTargetException

I have been able to track the problem down to the layoutType-Variable. If I change

  String layoutType = theOscMessage.get(1).stringValue();

to

  String layoutType = "Zeit";

no error occurs. That is quite confusing, because both versions should have the same result. The error message does not help me in any way.


Edit

I have compared the two possible variables like that:

String layoutType = theOscMessage.get(1).stringValue();
String layoutTypeB = "Zeit";
if(layoutType.equals(layoutTypeB)) println("Same String!");

Since gets printed to the console, both have to be the same … I really do not know where to search for an error anymore.


Edit 2

I have wrapped my second sketch in try {...} catch(Exception ex) {ex.printStackTrace();} like that:

void oscEvent(OscMessage theOscMessage) {
  try {  
    if(theOscMessage.checkAddrPattern("/test")) {
      if(debug && debugFeed) println("Received message from other sketch.");

      String title = theOscMessage.get(0).stringValue();
      String layoutTypeO = (String)theOscMessage.get(1).stringValue();
      String layoutType = "Zeit";
      if(debug && debugTemp) {
        if(layoutType.equals(layoutTypeO)) println("IS DOCH GLEICH!");
      }
      if(debug && debugFeed) println("Parsed Information.");
      if(debug && debugFeed) println("-----");
      addToQueue(title, layoutTypeO);
    }
  } catch(Exception ex) {ex.printStackTrace();}
}

That gives me this error as result:

java.lang.IndexOutOfBoundsException: Index: 0, Size: 0  
    at java.util.ArrayList.rangeCheck(ArrayList.java:635)  
    at java.util.ArrayList.get(ArrayList.java:411)  
    at printer$Headline.useLayout(printer.java:260)  
    at printer$Headline.<init>(printer.java:188)  
    at printer.addToQueue(printer.java:407)  
    at printer.oscEvent(printer.java:395)  
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)  
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)  
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)  
    at java.lang.reflect.Method.invoke(Method.java:606)  
    at oscP5.OscP5.invoke(Unknown Source)  
    at oscP5.OscP5.callMethod(Unknown Source)  
    at oscP5.OscP5.process(Unknown Source)  
    at oscP5.OscNetManager.process(Unknown Source)  
    at netP5.AbstractUdpServer.run(Unknown Source)  
    at java.lang.Thread.run(Thread.java:744)

Edit 4

Constructor for my Headline-Class:

class Headline {

  //Define Variables
  Layout layout;
  String title, lastHeadline;
  float yPos, speed;
  float transparency = 255;
  boolean fullyPrinted = false;
  int boundingBoxHeight;

  // Initialize Class Function
  Headline(String t, float y, float s, String lay) {
    title = t;
    yPos = y;
    speed = s;
    layout = useLayout(lay);
    boundingBoxHeight = calculateTextHeight(title);
  }

You might want to know about useLayout() too, so here it is:

Layout useLayout(String name) {
    ArrayList layoutVariants = new ArrayList<Layout>();
    int existingLayouts = layouts.size();
    Layout chosenLayout;

    for(int i = 0; i < existingLayouts; i++) {
      Layout currentLayout = (Layout)layouts.get(i);
      if(currentLayout.layoutType == name) {
        layoutVariants.add(currentLayout);
      }
    }

    if(layoutVariants != null) {
      int rand = (int)(Math.random() * layoutVariants.size());
      chosenLayout = (Layout)layoutVariants.get(rand);
    } else {
      chosenLayout = (Layout)layouts.get((int)(Math.random() * existingLayouts)); 
    }
  return chosenLayout;
}
War es hilfreich?

Lösung

There are two problems with your code, and both of them are in your useLayout method.

The first problem is that you are not comparing Stringss correctly on this line:

    if(currentLayout.layoutType == name) {

name is a String, and I assume currentLayout.layoutType is too. Two Strings that are equal but not the same will not compare equal under ==. As a result of this, your layoutVariants list will quite probably be empty at the end of the for loop.

This line should read:

    if(currentLayout.layoutType.equals(name)) {

See also this question.

The second problem is that you don't correctly handle the case that the layoutVariants list is empty. The problem is on this line:

    if(layoutVariants != null) {

layoutVariants will never be null, so the else branch of this if statement will never execute. Because layoutVariants.size() will be zero, rand will always be zero. Trying to get the element at index 0 in an empty ArrayList will give you precisely the IndexOutOfBoundsException you are seeing.

I imagine you want the else block to execute if the layout name given isn't recognised, in other words, if the layoutVariants list is empty, rather than null. In that case, change this line to

    if(!layoutVariants.isEmpty()) {

Note the ! (not-operator) before layoutVariants. You want the code under the if statement to run if the layoutVariants element is not empty.

EDIT in response to your comments: a null ArrayList is very much not the same as an empty one. null is a special value meaning that the variable doesn't have an object of a given type.

Let's try a real-world analogy: a shopping bag. If you have an empty bag, or no bag at all, then you have no shopping either way. However, you can put things into an empty bag, and count how many items it contains, for example. If you don't have a bag, then it doesn't make sense to put an item in it, as there's no bag to put the item into. null represents the case where you don't have a bag.

Similarly, a String is a collection of characters, and the collection of characters can exist even if it doesn't contain any characters.

isEmpty() can be used for any collection, and, if you're using Java 6 or later, Strings as well. Off the top of my head I can't name any other classes that have an isEmpty method. You'll just have to consult the documentation for these classes to find out.

I've not worked with Processing much, but I am aware that Processing is built on Java, so I would expect any standard Java method to work. Also, I wouldn't worry about 'clearing' a variable: the JVM is generally very good at clearing up after you. There's certainly nothing I can see wrong with your code in this respect.

EDIT 2 in response to your further comment: ArrayList arr; declares a variable of type ArrayList. However, the variable arr is uninitialized: it does not have a value (not even null) and it is an error to try to read the value of this variable before you have assigned a value to it:

ArrayList arr;
System.out.println(arr);     // compiler error: arr might not have been initialised.

Assign null and the code then compiles:

ArrayList arr = null;
System.out.println(arr);     // prints 'null'.

It's not often you need to declare a variable and not give it a name, but one common case is where you want to assign different values to the same variable on both sides of an if statement. The following code doesn't compile:

int y = getMeSomeInteger();   // assume this function exists
if (y == 4) {
    int x = 2;
} else {
    int x = 5;
}
System.out.println(x);        // compiler error: cannot find symbol x

The reason it doesn't compile is that each variable x is only available within the braces { and } that contain it. At the bottom, neither variable x is available and so you get a compiler error.

We need to declare x further up. We could instead write the following;

int y = getMeSomeInteger();   // assume this function exists
int x = 0;
if (y == 4) {
    x = 2;
} else {
    x = 5;
}
System.out.println(x);

This code compiles and runs, but the value 0 initially assigned to x is never used. There isn't a lot of point in doing this, and we can get rid of this unused value by declaring the variable but not immediately giving it a value.

int y = getMeSomeInteger();   // assume this function exists
int x;
if (y == 4) {
    x = 2;
} else {
    x = 5;
}
System.out.println(x);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top