Skip to main content

adding a container to a container on a different GraphicsDevice

3 replies [Last post]
a1flecke
Offline
Joined: 2006-03-05
Points: 0

Hello,

I am still pretty new to Java 3D (I have only been programming with it for about 2 months) and I have encountered a

problem when users use my software in a multiple monitor environment. When start the software on one monitor (which

creates and setup a Canvas3D object), move it to another monitor, and then tries to add to the panel (like a branchgroup),

I receive this error

Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: adding a container to a container on a

different GraphicsDevice
at java.awt.Component.checkGD(Component.java:858)
at java.awt.Container.addImpl(Container.java:1015)
at java.awt.Container.add(Container.java:351)
at Plot3DBuilder.switchtoSurface(Plot3DBuilder.java:340)

the switchtoSurface method's code is:

<br />
public void switchToSurface(){<br />
        if(surf==null){<br />
            if(lego!=null){<br />
                surf = new SurfacePlot(lego.getTransGroup());<br />
            } else{<br />
                surf=new SurfacePlot();<br />
            }<br />
            surf.setData(lego.getData());<br />
            panel.remove(lego);<br />
            panel.add(surf);  /*<-------line 340*/<br />
            surf.setLocation(lego.getLocation());<br />
            surf.setSize(lego.getSize());<br />
            surf.setXAxisLabel(lego.getXAxisLabel());<br />
            surf.setYAxisLabel(lego.getYAxisLabel());<br />
            surf.setZAxisLabel(lego.getZAxisLabel());<br />
            surf.setTextColor(lego.getTextColor());<br />
            surf.setBackgroundColor(lego.getBackgroundColor());<br />
            lego=null;<br />
            fixSize();<br />
            panel.revalidate();<br />
            panel.repaint();<br />
        }<br />
    }<br />

Panel is a JPanel. lego and surf are classes that extend another class of mine, Plot3D. Here is some of Plot3D's code:

<br />
public abstract class Plot3D extends Canvas3D {<br />
    protected boolean init = false;<br />
    protected boolean parallelProjection = false;<br />
    protected SUniverse universe;<br />
    Transform3D objT3d;<br />
    TransformGroup objTransform;<br />
    protected Color bkColor;<br />
    BranchGroup scene;<br />
    protected int zoomLevel=0;<br />
    protected TransparencyAttributes ta;<br />
    Appearance appear;</p>
<p>    double[] hldMtx;<br />
    double[] origMtx;<br />
    private final float ROT_CONV=180f/((float)Math.PI);</p>
<p>    Plot3D() {<br />
        super(SUniverse.getPreferredConfiguration());<br />
        bkColor=Color.WHITE;<br />
        Background newBk = new Background(new Color3f(bkColor));<br />
        this.getGraphicsContext3D().setBackground(newBk);<br />
        System.out.println("In Plot3D()");<br />
        System.out.println("Configuring SimpleUniverse with the preferred Configuration");<br />
        System.out.println("Leaving Plot3D");<br />
    }<br />
    Plot3D(TransformGroup t){<br />
        super(SUniverse.getPreferredConfiguration());<br />
        bkColor=Color.WHITE;<br />
        Background newBk = new Background(new Color3f(bkColor));<br />
        this.getGraphicsContext3D().setBackground(newBk);<br />
        System.out.println("In Plot3D()");<br />
        System.out.println("Configuring SimpleUniverse with the preferred Configuration");<br />
        System.out.println("Leaving Plot3D");<br />
        objTransform=t;<br />
    }<br />
    protected void init() {<br />
        Node plot = createPlot();<br />
        scene = defineMouseBehaviour(plot);<br />
        setupLights(scene);<br />
        scene.compile();<br />
        Background newBk = new Background(new Color3f(bkColor));<br />
        this.getGraphicsContext3D().setBackground(newBk);<br />
        universe = new SUniverse(this);<br />
        universe.getViewingPlatform().setNominalViewingTransform();<br />
        universe.addBranchGraph(scene);<br />

SUniverse is a class that extends SimpleUniverse to implement a workaround that was suggested here:

https://java3d.dev.java.net/issues/show_bug.cgi?id=89

<br />
public class SUniverse extends SimpleUniverse{</p>
<p>    /** Creates a new instance of SUniverse */<br />
    public SUniverse() {<br />
        super();<br />
    }<br />
    public SUniverse(Canvas3D c){<br />
        super(c);<br />
    }<br />
    public static GraphicsConfiguration getPreferredConfiguration(Window window) {<br />
        GraphicsDevice device = window.getGraphicsConfiguration().getDevice();<br />
        GraphicsConfigTemplate3D template = new GraphicsConfigTemplate3D();<br />
        String stereo;</p>
<p>        stereo = (String) java.security.AccessController.doPrivileged(<br />
                new java.security.PrivilegedAction() {<br />
            public Object run() {<br />
                return System.getProperty("j3d.stereo");<br />
            }<br />
        });</p>
<p>        if (stereo != null) {<br />
            if (stereo.equals("REQUIRED"))<br />
                template.setStereo(GraphicsConfigTemplate.REQUIRED);<br />
            else if (stereo.equals("PREFERRED"))<br />
                template.setStereo(GraphicsConfigTemplate.PREFERRED);<br />
        }<br />
        return device.getBestConfiguration(template);<br />
    }</p>
<p>}<br />

Any help would be appreciated. More of our uses are using dual-monitor setups and telling them that they must keep the application on one screen will not be welcomed.

Aaron

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
cringe
Offline
Joined: 2004-08-17
Points: 0

I stumbled across the same problem today by accident. This is what I found:

http://archives.java.sun.com/cgi-bin/wa?A2=ind0405&L=java3d-interest&T=0...

https://java3d.dev.java.net/issues/show_bug.cgi?id=89

The 2nd link is to the Java3D issue tracker. I don't know if they are developing or if this is yet fixed in the 1.4.0 release, but maybe you find some more information about it.

robertf
Offline
Joined: 2005-02-28
Points: 0

I too hit this a couple of days ago - must be morphic resonance. I got around it by storing the screen positions at startup and then getting the configuration for the screen on which the component centre lies.

Here are a few code fragments that may help:
[code]
// static initialiser to load available screens
static
{
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
screens_ = ge.getScreenDevices();
int ns = screens_.length;
screenRects_ = new Rectangle[ns];
for (int j = 0; j < ns; j++)
{
GraphicsDevice screen = screens_[j];
String id = screen.getIDstring();
screenNames_.addElement(id);
Rectangle r = screen.getDefaultConfiguration().getBounds();
screenRects_[j] = r;
}

defaultScreen_ = ge.getDefaultScreenDevice();
}

private static GraphicsConfiguration getPreferredConfig(GraphicsConfigTemplate template, Point p)
{
GraphicsDevice screen = ScreenSettings.getScreen(p);
if ( screen == null )
screen = ScreenSettings.defaultScreen_;

if ( template == null )
return screen.getDefaultConfiguration();
else
return screen.getBestConfiguration(template);
}

/**
* return the screen containing the point, null if none do
*/
public static GraphicsDevice getScreen(Point p)
{
if ( p==null )
return null;

GraphicsDevice screen = null;
int i, n = screenRects_.length;
for ( i=0;i {
if (screenRects_[i].contains(p) )
{
screen = screens_[i];
break;
}
}
return screen;
}
[/code]

Message was edited by: robertf

a1flecke
Offline
Joined: 2006-03-05
Points: 0

Thanks both of you for replying. As things usually go, I am currently on vacation, but I will try your suggestions on Monday.

Thanks again,

Aaron