Java multi-thread and model Observer

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Java multi-thread and model Observer

Jean-Max Redonnet
Hello everyone !

I'm using vtk throught its java wrapper and I'm setting up a versatile viewer that can display an existing model and update display when this model is updated (and it will be continously updated).

My Model is built around few classes: VtkObject that is the ancestor of many other classes like VtkSurface, VtkCurve, etc... and VtkModel that basically contains a list of VtkObjects and maintain Listeners. All these classes are of my own (please note uppercase "V" on VtkObject)


public class VtkObject{
    protected final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
    protected List<vtkActor> actors = new ArrayList<vtkActor>();
    ...
}

public class VtkSurface extends VtkObject {
    private vtkActor surfActor;
    ...
}

public class VtkModel implements PropertyChangeListener{
    protected List<VtkObject> objects;
    protected PropertyChangeSupport support;
    ...
}

For the viewer itself I wrote a VtkPanel that is mostly inspired by the example provided by Sébastien Jourdain (https://github.com/Kitware/VTK/blob/master/Wrapping/Java/vtk/sample/Demo.java)

I just make this panel model-aware implementing PropertyChangeListener:

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        if (evt.getPropertyName() == "AddedObject") {
            System.out.println("Added Object");
            VtkObject o = (VtkObject) evt.getNewValue();
            if(o.getActors().size()>0)
                exec.submit(new PipelineBuilder(o));
        }
        if (evt.getPropertyName() == "UpdatedObject") {
            System.out.println("Updated Object");
            VtkObject o = (VtkObject) evt.getNewValue();
            if(o.getActors().size()>0)
                exec.submit(new PipelineBuilder(o));
        }
    }

and slithly modify PipelineBuilder to make it able to manage VtkObjects that may contain several vtkActors

    public class PipelineBuilder implements Callable<vtkActor> {
        private int counter;
        private List<vtkActor> actors;

        public PipelineBuilder(VtkObject o) {
            actors = o.getActors();
            counter = 0;
        }

        @Override
        public vtkActor call() throws Exception {
            counter++;
            if (counter < actors.size() + 1)
                return actors.get(counter - 1);
            return null;
        }
    }

Also, workers are setup to continously search for new actors:

    private void setupWorkers() {
        // Add actor thread: Consume the working queue and add the actor into
        // the render inside the EDT thread
        final AddActorRunnable adderRunnable = new AddActorRunnable();
        adderRunnable.setRenderer(panel3d);
        new Thread() {
            public void run() {
                while (true) {
                    try {
                        adderRunnable.setActor(exec.take().get());
                        SwingUtilities.invokeAndWait(adderRunnable);
                        panel3d.repaint();
                    } catch (InterruptedException e) {
                        return;
                    } catch (ExecutionException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    }
                }
            };
        }.start();
    }


Here is the test class I use:

public class TestVtkPanel {
    public VtkModel model;

    public TestVtkPanel() {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                model = getModel();
                VtkPanel panel = new VtkPanel();
                model.addPropertyChangeListener(panel);

                JButton exitBtn = new JButton("Quitter");
                exitBtn.addActionListener(new ActionListener() {

                    public void actionPerformed(ActionEvent e) {
                        System.exit(0);
                    }
                });
                JFrame f = new JFrame("Vtk Viewer");
                f.getContentPane().setLayout(new BorderLayout());
                f.getContentPane().add(panel, BorderLayout.CENTER);
                f.getContentPane().add(exitBtn, BorderLayout.SOUTH);

                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.setSize(800, 600);
                f.setVisible(true);
                f.validate();

                panel.startWorking(model);

                new Thread(new Runnable() {
                    public void run() {
                        updateModel();
                    }
                }).start();

            }
        });

    }   
   

    ...
  }
   
   
   
All this stuff works fine, but few questions remains.

Is this way to do thing is the best for what I'm trying to achieve ? If a vtk guru can give a look to my code, it would be gratefully appreciated. Furthermore inside the VtkPanel constructor I tried to put the vtkPanel panel3d outside of the Timer but that do not work.

    new Timer(1000, new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                if (nbSeconds++ < 1) {
                    panel3d.resetCamera();
                }
                // Run GC in local thread (EDT)
            ...
     }
    
I can't figure out why. Any hint on this point may help me to understand multithreading.

Thanks for your help.

jMax

_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Please keep messages on-topic and check the VTK FAQ at: http://www.vtk.org/Wiki/VTK_FAQ

Search the list archives at: http://markmail.org/search/?q=vtkusers

Follow this link to subscribe/unsubscribe:
https://vtk.org/mailman/listinfo/vtkusers
Reply | Threaded
Open this post in threaded view
|

Re: Java multi-thread and model Observer

VTK - Users mailing list
Hi Jean-Max,

I'm not sure to follow all the details of your implementation or why you still have the use of a Timer.
The only things that you need to worry about is that any rendering action (addActor/removeActor, update when actor connected, render) MUST BE in the EDT.

HTH,

Seb

On Thu, Feb 21, 2019 at 2:19 AM Jean-Max Redonnet <[hidden email]> wrote:
Hello everyone !

I'm using vtk throught its java wrapper and I'm setting up a versatile viewer that can display an existing model and update display when this model is updated (and it will be continously updated).

My Model is built around few classes: VtkObject that is the ancestor of many other classes like VtkSurface, VtkCurve, etc... and VtkModel that basically contains a list of VtkObjects and maintain Listeners. All these classes are of my own (please note uppercase "V" on VtkObject)


public class VtkObject{
    protected final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
    protected List<vtkActor> actors = new ArrayList<vtkActor>();
    ...
}

public class VtkSurface extends VtkObject {
    private vtkActor surfActor;
    ...
}

public class VtkModel implements PropertyChangeListener{
    protected List<VtkObject> objects;
    protected PropertyChangeSupport support;
    ...
}

For the viewer itself I wrote a VtkPanel that is mostly inspired by the example provided by Sébastien Jourdain (https://github.com/Kitware/VTK/blob/master/Wrapping/Java/vtk/sample/Demo.java)

I just make this panel model-aware implementing PropertyChangeListener:

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        if (evt.getPropertyName() == "AddedObject") {
            System.out.println("Added Object");
            VtkObject o = (VtkObject) evt.getNewValue();
            if(o.getActors().size()>0)
                exec.submit(new PipelineBuilder(o));
        }
        if (evt.getPropertyName() == "UpdatedObject") {
            System.out.println("Updated Object");
            VtkObject o = (VtkObject) evt.getNewValue();
            if(o.getActors().size()>0)
                exec.submit(new PipelineBuilder(o));
        }
    }

and slithly modify PipelineBuilder to make it able to manage VtkObjects that may contain several vtkActors

    public class PipelineBuilder implements Callable<vtkActor> {
        private int counter;
        private List<vtkActor> actors;

        public PipelineBuilder(VtkObject o) {
            actors = o.getActors();
            counter = 0;
        }

        @Override
        public vtkActor call() throws Exception {
            counter++;
            if (counter < actors.size() + 1)
                return actors.get(counter - 1);
            return null;
        }
    }

Also, workers are setup to continously search for new actors:

    private void setupWorkers() {
        // Add actor thread: Consume the working queue and add the actor into
        // the render inside the EDT thread
        final AddActorRunnable adderRunnable = new AddActorRunnable();
        adderRunnable.setRenderer(panel3d);
        new Thread() {
            public void run() {
                while (true) {
                    try {
                        adderRunnable.setActor(exec.take().get());
                        SwingUtilities.invokeAndWait(adderRunnable);
                        panel3d.repaint();
                    } catch (InterruptedException e) {
                        return;
                    } catch (ExecutionException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    }
                }
            };
        }.start();
    }


Here is the test class I use:

public class TestVtkPanel {
    public VtkModel model;

    public TestVtkPanel() {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                model = getModel();
                VtkPanel panel = new VtkPanel();
                model.addPropertyChangeListener(panel);

                JButton exitBtn = new JButton("Quitter");
                exitBtn.addActionListener(new ActionListener() {

                    public void actionPerformed(ActionEvent e) {
                        System.exit(0);
                    }
                });
                JFrame f = new JFrame("Vtk Viewer");
                f.getContentPane().setLayout(new BorderLayout());
                f.getContentPane().add(panel, BorderLayout.CENTER);
                f.getContentPane().add(exitBtn, BorderLayout.SOUTH);

                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.setSize(800, 600);
                f.setVisible(true);
                f.validate();

                panel.startWorking(model);

                new Thread(new Runnable() {
                    public void run() {
                        updateModel();
                    }
                }).start();

            }
        });

    }   
   

    ...
  }
   
   
   
All this stuff works fine, but few questions remains.

Is this way to do thing is the best for what I'm trying to achieve ? If a vtk guru can give a look to my code, it would be gratefully appreciated. Furthermore inside the VtkPanel constructor I tried to put the vtkPanel panel3d outside of the Timer but that do not work.

    new Timer(1000, new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                if (nbSeconds++ < 1) {
                    panel3d.resetCamera();
                }
                // Run GC in local thread (EDT)
            ...
     }
    
I can't figure out why. Any hint on this point may help me to understand multithreading.

Thanks for your help.

jMax
_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Please keep messages on-topic and check the VTK FAQ at: http://www.vtk.org/Wiki/VTK_FAQ

Search the list archives at: http://markmail.org/search/?q=vtkusers

Follow this link to subscribe/unsubscribe:
https://vtk.org/mailman/listinfo/vtkusers

_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Please keep messages on-topic and check the VTK FAQ at: http://www.vtk.org/Wiki/VTK_FAQ

Search the list archives at: http://markmail.org/search/?q=vtkusers

Follow this link to subscribe/unsubscribe:
https://vtk.org/mailman/listinfo/vtkusers
Reply | Threaded
Open this post in threaded view
|

Re: Java multi-thread and model Observer

Jean-Max Redonnet
Hi Sébastien,

Thanks for your response.

Actually, I don't understand why I still have the use of a Timer, neither. But the point is that if I put the panel3d.resetCamera() command outside the Timer, it doesn't work :-(.

Hope I can figure out why soon and any hint on this purpose will be really appreciated.

Anyway thanks again for your time.

jMax




Le ven. 22 févr. 2019 à 19:09, Sebastien Jourdain <[hidden email]> a écrit :
Hi Jean-Max,

I'm not sure to follow all the details of your implementation or why you still have the use of a Timer.
The only things that you need to worry about is that any rendering action (addActor/removeActor, update when actor connected, render) MUST BE in the EDT.

HTH,

Seb

On Thu, Feb 21, 2019 at 2:19 AM Jean-Max Redonnet <[hidden email]> wrote:
Hello everyone !

I'm using vtk throught its java wrapper and I'm setting up a versatile viewer that can display an existing model and update display when this model is updated (and it will be continously updated).

My Model is built around few classes: VtkObject that is the ancestor of many other classes like VtkSurface, VtkCurve, etc... and VtkModel that basically contains a list of VtkObjects and maintain Listeners. All these classes are of my own (please note uppercase "V" on VtkObject)


public class VtkObject{
    protected final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
    protected List<vtkActor> actors = new ArrayList<vtkActor>();
    ...
}

public class VtkSurface extends VtkObject {
    private vtkActor surfActor;
    ...
}

public class VtkModel implements PropertyChangeListener{
    protected List<VtkObject> objects;
    protected PropertyChangeSupport support;
    ...
}

For the viewer itself I wrote a VtkPanel that is mostly inspired by the example provided by Sébastien Jourdain (https://github.com/Kitware/VTK/blob/master/Wrapping/Java/vtk/sample/Demo.java)

I just make this panel model-aware implementing PropertyChangeListener:

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        if (evt.getPropertyName() == "AddedObject") {
            System.out.println("Added Object");
            VtkObject o = (VtkObject) evt.getNewValue();
            if(o.getActors().size()>0)
                exec.submit(new PipelineBuilder(o));
        }
        if (evt.getPropertyName() == "UpdatedObject") {
            System.out.println("Updated Object");
            VtkObject o = (VtkObject) evt.getNewValue();
            if(o.getActors().size()>0)
                exec.submit(new PipelineBuilder(o));
        }
    }

and slithly modify PipelineBuilder to make it able to manage VtkObjects that may contain several vtkActors

    public class PipelineBuilder implements Callable<vtkActor> {
        private int counter;
        private List<vtkActor> actors;

        public PipelineBuilder(VtkObject o) {
            actors = o.getActors();
            counter = 0;
        }

        @Override
        public vtkActor call() throws Exception {
            counter++;
            if (counter < actors.size() + 1)
                return actors.get(counter - 1);
            return null;
        }
    }

Also, workers are setup to continously search for new actors:

    private void setupWorkers() {
        // Add actor thread: Consume the working queue and add the actor into
        // the render inside the EDT thread
        final AddActorRunnable adderRunnable = new AddActorRunnable();
        adderRunnable.setRenderer(panel3d);
        new Thread() {
            public void run() {
                while (true) {
                    try {
                        adderRunnable.setActor(exec.take().get());
                        SwingUtilities.invokeAndWait(adderRunnable);
                        panel3d.repaint();
                    } catch (InterruptedException e) {
                        return;
                    } catch (ExecutionException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    }
                }
            };
        }.start();
    }


Here is the test class I use:

public class TestVtkPanel {
    public VtkModel model;

    public TestVtkPanel() {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                model = getModel();
                VtkPanel panel = new VtkPanel();
                model.addPropertyChangeListener(panel);

                JButton exitBtn = new JButton("Quitter");
                exitBtn.addActionListener(new ActionListener() {

                    public void actionPerformed(ActionEvent e) {
                        System.exit(0);
                    }
                });
                JFrame f = new JFrame("Vtk Viewer");
                f.getContentPane().setLayout(new BorderLayout());
                f.getContentPane().add(panel, BorderLayout.CENTER);
                f.getContentPane().add(exitBtn, BorderLayout.SOUTH);

                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.setSize(800, 600);
                f.setVisible(true);
                f.validate();

                panel.startWorking(model);

                new Thread(new Runnable() {
                    public void run() {
                        updateModel();
                    }
                }).start();

            }
        });

    }   
   

    ...
  }
   
   
   
All this stuff works fine, but few questions remains.

Is this way to do thing is the best for what I'm trying to achieve ? If a vtk guru can give a look to my code, it would be gratefully appreciated. Furthermore inside the VtkPanel constructor I tried to put the vtkPanel panel3d outside of the Timer but that do not work.

    new Timer(1000, new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                if (nbSeconds++ < 1) {
                    panel3d.resetCamera();
                }
                // Run GC in local thread (EDT)
            ...
     }
    
I can't figure out why. Any hint on this point may help me to understand multithreading.

Thanks for your help.

jMax
_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Please keep messages on-topic and check the VTK FAQ at: http://www.vtk.org/Wiki/VTK_FAQ

Search the list archives at: http://markmail.org/search/?q=vtkusers

Follow this link to subscribe/unsubscribe:
https://vtk.org/mailman/listinfo/vtkusers

_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Please keep messages on-topic and check the VTK FAQ at: http://www.vtk.org/Wiki/VTK_FAQ

Search the list archives at: http://markmail.org/search/?q=vtkusers

Follow this link to subscribe/unsubscribe:
https://vtk.org/mailman/listinfo/vtkusers
Reply | Threaded
Open this post in threaded view
|

Re: Java multi-thread and model Observer

VTK - Users mailing list
You can do it via an invokeLater or anything that will schedule the execution in the EDT.

On Mon, Mar 4, 2019 at 7:02 AM Jean-Max Redonnet <[hidden email]> wrote:
Hi Sébastien,

Thanks for your response.

Actually, I don't understand why I still have the use of a Timer, neither. But the point is that if I put the panel3d.resetCamera() command outside the Timer, it doesn't work :-(.

Hope I can figure out why soon and any hint on this purpose will be really appreciated.

Anyway thanks again for your time.

jMax




Le ven. 22 févr. 2019 à 19:09, Sebastien Jourdain <[hidden email]> a écrit :
Hi Jean-Max,

I'm not sure to follow all the details of your implementation or why you still have the use of a Timer.
The only things that you need to worry about is that any rendering action (addActor/removeActor, update when actor connected, render) MUST BE in the EDT.

HTH,

Seb

On Thu, Feb 21, 2019 at 2:19 AM Jean-Max Redonnet <[hidden email]> wrote:
Hello everyone !

I'm using vtk throught its java wrapper and I'm setting up a versatile viewer that can display an existing model and update display when this model is updated (and it will be continously updated).

My Model is built around few classes: VtkObject that is the ancestor of many other classes like VtkSurface, VtkCurve, etc... and VtkModel that basically contains a list of VtkObjects and maintain Listeners. All these classes are of my own (please note uppercase "V" on VtkObject)


public class VtkObject{
    protected final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
    protected List<vtkActor> actors = new ArrayList<vtkActor>();
    ...
}

public class VtkSurface extends VtkObject {
    private vtkActor surfActor;
    ...
}

public class VtkModel implements PropertyChangeListener{
    protected List<VtkObject> objects;
    protected PropertyChangeSupport support;
    ...
}

For the viewer itself I wrote a VtkPanel that is mostly inspired by the example provided by Sébastien Jourdain (https://github.com/Kitware/VTK/blob/master/Wrapping/Java/vtk/sample/Demo.java)

I just make this panel model-aware implementing PropertyChangeListener:

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        if (evt.getPropertyName() == "AddedObject") {
            System.out.println("Added Object");
            VtkObject o = (VtkObject) evt.getNewValue();
            if(o.getActors().size()>0)
                exec.submit(new PipelineBuilder(o));
        }
        if (evt.getPropertyName() == "UpdatedObject") {
            System.out.println("Updated Object");
            VtkObject o = (VtkObject) evt.getNewValue();
            if(o.getActors().size()>0)
                exec.submit(new PipelineBuilder(o));
        }
    }

and slithly modify PipelineBuilder to make it able to manage VtkObjects that may contain several vtkActors

    public class PipelineBuilder implements Callable<vtkActor> {
        private int counter;
        private List<vtkActor> actors;

        public PipelineBuilder(VtkObject o) {
            actors = o.getActors();
            counter = 0;
        }

        @Override
        public vtkActor call() throws Exception {
            counter++;
            if (counter < actors.size() + 1)
                return actors.get(counter - 1);
            return null;
        }
    }

Also, workers are setup to continously search for new actors:

    private void setupWorkers() {
        // Add actor thread: Consume the working queue and add the actor into
        // the render inside the EDT thread
        final AddActorRunnable adderRunnable = new AddActorRunnable();
        adderRunnable.setRenderer(panel3d);
        new Thread() {
            public void run() {
                while (true) {
                    try {
                        adderRunnable.setActor(exec.take().get());
                        SwingUtilities.invokeAndWait(adderRunnable);
                        panel3d.repaint();
                    } catch (InterruptedException e) {
                        return;
                    } catch (ExecutionException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    }
                }
            };
        }.start();
    }


Here is the test class I use:

public class TestVtkPanel {
    public VtkModel model;

    public TestVtkPanel() {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                model = getModel();
                VtkPanel panel = new VtkPanel();
                model.addPropertyChangeListener(panel);

                JButton exitBtn = new JButton("Quitter");
                exitBtn.addActionListener(new ActionListener() {

                    public void actionPerformed(ActionEvent e) {
                        System.exit(0);
                    }
                });
                JFrame f = new JFrame("Vtk Viewer");
                f.getContentPane().setLayout(new BorderLayout());
                f.getContentPane().add(panel, BorderLayout.CENTER);
                f.getContentPane().add(exitBtn, BorderLayout.SOUTH);

                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.setSize(800, 600);
                f.setVisible(true);
                f.validate();

                panel.startWorking(model);

                new Thread(new Runnable() {
                    public void run() {
                        updateModel();
                    }
                }).start();

            }
        });

    }   
   

    ...
  }
   
   
   
All this stuff works fine, but few questions remains.

Is this way to do thing is the best for what I'm trying to achieve ? If a vtk guru can give a look to my code, it would be gratefully appreciated. Furthermore inside the VtkPanel constructor I tried to put the vtkPanel panel3d outside of the Timer but that do not work.

    new Timer(1000, new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                if (nbSeconds++ < 1) {
                    panel3d.resetCamera();
                }
                // Run GC in local thread (EDT)
            ...
     }
    
I can't figure out why. Any hint on this point may help me to understand multithreading.

Thanks for your help.

jMax
_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Please keep messages on-topic and check the VTK FAQ at: http://www.vtk.org/Wiki/VTK_FAQ

Search the list archives at: http://markmail.org/search/?q=vtkusers

Follow this link to subscribe/unsubscribe:
https://vtk.org/mailman/listinfo/vtkusers

_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Please keep messages on-topic and check the VTK FAQ at: http://www.vtk.org/Wiki/VTK_FAQ

Search the list archives at: http://markmail.org/search/?q=vtkusers

Follow this link to subscribe/unsubscribe:
https://vtk.org/mailman/listinfo/vtkusers