I am trying to create a XSSFConditionalFormattingRule with a 3-scale coloring. Therefore I need to set the thresholds as well. Yet upon debugging I found that each XSSFConditionalFormattingThreshold throws an com.sun.jdi.InvocationException occurred invoking method. on their CTCfvo property, but only after calling rule.getColorScaleFormatting().setNumControlPoints(3);
My complete code is this:
CellRangeAddress[] regions = { CellRangeAddress.valueOf("Z2:Z" + (sheet.getLastRowNum() + 1)) };
XSSFConditionalFormattingRule rule = sheet.getSheetConditionalFormatting()
.createConditionalFormattingColorScaleRule();
XSSFConditionalFormattingThreshold thresh5 = rule.getColorScaleFormatting().createThreshold();
thresh5.setRangeType(RangeType.NUMBER);
thresh5.setValue(0.05);
XSSFConditionalFormattingThreshold thresh10 = rule.getColorScaleFormatting().createThreshold();
thresh10.setRangeType(RangeType.NUMBER);
thresh10.setValue(0.10);
XSSFConditionalFormattingThreshold thresh15 = rule.getColorScaleFormatting().createThreshold();
thresh15.setRangeType(RangeType.NUMBER);
thresh15.setValue(0.15);
rule.getColorScaleFormatting().setNumControlPoints(3);
rule.getColorScaleFormatting()
.setThresholds(new ConditionalFormattingThreshold[] { thresh5, thresh10, thresh15 });
XSSFColor colorGreen = new XSSFColor(IndexedColors.GREEN, colorMap);
XSSFColor colorYellow = new XSSFColor(IndexedColors.YELLOW, colorMap);
XSSFColor colorRed = new XSSFColor(IndexedColors.RED, colorMap);
rule.getColorScaleFormatting().setColors(new Color[] { colorGreen, colorYellow, colorRed });
sheet.getSheetConditionalFormatting().addConditionalFormatting(regions, rule);
And this the shortened stacktrace I get when execting the code above:
org.apache.xmlbeans.impl.values.XmlValueDisconnectedException at
org.apache.xmlbeans.impl.values.XmlObjectBase.check_orphaned(XmlObjectBase.java:1258)
at
org.apache.xmlbeans.impl.values.XmlObjectBase.newCursor(XmlObjectBase.java:286)
at
org.apache.xmlbeans.impl.values.XmlComplexContentImpl.arraySetterHelper(XmlComplexContentImpl.java:1124)
at
org.openxmlformats.schemas.spreadsheetml.x2006.main.impl.CTColorScaleImpl.setCfvoArray(Unknown
Source) at
org.apache.poi.xssf.usermodel.XSSFColorScaleFormatting.setThresholds(XSSFColorScaleFormatting.java:85)
What causes the error I am seeing here? Is it a mistake when I create the XSSFConditionalFormattingThreshold? Or something entirely else?
I am using apache poi v4.0.0.
As stated in the question, the only occurences of this error was attributed to writing the workbook twice (SO question, bugzilla). So that got me wondering what I am doing wrong. I had no real idea where to start, as everything associated with the error has nothing to do with my problem.
My first look went to the documentation of void org.apache.poi.xssf.usermodel.XSSFColorScaleFormatting.setNumControlPoints(int num), which states the following:
Sets the number of control points to use to map the colours. Should
normally be 2 or 3.
After updating, you need to ensure that the Threshold count and Color
count match
The second part caught my eye. I thought something along the lines:
I create the thresholds directly on the ColorScaleFormatting with getColorScaleFormatting().createThreshold(). So what if setNumControlPoints() actually resets all the thresholds which have been previously created?
And that was the point where I simply moved rule.getColorScaleFormatting().setNumControlPoints(3); in before the creation of all the XSSFConditionalFormattingThreshold and there it was, my code working just fine.
Having a look at the setNumControlPoints method we can see this:
public void setNumControlPoints(int num) {
while (num < _scale.sizeOfCfvoArray()) {
_scale.removeCfvo(_scale.sizeOfCfvoArray()-1);
_scale.removeColor(_scale.sizeOfColorArray()-1);
}
while (num > _scale.sizeOfCfvoArray()) {
_scale.addNewCfvo();
_scale.addNewColor();
}
}
This clearly suggests that some things might get removed when calling this method, though I couldn't quite get what the initial size of _scale.sizeOfCfvoArray() is (I'd assume 0). And because of that I couldn't quite see how stuff gets removed, because I created 3 thresholds (_scale.sizeOfCfvoArray() should be 3) and then I call setNumControlPoints(3), so we would have num == _scale.sizeOfCfvoArray() and I couldn't find anything for what happens in that case (looks like complete removal of everything though).
To conclude, setNumControlPoints(int num) should always be called as first thing after creating the rule and before creating any thresholds.
If anyone can point out why everything gets reset if num == _scale.sizeOfCfvoArray(), feel free to comment or edit.
Related
I'm trying to use JFugue 5.0.9 in my Java project to create *.midi files with it. While implementing JFugue's midi capabilities into my project that uses frequencies of a 24 tune makam piano, I realized it has some tune issues.
For example this code:
ChordProgression cp = new ChordProgression("I-III-IV-iv").setKey("E");
System.out.println(cp);
Player player = new Player();
player.play(cp);
should print
E4MAJ G#4MAJ A4MAJ A4MIN
on console as it's said here.
But prints
E4MAJ E4MAJ E4MAJ A4MIN
in my project. Yes, first three chords are same for some reason. They sound same also, of course.
Also, while using microtones like "m390", it doesn't sound exactly in that frequency.
In another file, in the main method I wrote this:
Player player = new Player();
player.play("A4 m440 m400 m390 m380 m370 m360");
I know that A4 and m440 are the same but as it's said here, A5 and m440 should sound same. But in my project A4 and m440 sound same but it's not exactly 440Hz. When I realized something goes wrong, I decided to use a tuning app and here are the frequencies it calculated respectively:
221.5 221.5 197.5 186.6 186.6 186.6 176.2
As you can see, it plays something very near A3 instead of a clear A4. But this is not all. It also sounds exactly same for m390, m380 and m370.
What exactly is wrong here? Any help would be appreciated.
A little note: I'm pretty sure it has nothing to do with my project. I tryed running the codes above in a brand new project, the same problems occured. And there's no problem with my system because my main project and any other softwares like SunVox, they all sound very good actually.
OK, I had a look at the source codes of JFugue 5.0.9 and here is what I got in ChordProgression.java:
/**
* Only converts Roman numerals I through VII, because that's all we need in music theory...
* VIII would be the octave and equal I!
*/
private int romanNumeralToIndex(String romanNumeral) {
String s = romanNumeral.toLowerCase();
if (s.startsWith("vii")) { return 6; }
else if (s.startsWith("vi")) { return 5; }
else if (s.startsWith("v")) { return 4; }
else if (s.startsWith("iv")) { return 3; }
else if (s.startsWith("iii")) { return 2; }
else if (s.startsWith("ii")) { return 1; }
else if (s.startsWith("i")) { return 0; }
else { return 0; }
}
A little laziness... :D One of the problems lies right here. If you use toLowerCase() method without specifying a locale, it causes some problems in runtime. In Turkish alphabet which I'm using right now lower case of I is "ı", not "i". So, the program converts my chords from "I-II-III" to "i-i-i" because as you can see there is no if statement for lower case I of Turkish alphabet (ı) and this leads it to return 0 as in the case of "i".
To solve this issue, we have to either delete lower case conversion and write all if statements for also upper case I's or set default locale to "en" to make sure it converts (upper case)I's to (lower case)i's. So, this should be used in the source:
Locale.setDefault(new Locale("en"));
Fortunately, JFugue is an open source software published under Apache 2.0.
This still doesn't explain why tunes sound wrong but now at least we know that these are totally different problems. Or maybe it seems so... I don't know. I will edit this answer if I ever find out an explanation or a solution for the rest.
Edit
Finally I figured out the problem with microtones by accident. I decided to look at microtone calculation functions in the source one more time.
In MicrotonePreprocessor class (which is in org.staccato package) there is a function named convertFrequencyToStaccato(). What this function does is convert frequency to midi note number and pitch bend value. At the 107th line, that code rounds semitone, octave and pitch values if calculated pitch value is very close to the next note:
// If we're close enough to the next note, just use the next note.
if (pitches >= 16380)
{
pitches = 0;
semitone += 1;
if (semitone == 12)
{
octave += 1;
semitone = 0;
}
}
The line where pitch is reset should be changed as:
pitches = 8192;
Because, you know, neutral pitch value is 8192. 0 (zero) is minimum pitch value and 16384 is maximum pitch value. At first, I thought the same way as the developer: "After 16384, it should be 0. That is okay. No problem here.". Then I said "What if I change pitch-reset value from 0 to 8192?". It worked. This was a beautiful perception error we both had. :D I'm really having a lot of laugh now.
This fixes the microtone issue. I can hear perfect intervals now! I feel happy and satisfied.
Edit2
I just wanted to share my further changes which results in better microtonal tunning:
if (pitches >= 12288)
{
int diff = 16384-pitches;
int applieddiff = 8192-diff;
pitches = applieddiff;
semitone += 1;
if (semitone == 12)
{
octave += 1;
semitone = 0;
}
}
This also helps use semitone (black) keys on a midi-board instead of only tone (white) keys with high pitch values. So, if you send the data to another software, it will detect all keys seperately. For example, there were no G and G# before, only G and G-with-high-pitch. These caused keys to stop eachother when note-on messages are sent simultaneously.
Is it possible to know/get how much space/memory are used when a method is executed or when there is a return value? I don't want to know how much space used by the app, just some code like method or the return value. I tried the runtime.getRuntime, but from my understanding, It looks like it tells me how much space is used by the entire code/app, am I right?
EDIT :
public int [] randtotal(int times2)
{
int in1[] = new int[times2];
for (int i = 0; i<Num2; i++)
Random rand = new Random();
{
in1[times2]= rand.NextInt(5);
}
totalNum(in1);
return int1;
}
As you can see here, at the end of the code there is the "return int1;" , so I want to know when these code is executed how much space is allocated for the value here?
You can use Visualvm tool to profile the overall application and you can also profile certain package, class or function
see this link :
https://visualvm.java.net/profiler.html
I have been debugging my implementation of Game of Life, and my main problem looks like its coming from how I use arrays.
public boolean[][] oldState;
public boolean[][] newState;
private boolean gameState = true;
public LifeBoard(Seed seed) {
oldState = seed.getSeed();
newState = new boolean[oldState.length][oldState[0].length];
run();
}
public void run() {
//debug code to run for x generations
for (int i = 0; i < 5; i++) {
BoardPrinter.print(oldState);
evaluateCells();
oldState = newState;
}
BoardPrinter.print(oldState);
System.out.println("game over");
}
the boolean[][] from Seed is a 5x5 grid, all false (dead) except the 3 horizontal middle cells in the middle row
00000
00000
0+++0
00000
00000
evaluateCells() looks at each cell in the grid, looks at the 8 cells around it, counts them, and based on the number of neighbors it writes a new value to newState.
What should happen: use oldState to calculate newState, copy newState to oldState, then go back through newState, writing each cell again based on the new oldState.
What really happens: the first generation works correctly, but after that the results are increasingly weird, it evaluates cells to be false that I know to be true, etc. The problem seems to be in the way I am copying the arrays.
If I initialize a 3rd blank array blankState[][] = new boolean[5][5];
and during the loop in run say:
public void run() {
//debug code to run for x generations
for (int i = 0; i < 5; i++) {
BoardPrinter.print(oldState);
evaluateCells();
oldState = newState;
newState = blankState;
}
BoardPrinter.print(oldState);
System.out.println("game over");
}
...then the game works correctly for an additional 1 generation, then the weird garbage returns.
I have 2 questions: first, it looks like I have to use System.arraycopy(), but unless someone tells me about a version for multidimensional arrays, I will have to write a simple loop.
My real question: why do you have to use this special System method to copy an array? Why can't you use the = operator?
EDIT: the conceptual answer is accepted below. Here is the code that solved the implementation problem:
for (int n = 0; n < oldState.length; n++) {
System.arraycopy(newState[n], 0, oldState[n], 0, oldState.length);
}
for (int t = 0; t < newState.length; t++) {
System.arraycopy(blankState[t], 0, newState[t], 0, newState.length);
}
Also for the record, System.arraycopy(boolean[][], 0, boolean[][], 0, boolean.length); did not work correctly, you have to iterate through each line.
My real question: why do you have to use this special System method to copy an array? Why can't you use the = operator?
This is actually an important Java lesson, so pay attention. Are you paying attention? Good. This will be important in the future.
Now, this applies for all objects in Java, as arrays are objects. If you use = then you only set the reference, and encounter all kinds of fun as seen here. Namely, if I have a simple class with a getter and setter called TestClass with a public int test, then the following code will work:
TestClass t=new TestClass();
t.test=1;
TestClass t1=t;
t1.test=6;
System.out.println(t.test); //prints 6.
Now, why? Because the references t and t1 point to the same object on the heap. And this holds for arrays as well. To get copies, you need to perform tasks that are object-specific. Some let you call clone() directly(Cloneable interface), some let you pass another instance into the constructor to get a new instance(Like the ArrayList constructor), and some use utility methods, like arrays here.
evaluateCells() looks at each cell in the grid, looks at the 8 cells
around it, counts them, and based on the number of neighbors it writes
a new value to newState.
What should happen: use oldState to calculate newState, copy newState
to oldState, then go back through newState, writing each cell again
based on the new oldState.
What really happens: the first generation works correctly, but after
that the results are increasingly weird, it evaluates cells to be
false that I know to be true, etc. The problem seems to be in the way
I am copying the arrays.
Without seeing your bit shifting code, I'd bet this is caused by a higher level problem. Most likely your bit shifting algorithm has a bug somewhere.
Have you stepped through your code with Eclipse's debugger? If not, read this tutorial and try a few different seeds. This will tell you where, if anywhere, in your algorithm the bit shift error occurs.
http://www.vogella.com/articles/EclipseDebugging/article.html
OK, so I created a console app that, among other things, takes an array of numbers and prints them out one by one, line by line. Now, I have to take the class that I created for that console app, and pop it into a separate GUI app we're creating. I have all of the other methods working fine, but for the life of me I cannot get the array method to print out correctly. It just gives me the last number I typed into the text field. I'm hoping someone can give me a nudge to help me figure this part out so I can move along, and get to the whole SpringLayout stuff, (the main part of the new assignment) I am limited in what I can show you here because this is a current assignment, so I will have to stick to this stuff as specifically as I can. And please, don't just post the code as an answer, (because then I can't use it), thanks.
Here's what I had for my original project for the array method:
int [] getArray(int x)
{
breakUpNum(x);
return numAry;
}
From there, inside my new class I have this, in an attempt to get it to print:
private class ButtonTest implements ActionListener
{
public void actionPerformed(ActionEvent ae)
{
Lab1 tester = new Lab1();
int[] test4 = tester.getArray(num);
for(int i = 0; i < test4.length; i ++)
{
crossTest.getArrCross.setText("" + test4[i]);
}
}
}
Any help pointing me in the right direction would be greatly appreciated, thanks!
setText does just that, sets the text you pass to as the current text content, it does not append it.
If you were to use JTextArea, you could use it's append method...however, for a JTextField you need to have a different approach.
Now you could use getArrCross.setText(getArrCross.getText() + test4[i])...but to quite frank, that's rather inefficient, as each call to setText is going to stage a paint event...
StringBuilder sb = new StringBuilder(128);
for(int i = 0; i < test4.length; i ++)
{
sb.append(test4[i]);
}
crossTest.getArrCross.setText(sb.toString());
Now, if you want to separate each element, you need to add
if (sb.length() > 0) {
sb.append(", ");
}
Before sb.append(test4[i]);
The last bit of actionPerformed in the for loop isn't working right. setText replaces the current text with its argument, and it doesn't seem like you want to do that. To fix it, replace the line in the for loop with this:
crossTest.getArrCross.setText(crossTest.getArrCross.getText() + test4[i]);
I'm working on (what is to a beginner) a rather complex assignment. I think I've got the jist of it down, but I'm having trouble with it printing "null" after Monday-Sunday are entered into the dialog box. Also, the goal of the assignment is, later, for the user to enter a number 0-6 and then the corresponding weekday (from the String[] weekArray set in the method) is printed. I'm not really sure how to do this and my book doesn't seem to be showing me the way, but am I even going to be able to do that the way my code is set up? Thanks and best regards. Here's the code.
EDIT - there's an example in my book under returning an array from a method. I'm not sure if it's applicable to my assignment as they seem to have different goals, but here it is..
EDIT#2 - instructions for reference to what I'm doing.
EDIT#3 - my interpretation of the example for passing methods to arrays.
EDIT #4 - solved the issue. I was going about it the wrong way for much. The book's example wasn't much help. Thanks to those of you who replied. I deleted the homework assignment description in consideration of the professor (who probably wouldn't like his assignments on the internet next semester)
Excerpt of the code below... I was making this way more complicated than it was
public static String[] getWeek() {
String[] weekArray = new String[7];
for (int i = 0; i < weekArray.length; i++) {
weekArray[0] = JOptionPane.showInputDialog("Enter 'Monday'. ");
if (weekArray[0].compareTo("Monday") > 0) {
weekArray[0] = JOptionPane.showInputDialog("Enter 'Monday'. ");
Your branches have unreachable statements -
weekArray[5] = ...
while(weekArray[5].equalsIgnoreCase(null)) {
// Cannot reach this point as equalsIgnoreCase(null) always returns false.
}
From String#equalsIgnoreCase:
true if the argument is not null and the Strings are equal, ignoring case; false otherwise.
Emphasis mine.
EDIT: From your edit above you appear to be having trouble with populating an array. The rough idea is:
public static void main(String[] args) {
// Just an example
int[] values = new int[5];
System.out.println(Arrays.toString(values));
populateArray(values);
System.out.println(Arrays.toString(values));
}
private static void populateArray(int[] toBePopulated) {
toBePopulated[0] = 42;
toBePopulated[1] = 11;
// Etc. Again, just an example.
}
This will print:
[0, 0, 0, 0, 0]
[42, 11, 0, 0, 0]
The idea is that what is passed to the method populateArray is a reference to the location of the array in memory. That means that you can manipulate the contents of the array, and the change will be reflected in values afterwards.
I don't know if i got it right , but from a cursory look , seems you're mistaking the sunday part , guess it should be sth like :
if (weekArray[5].equalsIgnoreCase("Sunday")) // Note the "5"
Your cheek for string being null is probably not what you want. If you indent the code it would be easier to see.
After formatting this is what you have
while (weekArray[0].equalsIgnoreCase(null)) {
if (weekArray[0].equalsIgnoreCase("Monday"))
return weekArray[0];
}
So, if weekArray[0] is null, then you check if null equalsIgnoreCase("Monday"). This logic is not what you want.
After asking and checking all days you return null (at the end of the method). This si the null being printed.