[vtkusers] Java app Xlib async problem

Jeff Lee jeff at cdnorthamerica.com
Tue Sep 14 18:05:29 EDT 2004



Christopher.Moore at noaa.gov wrote:

>I know this was beaten to death, but I'm a humble C++ programmer trying to 
>learn Java.
>
>I'm using VTK 4.2 on RedHat 9, and I create a Java application, with a 
>simple GUI, based on the Examples.  It uses vtkCanvas (which extends 
>vtkPanel), so I thought I didn't have to worry about calls to the Renderer 
>from the GUI, but I still get Xlib: unexpected async reply.
>
>I'm including the shortest application I could make that repeats the 
>problem.  Could someone let me know how I could fix the call to 
>createIconFromScreen?  I tried using SwingUtilities.invokeLater, to no 
>avail.
>  
>
Hi,
The problem is that you need to lock the drawing surface when changing 
it.  The call to windowToImageFilter Update() will cause the c++ code to 
call Render() which is changing the java drawing surface.  What you need 
to do is  similar to what vtkPanel.Hardcopy() does.  I guess we 
can/should expose the lock mechanism of vtkPanel (that's what I do.).  
In the short term, you can modify vtkPanel and give it public methods 
lock() and unlock() which internally call Lock() and UnLock() 
respectively.  Then in your createIconFromScreen() method, wrap 
w2i.Update() with a renWin.lock()/renWin.unlock() and it should be 
fine.  There are more sophisticated locking mechanisms, but this should 
suffice for what you are trying to do.  The rule (one of experience) is 
to lock/unlock around any java method which might call Render() or 
MakeCurrent() or otherwise modify the drawing surface.  A note of 
caution - lock/unlock does not imply thread safety - for instance you 
can still screw things up if you get the locking right but start 
changing the pipeline from different threads.  Have fun,
-Jeff

>Thanks in advance,
>Chris
>
>==== code follows ====
>
>import vtk.*;
>
>import java.awt.*;
>import java.awt.event.*;
>import java.util.*;
>import javax.swing.*;
>
>/**
> *   Example application using Java-wrapped VTK
> *   to learn how to use threads in Java to avoid
> *   Xlib: async errors
> *
> *   Run the first time as is:
> *   (compile with "javac ExampleApp.java", run with "java ExampleApp")
> *
> *   Then uncomment the call to createIconFromScreen (line 128)
> *   and re-compile and run to see error message (click "Add" button
> *   repeatedly until error occurs)
> */
>
>public class ExampleApp extends JFrame {
>
>    private JToolBar mainTools;
>    private JButton addButton;
>    private JButton removeButton;
>    private JButton cameraResetButton;
>    private Dimension screenSize;
>
>    private vtkCanvas renWin = null;
>    private vtkRenderer ren = null;
>    private vtkCamera camera = null;
>
>    private Vector UserGobs = null;
>    private int gobCount = -1;
>
>    public ExampleApp() {
>	this.setSize(800, 800);
>
>	screenSize = Toolkit.getDefaultToolkit().getScreenSize();
>
>	WindowListener l = new WindowAdapter() {
>		public void windowClosing(WindowEvent e) {
>		    System.exit(0);
>		}
>	    };
>	this.addWindowListener(l);
>
>	mainTools = new JToolBar();
>	mainTools.setOrientation(1);
>
>	addButton = new JButton("Add");
>	addButton.addActionListener(new ActionListener() {
>		public void actionPerformed(ActionEvent evt) {
>		    addActor(evt);}
>	    });
>	mainTools.add(addButton);
>
>	removeButton = new JButton("Remove");
>	removeButton.addActionListener(new ActionListener() {
>		public void actionPerformed(ActionEvent evt) {
>		    removeActor(evt);}
>	    });
>	mainTools.add(removeButton);
>
>	cameraResetButton = new JButton("ResetCamera");
>	cameraResetButton.addActionListener(new ActionListener() {
>		public void actionPerformed(ActionEvent evt) {
>		    updateCamera();}
>	    });
>	mainTools.add(cameraResetButton);
>
>	this.getContentPane().add(mainTools, BorderLayout.WEST);
>
>	renWin = new vtkCanvas();
>
>	// attach observer to set the render window size after
>	// the render window is created...
>	renWin.addWindowSetObserver(new Observer() {
>		public void update(Observable o, Object arg) {
>		    renWin.setSize(800, 800);
>		}
>	    });
>	this.getContentPane().add(renWin, BorderLayout.CENTER);
>	renWin.setSize(800,800);
>
>	ren = renWin.GetRenderer();
>        ren.SetBackground(1,1,1);
>	ren.LightFollowCameraOn();
>
>	this.getContentPane().add(renWin, BorderLayout.CENTER);
>
>	// Always have at least one actor:
>	vtkConeSource cs = new vtkConeSource();
>	cs.SetRadius(0.5);
>	cs.SetHeight(2.0);
>	vtkPolyDataMapper coneMapper = new vtkPolyDataMapper();
>	coneMapper.SetInput(cs.GetOutput());
>	vtkActor coneActor = new vtkActor();
>	coneActor.SetMapper(coneMapper);
>	coneActor.GetProperty().SetColor(0,0,1);
>	coneActor.AddPosition(0,1.0,0);
>	ren.AddActor(coneActor);
>
>	UserGobs = new Vector();
>
>	camera = ren.GetActiveCamera();
>    }
>
>
>    private void updateCamera() {
>	camera.SetPosition(0,0,10.0+(double)gobCount);
>	camera.SetFocalPoint(0,0,0);
>	camera.SetViewUp(0,1,0);
>	renWin.resetCameraClippingRange();
>	renWin.Render();
>    }
>
>    private void addActor(ActionEvent evt) {
>	Hydro ctdHydro = new Hydro();
>	UserGobs.add(ctdHydro);
>	gobCount++;
>	ctdHydro.getActor().GetProperty().SetColor(1,(double)gobCount/5.0,0);
>	ctdHydro.getActor().AddPosition((double)gobCount/4.0,0,0);
>	ren.AddActor(ctdHydro.getActor());
>	renWin.resetCameraClippingRange();
>	renWin.Render();
>	// uncomment this to get Xlib: async error
>	//createIconFromScreen();
>    }
>
>    private void removeActor(ActionEvent evt) {
>	if (gobCount >= 0) {
>	    Hydro ctdHydro = (Hydro) UserGobs.get(gobCount);
>	    ren.RemoveActor(ctdHydro.getActor());
>	    UserGobs.remove(gobCount);
>	    gobCount--;
>	    renWin.Render();
>	}
>    }
>
>    public class Hydro {
>	private vtkActor HydroActor;
>
>	public Hydro() {
>	    vtkSphereSource ss = new vtkSphereSource();
>	    ss.SetRadius(1.0);
>	    vtkPolyDataMapper sMapper = new vtkPolyDataMapper();
>	    sMapper.SetInput(ss.GetOutput());
>	    HydroActor = new vtkActor();
>	    HydroActor.SetMapper(sMapper);
>	}
>
>	public vtkActor getActor() {
>	    return HydroActor;
>	}
>
>    }
>
>    private void createIconFromScreen() {
>	// I tried with and without "invokeLater"
>	SwingUtilities.invokeLater(new Runnable() {
>		public void run() {
>		    vtkWindowToImageFilter w2i = new vtkWindowToImageFilter();
>		    w2i.SetInput(renWin.GetRenderWindow());
>		    w2i.Update();
>
>		    int[] dims = w2i.GetOutput().GetDimensions();
>		    System.out.println("image x: " + dims[0]);
>		    System.out.println("image y: " + dims[1]);
>		    System.out.println("image z: " + dims[2]);
>		}
>	    });
>
>	/*
>	vtkPNGWriter pngWriter = new vtkPNGWriter();
>	pgnWriter.SetInput(w2i.GetOutput());
>	pngWriter.SetFileName();
>	pngWriter.Write();
>
>	w2i.Delete();
>	pngWriter.Delete();
>	*/
>    }
>
>    public static void main(String[] args) {
>	JFrame f = new ExampleApp();
>	f.pack();
>	f.setVisible(true);
>    }
>}
>
>_______________________________________________
>This is the private VTK discussion list. 
>Please keep messages on-topic. Check the FAQ at: <http://public.kitware.com/cgi-bin/vtkfaq>
>Follow this link to subscribe/unsubscribe:
>http://www.vtk.org/mailman/listinfo/vtkusers
>
>
>  
>



More information about the vtkusers mailing list