http://imagej.273.s1.nabble.com/Strange-ClassCastException-A-puzzle-for-Java-ImageJ-experts-to-help-me-wit-tp3692688p3692694.html
Thanks, Curtis. Here's what I get
file:/Applications/ImageJ/plugins/QuickTime_Plugins_MMRD041109/MultiQTVirtualStack.class
file:/Applications/ImageJ/plugins/QuickTime_Plugins_MMRD041109/MultiQTVirtualStack.class
equal classes. However both paths point to the same class file!
I didn't think that imp.getStack() would call the constructor....
>Hi Bill,
>
>That's a devilish problem. Normally, the message printed in the
>ClassCastException is the actual (incompatible) class of the object in
>question. So it would appear that your object's class is
>MultiQTVirtualStack, but somehow a different MultiQTVirtualStack than the
>one you are referencing in code.
>
>The only way I know for that to happen would be if the two classes have
>different packages, which would happen if you have an import statement at
>the top of your class. For example, let's say there's a
>foo.bar.MultiQTVirtualStack in your classpath. If your code has a line
>"import foo.bar.*;" on top, you might have the problem you're seeing.
>
>Try adding the following debugging code:
>
>Class stackClass = stack.getClass();
>Class mqtvsClass = MultiQTVirtualStack.class;
>IJ.log("stack class = " + stackClass.getName());
>IJ.log("MultiQTVirtualStack class = " + mqtvsClass.getName());
>IJ.log("Classes equal? " + (stackClass == mqtvsClass) + "/" +
>stackClass.equals(mqtvsClass));
>IJ.log("path to MultiQTVirtualStack class = " +
>mqtvsClass.getResource(mqtvsClass.getName() + ".class"));
>IJ.log("path to stack class = " +
>stackClass.getResource(stackClass.getName() + ".class"));
>
>Let us know what you find out!
>
>-Curtis
>
>On Wed, Apr 29, 2009 at 9:50 AM, Bill Mohler <
[hidden email]>wrote:
>
>> I hope that some of you with time and experience can help me with a
>> suggestion. Please take some time, if you have a chance, to work through
>> the details I'm providing below:
>>
>> I have created a new class called MultiQTVirtualStack (MQTVS for short
>> here), spinning off of the success of Jeffrey Woodard's QTVirtualStack (QTVS
>> for short here, which makes working with QuickTime movies in a true ImageJ
>> StackWindow a delight).
>>
>> MQTVS extends VirtualStack (and therefore ImageStack) and allows the user
>> to open a collection of QTVSs into a single Virtual HyperStack window, in
>> which each QTVS plays as a separate channel, but all the QTVS-derived
>> channels are navigated synchronously in the Z and T dimensions. The window
>> can be viewed in either Composite (color overlay), Color (separate channel),
>> or Grayscale (separate channel) modes that are available for HyperStacks.
>> This all works nicely now for me. Happy to share the code, but it's not
>> cleaned up pretty yet.
>>
>> Now I am trying to create a PluginFrame with which the user can shift the
>> registration of the Z and T dimensions of the various QTVS channels of the
>> MQTVS window, so as to better synchronize movies that were collected
>> separately and may start at different relative times during an event of
>> interest that needs to be compared.
>>
>> I have previously created methods MQTVS.adjustSingleMovieZ(int channel,
>> boolean forward) and MQTVS.adjustSingleMovieT(int channel, boolean forward),
> > which in turn call methods in my modified version of QTVS to rearrange the
>> order of elements in the ArrayList, frameLocations, pointing to movie frames
>> by a single position in either Z or T. This interaction of methods has
> > worked well for me when I code "for" loops that make a fixed
>number of calls
>> to the MQTVS.adjustSingleMovie...() methods from within the constructor of
>> MQTVS (an experimental proof of principal that works very nicely). Here are
>> the methods themselves, isolated from the rest of their classes for
>> simplicity. The problems I'm having in calling these methods via a
>> PluginFrame are described below.
>>
>> From MQTVS:
>> /*These methods allow viewer to shift the Z or T positions of a given
>> channel to better synchronize movies.*/
>> public void adjustSingleMovieZ(int channel, boolean forward) {
>> this.forward = forward;
>> ((QTVirtualStack) stack[channel]).shiftMovieZ(forward);
>> IJ.log("got to MQTVS.ASMZ");
>>
>> }
>>
>> public void adjustSingleMovieT(int channel, boolean forward) {
>> this.forward = forward;
>> ((QTVirtualStack) stack[channel]).shiftMovieT(forward);
>>
>> }
>>
>>
>> From QTVS:
>> /*These methods allow viewer to shift the Z or T positions of a given
>> channel to better synchronize movies.*/
>> public void shiftMovieT(boolean forward) {
>> this.forward = forward;
>> if (!forward) {
>> for (int z = 0; z < maxSlicesSingleMovie ; z++) {
>> this.frameLocations.add( (z*
>> maxTimesSingleMovie) , this.frameLocations.get( ((z+1)* maxTimesSingleMovie)
>> -1) );
>> this.frameLocations.remove( ((z+1)*
>> maxTimesSingleMovie) -1 );
>> }
>> } else {
>> for (int z = maxSlicesSingleMovie-1 ; z >= 0 ; z--)
>> {
>> this.frameLocations.add( ((z+1)*
>> maxTimesSingleMovie-1) , this.frameLocations.get( (z)* maxTimesSingleMovie
>> ));
>> this.frameLocations.remove( ((z)*
>> maxTimesSingleMovie ) );
>> }
>> }
>> }
>>
>> public void shiftMovieZ(boolean forward) {
>>
>> this.forward = forward;
>> ArrayList copyFrames = new ArrayList();
>> IJ.log("Got to the QTVS.SMZ");
>>
>> if (forward) {
>> for (int t= 0; t < maxTimesSingleMovie; t++) {
>> copyFrames.add(
>> this.frameLocations.get(((maxSlicesSingleMovie-1)*maxTimesSingleMovie) ) );
>>
>>
>> this.frameLocations.remove(((maxSlicesSingleMovie-1)*maxTimesSingleMovie)
>> );
>> }
>> this.frameLocations.addAll(0, copyFrames);
>> } else {
>> for (int t= 0; t < maxTimesSingleMovie; t++) {
>> copyFrames.add( this.frameLocations.get(0)
>> );
>> this.frameLocations.remove(0);
>> }
>> this.frameLocations.addAll(copyFrames);
>> }
>>
>> }
>>
>>
>>
>> **Now to the problems I am having (apparently at the level of the JVM??).
>> Here I try to call the public method MQTVS.adjustSingleMovieZ(int channel,
>> boolean forward), sending parameters set by the user in the slider of the
>> PluginFrame. I have no problems compiling, and get no exceptions reported
>> in the log window of ImageJ. But (thanks to help from Wayne), I find a
>> ClassCastException from the event dispatch thread in the console. The
>> confusion comes in the apparent correctness of the type of a variable that I
>> assign with the ImagePlus.getStack() command, but the wrongness of how the
>> event dispatch thread deals with the variable when I try to cast it to its
>> true type (I think). First I show the code from the method in the
>> PluginFrame that reads the value of sliders and should call
>> MQTVS.adjustSingleMovieZ(int channel, boolean forward) to change a specific
> > QTVS's frame position being displayed. Then below the code, I show the
>> IJ.log output from several lines in the method, and then the
>> ClassCastException from the console.
>>
>> The key method from my PluginFrame MovieAlignFrameMOD:
> > public synchronized void adjustmentValueChanged(AdjustmentEvent e) {
>> ImagePlus imp = WindowManager.getCurrentImage();
>>
>> ImageStack stack = imp.getStack();
>> IJ.log(""+stack.getClass().getName() + "1");
>>
>> ImageWindow win = imp.getWindow();
>> int zImpPos = imp.getSlice();
>> int tImpPos = imp.getFrame();
>> IJ.log("beforetheloop " + imp+" \n" + imp.getStack()) ;
>> boolean forward = false;
>>
>> if (imp==null) return;
>> for (int i=0; i< imp.getNChannels(); i++){
>> if (e.getSource()==sliceShifter[i]) {
>> int zShiftLive = sliceShifter[i].getValue();
>> int zShiftNet = zShiftLive -
>> previousShiftZ[i];
>> int zShiftNetAbs = zShiftNet;
>> if (zShiftNet < 0) {
>> zShiftNetAbs = -zShiftNet;
>> forward = true;
>> }
>> previousShiftZ[i] = previousShiftZ[i] +
>> zShiftNet;
>>
>> for(int j = 0; j < zShiftNetAbs; j++){
>> IJ.log("intheloop j= " + j + " " +
>> imp+" \n" + imp.getStack()) ;
>> IJ.log(""+stack.getClass().getName() + "2");
>>
>> /** THIS DOES NOT REPORT, SO IT'S CLEAR THAT stack
>> IS NOT reporting as instanceof MultiQTVirtualStack,
>> even though it reports as one using
>> stack.getClass().getName() **/
>> if (stack instanceof
>> MultiQTVirtualStack ) IJ.log("MultiQTVirtualStack? Yes!!!!");
>>
>> /*** ...But THIS STILL READS OUT AS
>> MultiQTVirtualStack ******/
>>
>> IJ.log(""+stack.getClass().getName() + "3");
>>
>> /**** THIS GIVES A "SILENT" ClassCastException ON
>> THE EVENT DISPATCH THREAD, CAN SEE IN CONSOLE *****/
>> /* LINE 289 */ ((MultiQTVirtualStack)
>> stack).adjustSingleMovieZ(i, forward);
>>
>> /***** Once the exception has been thrown, this next
>> log statement fails to run ***********/
>>
>> IJ.log(""+stack.getClass().getName() + "4");
>>
>> }
>>
>> }
>> else if (e.getSource()==frameShifter[i]) {
>> int tShiftLive = frameShifter[i].getValue();
>> int tShiftNet = tShiftLive -
>> previousShiftT[i];
>> previousShiftT[i] = tShiftNet;
>> /****** THE ACTIONS OF THIS IF CONDITION WILL BE
>> FILLED IN LATER ONCE I FIGURE OUT OTHER PROBLEMS ********/
>>
>> }
>> notify();
>> }
>> }
>> }
>>
>>
>>
>> Here's what is logged by the IJ.log() statements above during a slider
>> adjustment:
>>
>> MultiQTVirtualStack1
>> beforetheloop imp[3-Movie Overlay #1 : see Log window for details
>> 600x411x38961]
>> stack[600x411x38961]
>> intheloop j= 0 imp[3-Movie Overlay #1 : see Log window for details
>> 600x411x38961]
>> stack[600x411x38961]
>> MultiQTVirtualStack2
>> MultiQTVirtualStack3
>>
>>
>> !!Note that I did not leave out the 4th log statement in copying. The CCE
>> apparently blocks the ability to run the 4th IJ.log statement after line
>> 289. Also, the instanceof test fails (even before line 289), because I
>> don't get the "MultiQTVirtualStack? Yes!!!" log printed.
>>
>>
>> Finally, this is the exception from the event dispatch thread at the
>> critical line 289:
>>
>> 4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748] Exception in
>> thread "AWT-EventQueue-0" java.lang.ClassCastException: MultiQTVirtualStack
>> 4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748] at
> > MovieAlignFrameMOD.adjustmentValueChanged(MovieAlignFrameMOD.java:289)
>> 4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748] at
>> java.awt.Scrollbar.processAdjustmentEvent(Scrollbar.java:1094)
>> 4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748] at
> > java.awt.Scrollbar.processEvent(Scrollbar.java:1061)
>> 4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748] at
>> java.awt.Component.dispatchEventImpl(Component.java:4068)
>> 4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748] at
>> java.awt.Component.dispatchEvent(Component.java:3903)
>> 4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748] at
>> java.awt.EventQueue.dispatchEvent(EventQueue.java:463)
>> 4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748] at
>>
>>java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:269)
>> 4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748] at
>>
>>java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:190)
>> 4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748] at
>> java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:184)
>> 4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748] at
>> java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:176)
>>
>>
>>
>> In summary, I seem to have an object called stack returned to me by
>> ImagePlus.getStack() which both is a MultiQTVirtualStack by some tests and
>> is NOT a MultiQTVirtualStack by others, and these other criteria are what I
>> really need to make my PluginFrame work.
>>
>> Can anyone give me a hint of an explanation of what is going on here?
>>
William A. Mohler
Dept. of Genetics and Developmental Biology
263 Farmington Ave.
alt. mobile: (860) 331-8514
G&DB dept. ofc.: (860) 679-8350
G&DB dept. fax : (860) 679-8345