[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