blob: bed869c53a3ead9c089ca835c2e26c744f94d6c2 [file] [log] [blame]
<!doctype html>
<html class="no-js" lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>Writing POV-Ray Support for NetBeans VII—Support For Running POV-Ray</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Writing POV-Ray Support for NetBeans VII—Support For Running POV-Ray - Apache NetBeans">
<meta name="author" content="Apache NetBeans">
<meta name="description" content="Writing POV-Ray Support for NetBeans VII—Support For Running POV-Ray - Apache NetBeans">
<meta name="keywords" content="Apache NetBeans Platform, Platform Tutorials, Writing POV-Ray Support for NetBeans VII—Support For Running POV-Ray">
<meta name="generator" content="Apache NetBeans">
<link rel="stylesheet" href="../../../../_/css/font-awesome.min.css">
<link rel="alternate" type="application/atom+xml" title="Apache NetBeans Blog" href="https://netbeans.apache.org/blogs/atom" />
<link rel="stylesheet" href="../../../../_/css/highlightjs/default.min.css">
<link rel="stylesheet" href="../../../../_/css/netbeans.css">
<link rel="apple-touch-icon" sizes="180x180" href="../../../../_/images/fav/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="../../../../_/images/fav/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="../../../../_/images/fav/favicon-16x16.png">
<link rel="manifest" href="../../../../_/images/fav/site.webmanifest">
<link rel="mask-icon" href="../../../../_/images/fav/safari-pinned-tab.svg" color="#5bbad5">
<meta name="msapplication-TileColor" content="#ffc40d">
<meta name="theme-color" content="#ffffff">
<link href="../../../../_/css/font-open-sans.css" rel="stylesheet">
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
</head>
<body>
<div class="title-bar" data-responsive-toggle="responsive-menu" data-hide-for="medium">
<button type="button" data-toggle="responsive-menu"><i style='font-size: 32px; color: #fff; padding: 8px' class='fa fa-bars'></i></button>
<div class="title-bar-title">Apache NetBeans</div>
</div>
<div class="top-bar" id="responsive-menu">
<div class='top-bar-left'>
<a class='title' href="../../../../index.html"><img src='../../../../_/images/apache-netbeans.svg' style='padding: 8px; height: 48px;'> Apache NetBeans</a>
</div>
<div class="top-bar-right">
<ul class="vertical medium-horizontal menu" data-responsive-menu="drilldown medium-dropdown">
<li> <input id="search-input" type="text" placeholder="Search the docs"> </li>
<li> <a href="../../../../front/main/community">Community</a> </li>
<li> <a href="../../../../front/main/participate">Participate</a> </li>
<li> <a href="../../../../front/main/blogs">Blog</a></li>
<li> <a href="../../../../front/main/help">Get Help</a> </li>
<li> <a href="https://plugins.netbeans.apache.org/">Plugins</a> </li>
<li> <a href="../../../../front/main/download">Download</a> </li>
</ul>
</div>
</div>
<!-- src/templates/news -->
<section class="hero news alternate">
<div class='grid-container'>
<div class='cell'>
<div class="annotation">Latest release</div>
<h1>Apache NetBeans 28</h1>
<p><a class="button success" href="../../../../front/main/download/nb28">Download</a></p>
</div>
</div>
</section>
<div class='grid-container main-content tutorial'>
<h1 class="sect0">Writing POV-Ray Support for NetBeans VII—Support For Running POV-Ray</h1>
<div class="sectionbody">
<div class="admonitionblock note">
<table>
<tbody><tr>
<td class="icon"><i class="fa icon-note" title="Note"></i></td>
<td class="content">This tutorial needs a review.
You can <a href="https://github.com/apache/netbeans-antora-tutorials/edit/main/modules/ROOT/pages/tutorials/nbm-povray-7.adoc" title="Edit this tutorial in github">edit it in GitHub </a>
following these <a href="../../../../tutorial/main/kb/docs/contributing">contribution guidelines.</a></td>
</tr></tbody>
</table>
</div>
</div>
<div id="toc" class="toc">
<div id="toctitle"></div>
<ul class="sectlevel1">
<li><a href="#_obtaining_pov_ray">Obtaining POV-Ray</a></li>
<li><a href="#_executing_pov_ray_and_displaying_the_output">Executing POV-Ray and Displaying the Output</a></li>
<li><a href="#_next_steps">Next Steps</a></li>
</ul>
</div>
<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>This is a continuation of the tutorial for building a POV-Ray rendering application on the NetBeans Platform. If you have not read the <a href="../nbm-povray-1/" class="xref page">first</a>, <a href="../nbm-povray-2/" class="xref page">second</a>, <a href="../nbm-povray-3/" class="xref page">third</a>, <a href="../nbm-povray-4/" class="xref page">fourth</a>, <a href="../nbm-povray-5/" class="xref page">fifth</a>, and <a href="../nbm-povray-6/" class="xref page">sixth</a> parts of this tutorial, you may want to start there.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_obtaining_pov_ray"><a class="anchor" href="#_obtaining_pov_ray"></a>Obtaining POV-Ray</h2>
<div class="sectionbody">
<div class="paragraph">
<p>At this point, we&#8217;re almost ready to run code, so it would be a good idea to download a copy of POV-Ray.</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Official builds can be obtained from <a href="http://povray.org">povray.org</a>.</p>
</li>
<li>
<p>Macintosh users may find <a href="http://darwinports.opendarwin.org/">DarwinPorts</a> the easiest way—simply install DarwinPorts and then run <code>sudo port install povray</code>.</p>
</li>
<li>
<p>Linux and other Unix users should be fine with the downloads available from <a href="http://povray.org">povray.org</a>, using <a href="http://povray.org/download/linux.php">these instructions</a>. Everything should work out of the box for these users, without any tweaks or post-install configurations. Make sure, however, that the POV-Ray launcher has the correct permissions, otherwise it will not execute. Run it from the command line to check that it executes.</p>
</li>
</ul>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
For details on setting up POV-Ray, especially for detailed instructions for Windows, <a href="../nbm-povray-10/#appendix" class="xref page">see the Appendix</a>.
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_executing_pov_ray_and_displaying_the_output"><a class="anchor" href="#_executing_pov_ray_and_displaying_the_output"></a>Executing POV-Ray and Displaying the Output</h2>
<div class="sectionbody">
<div class="paragraph">
<p>At this point, we are ready to write the code that will actually invoke the external POV-Ray executable, pass it the correct arguments and display its output.</p>
</div>
<div class="paragraph">
<p>At the end of this part of the tutorial, you will have an application that looks like this (click to enlarge the image):</p>
</div>
<div class="openblock feature">
<div class="content">
<div class="imageblock xref-image left">
<div class="content">
<a class="image" href="../../_images/tutorials/povray_71_ch7_pic2.png"><img src="../../_images/tutorials/povray_71_ch7_pic2.png" alt="povray 71 ch7 pic2"></a>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>POV-Ray has two kinds of output: It will write out status and success failure on the command line, in a similar way to what a compiler does, and it will write out an image file on disk, which we will want to display.</p>
</div>
<div class="paragraph">
<p>The first part is just being able to invoke the external executable. NetBeans has some API classes that can help with that.</p>
</div>
<div class="olist arabic">
<ol class="arabic" start="1">
<li>
<p>Add the following constructor and fields to the <code>Povray</code> class:</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> private final RendererServiceImpl renderService;
private final FileObject toRender;
private final Properties settings;
Povray (RendererServiceImpl renderService, FileObject toRender, Properties settings) {
this.renderService = renderService;
this.toRender = toRender;
this.settings = settings == null ? renderService.getRendererSettings(
renderService.getPreferredRendererSettingsName()) : settings;
}</code></pre>
</div>
</div>
<div class="olist arabic">
<ol class="arabic" start="2">
<li>
<p>Next we will implement a method that will find the file to render. We were passed a <code>FileObject</code>, but now we need an actual <code>java.io.File</code> to get the path from, to pass on the command line to POV-Ray. There are two caveats: 1. The file passed to the constructor may be null—in that case we should find the main file of the project and use that; and 2. It is conceivable that the file will not exist on disk—NetBeans filesystems are virtual, after all, and the file could exist in a remote FTP filesystem or such. Since NetBeans 4.0, this is rather unlikely, but we should still test for this condition (<code>FileUtil.toFile()</code> returns null). So we will add a method to <code>Povray</code> as follows:</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">private File getFileToRender() throws IOException {
FileObject render = toRender;
if (render == null) {
PovrayProject proj = renderService.getProject();
MainFileProvider provider = (MainFileProvider)
proj.getLookup().lookup (MainFileProvider.class);
if (provider == null) {
throw new IllegalStateException ("Main file provider missing");
}
render = provider.getMainFile();
if (render == null) {
ProjectInformation info = (ProjectInformation)
proj.getLookup().lookup(ProjectInformation.class);
//XXX let the user choose
throw new IOException (NbBundle.getMessage(Povray.class,
"MSG_NoMainFile", info.getDisplayName()));
}
}
assert render != null;
File result = FileUtil.toFile (render);
if (result == null) {
throw new IOException (NbBundle.getMessage(Povray.class,
"MSG_VirtualFile", render.getName()));
}
assert result.exists();
assert result.isFile();
return result;
}</code></pre>
</div>
</div>
<div class="olist arabic">
<ol class="arabic" start="3">
<li>
<p>Next we need to assemble the command-line arguments that need to be passed to POV-Ray. These take the form of <code>+[some character][somevalue]</code>, for example, <code>+A0.9</code> sets the anti-aliasing parameter to 0.9 pixels. So we need to iterate the <code>Properties</code> object passed to the constructor and assemble from it a set of command line arguments:</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">private String getCmdLineArgs(File includesDir) {
StringBuilder cmdline = new StringBuilder();
for (Iterator i=settings.keySet().iterator(); i.hasNext();) {
String key = (String) i.next();
String val = settings.getProperty(key);
cmdline.append ('+');
cmdline.append (key);
cmdline.append (val);
cmdline.append (' ');
}
cmdline.append ("+L");
cmdline.append (includesDir.getPath());
return cmdline.toString();
}</code></pre>
</div>
</div>
<div class="olist arabic">
<ol class="arabic" start="4">
<li>
<p>Next we need to implement a couple of utility methods that the rendering method will use:</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">private File getImagesDir() {
PovrayProject proj = renderService.getProject();
FileObject fob = proj.getImagesFolder(true);
File result = FileUtil.toFile(fob);
assert result != null &amp;amp;&amp;amp; result.exists();
return result;
}
private String stripExtension(File f) {
String sceneName = f.getName();
int endIndex;
if ((endIndex = sceneName.lastIndexOf('.')) != -1) {
sceneName = sceneName.substring(0, endIndex);
}
return sceneName;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Neither is terribly exciting—one gets the images directory from the project as a <code>java.io.File</code>, and the other trims the file extension off a file name (so we can create an image file with the same name as the scene file).</p>
</div>
<div class="olist arabic">
<ol class="arabic" start="5">
<li>
<p>The next method we will add is another utility method. When we render, we will want to show messages on the status bar that describe what is happening—or what went wrong in the event of failure. The UI Utilities API contains a class called <code>StatusDisplayer</code> that lets any code in NetBeans that wants to write to the status bar (the actual implementation of <code>StatusDisplayer</code> is in the windowing system implementations, <code>core/windows</code> in NetBeans CVS).</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>Implement the following method, and then add a dependency on the UI Utilities API module from the Povray Projects module:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">private void showMsg (String msg) {
StatusDisplayer.getDefault().setStatusText(msg);
}</code></pre>
</div>
</div>
<div class="olist arabic">
<ol class="arabic" start="6">
<li>
<p>At this point, we&#8217;ve added a bunch of status messages our code can display, so it is time to add actual text for those messages to the resource bundle. Note that in a number of cases we call:</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">NbBundle.getMessage(SomeClass.class, "MSG_Something", _[.underline]#someStringArgument#_);</code></pre>
</div>
</div>
<div class="paragraph">
<p>to fetch a localized string. <code>NbBundle</code> supports embedding arguments inside of a localized string—you can either use the above method, or a variant that takes an array of arguments to embed. So you can define strings in a resource bundle using the syntax:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">Could not delete {0} because {1}</code></pre>
</div>
</div>
<div class="paragraph">
<p>and <code>{0}</code> and <code>{1}</code> will be replaced by arguments passed to <code>getMessage()</code>. This is extremely useful, as often the order in which such strings occur in the result text will be different in different human languages.</p>
</div>
<div class="paragraph">
<p>So let&#8217;s go ahead and add the warning messages we need to <code>Bundle.properties</code> in the same package as <code>PovrayProject</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">MSG_NoMainFile=Main scene file not set for {0}
MSG_VirtualFile=Not a file on disk: {0}
MSG_Rendering=Rendering {0}
MSG_NoPovrayExe=No POV-Ray executable, cannot render
MSG_NoPovrayInc=No POV-Ray includes dir, cannot render
MSG_Success=Rendered {0} successfully
MSG_Failure=Failed to render {0}
MSG_CantDelete=Could not delete {0}, it is locked or in use</code></pre>
</div>
</div>
<div class="olist arabic">
<ol class="arabic" start="7">
<li>
<p>Now we are almost ready to get down to the nitty-gritty of actually invoking POV-Ray from NetBeans. We will do this in the standard Java way, using <code>Runtime.exec()</code> to start an external process. We also will want to display the text output from the process as it reports its progress, in the output window. This means we will need a way to write to the output window. So we will add one more dependency to Povray Projects—add a dependency on the IO API module (use the class name <code>InputOutput</code> in the Add Dependency dialog).</p>
</li>
</ol>
</div>
<div class="olist arabic">
<ol class="arabic" start="8">
<li>
<p>Handling output from a process is tricky—we will actually have three threads running to handle our process:</p>
<div class="ulist">
<ul>
<li>
<p>The thread that invoked the process and is waiting for it to terminate</p>
</li>
<li>
<p>A thread that is collecting output from the standard output of the POV-Ray process and writing it to the output window</p>
</li>
<li>
<p>Another thread that is doing the same thing for the error output of the POV-Ray process</p>
</li>
</ul>
</div>
</li>
</ol>
</div>
<div class="paragraph">
<p>So we will need some kind of <code>Runnable</code> which will wait for data from each output stream and route it to the output window in NetBeans as it becomes available. Writing to the output window is quite easy—you get an <code>InputOutput</code> object from <code>IOProvider.getDefault()</code> and then write to one of its streams—for example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> InputOutput io = IOProvider.getDefault().getIO ("Hello", true);
io.select();
io.getOut().println ("Hello world");
io.getErr().println ("This is the standard error output—it should be red");</code></pre>
</div>
</div>
<div class="paragraph">
<p>is all it takes to make the output window pop up and display some output.</p>
</div>
<div class="paragraph">
<p>So before we implement the code that will create the process, lets create the runnable that will wait for output from the process and route it to the output window—it will be a static nested class inside the <code>Povray</code> class:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> static class OutHandler implements Runnable {
private Reader out;
private OutputWriter writer;
public OutHandler (Reader out, OutputWriter writer) {
this.out = out;
this.writer = writer;
}
@Override
public void run() {
while (true) {
try {
while (!out.ready()) {
try {
Thread.currentThread().sleep(200);
} catch (InterruptedException e) {
close();
return;
}
}
if (!readOneBuffer() || Thread.currentThread().isInterrupted()) {
close();
return;
}
} catch (IOException ioe) {
//Stream already closed, this is fine
return;
}
}
}
private boolean readOneBuffer() throws IOException {
char[] cbuf = new char[255];
int read;
while ((read = out.read(cbuf)) != -1) {
writer.write(cbuf, 0, read);
}
return read != -1;
}
private void close() {
try {
out.close();
} catch (IOException ioe) {
Exceptions.printStackTrace(ioe);
} finally {
writer.close();
}
}
}</code></pre>
</div>
</div>
<div class="olist arabic">
<ol class="arabic" start="9">
<li>
<p>Now we are ready to implement the <code>render()</code> method in the <code>Povray</code> class, in the Povray Project module, that will invoke <code>POV-Ray</code>. This method should be never be invoked from the event thread, because it would block the UI until POV-Ray is finished. So the first thing we do is sanity check what thread we&#8217;re running on. Then we get the file we need to render, sanity checking that. Then we call <code>getPovray()</code> which may open a file chooser to let the user pick it, and similarly get the default include directory which we will need to pass on the command line. Then we get the directory where we will put the output, assemble our output file name (we use PNG format since NetBeans' Image module supports that).</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>Then we compute the command line that should be passed to POV-Ray. Then we call <code>Runtime.exec()</code> with that argument, wire up the output window to the output streams from the resulting process, and wait for the process to exit. Once it exits, we determine if it succeeded or failed, show an appropriate message, and if it succeeded, return a <code>FileObject</code> representing the file that was created.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">public FileObject render () throws IOException {
if (EventQueue.isDispatchThread()) {
throw new IllegalStateException ("Tried to run povray from the " +
"event thread");
}
//Find the scene file pass to POV-Ray as a java.io.File
File scene;
try {
scene = getFileToRender();
} catch (IOException ioe) {
showMsg (ioe.getMessage());
return null;
}
//Get the POV-Ray executable
File povray = getPovray();
if (povray == null) {
//The user cancelled the file chooser w/o selecting
showMsg(NbBundle.getMessage(Povray.class, "MSG_NoPovrayExe"));
return null;
}
//Get the include dir, if it isn't under povray's home dir
File includesDir = getStandardIncludeDir(povray);
if (includesDir == null) {
//The user cancelled the file chooser w/o selecting
showMsg (NbBundle.getMessage(Povray.class, "MSG_NoPovrayInc"));
return null;
}
//Find the image output directory for the project
File imagesDir = getImagesDir();
//Assemble and format the line switches for the POV-Ray process based
//on the contents of the Properties object
String args = getCmdLineArgs(includesDir);
String outFileName = stripExtension (scene) + ".png";
//Compute the name of the output image file
File outFile = new File(imagesDir.getPath() + File.separator +
outFileName);
//Delete the image if it exists, so that any current tab viewing the file is
//closed and the file will definitely be re-read when it is re-opened
if (outFile.exists() &amp;amp;&amp;amp; !outFile.delete()) {
showMsg (NbBundle.getMessage(Povray.class,
"LBL_CantDelete", outFile.getName()));
return null;
}
//Append the input file and output file arguments to the command line
String cmdline = povray.getPath() + ' ' + args + " +I" +
scene.getPath() + " +O" + outFile.getPath();
System.err.println(cmdline);
showMsg (NbBundle.getMessage(Povray.class, "MSG_Rendering",
scene.getName()));
final Process process = Runtime.getRuntime().exec (cmdline);
//Get the standard out of the process
InputStream out = new BufferedInputStream (process.getInputStream(), 8192);
//Get the standard in of the process
InputStream err = new BufferedInputStream (process.getErrorStream(), 8192);
//Create readers for each
final Reader outReader = new BufferedReader (new InputStreamReader (out));
final Reader errReader = new BufferedReader (new InputStreamReader (err));
//Get an InputOutput to write to the output window
InputOutput io = IOProvider.getDefault().getIO(scene.getName(), false);
//Force it to open the output window/activate our tab
io.select();
//Print the command line we're calling for debug purposes
io.getOut().println(cmdline);
//Create runnables to poll each output stream
OutHandler processSystemOut = new OutHandler (outReader, io.getOut());
OutHandler processSystemErr = new OutHandler (errReader, io.getErr());
//Get two different threads listening on the output &amp;amp; err
//using the system-wide thread pool
RequestProcessor.getDefault().post(processSystemOut);
RequestProcessor.getDefault().post(processSystemErr);
try {
//Hang this thread until the process exits
process.waitFor();
} catch (InterruptedException ex) {
Exceptions.printStackTrace(ex);
}
//Close the output window's streams (title will become non-bold)
processSystemOut.close();
processSystemErr.close();
if (outFile.exists() &amp;amp;&amp;amp; process.exitValue() == 0) {
//Try to find the new image file
FileObject outFileObject = FileUtil.toFileObject(outFile);
showMsg (NbBundle.getMessage(Povray.class, "MSG_Success",
outFile.getPath()));
return outFileObject;
} else {
showMsg (NbBundle.getMessage(Povray.class, "MSG_Failure",
scene.getPath()));
return null;
}
}</code></pre>
</div>
</div>
<div class="olist arabic">
<ol class="arabic" start="10">
<li>
<p>The last thing is to fix our implementation of <code>RendererService</code> to call <code>Povray.render()</code>. Open <code>RendererServiceImpl</code> in the code editor, and modify the render method:</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@Override
public FileObject render(FileObject scene, Properties renderSettings) {
Povray pov = new Povray (this, scene, renderSettings);
try {
return pov.render();
} catch (IOException ioe) {
Exceptions.printStackTrace(ioe);
return null;
}
}</code></pre>
</div>
</div>
<div class="olist arabic">
<ol class="arabic" start="11">
<li>
<p>The last step is to open the image when the rendering process is complete. This is quite simple to implement—we just need to look for an <code>OpenCookie</code> on the <code>Node</code> for the image that was rendered. If you are running a standard configuration of the NetBeans IDE, you already have the Image module installed—it will provide support for opening an image, displaying it in the editor area. So implement <code>RendererAction.RenderWithSettingsAction.run()</code> like this:</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">public void run() {
DataObject ob = node.getDataObject();
FileObject toRender = ob.getPrimaryFile();
*Properties mySettings = renderer.getRendererSettings(name);*
FileObject image = renderer.render(toRender, *mySettings*);
if (image != null) {
try {
DataObject dob = DataObject.find (image);
Node n = dob.getNodeDelegate();
OpenCookie ck = (OpenCookie) n.getLookup().lookup(OpenCookie.class);
if (ck != null) {
ck.open();
}
} catch (DataObjectNotFoundException e) {
//Should never happen
Exceptions.printStackTrace(e);
}
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>With that, you should be able to clean, build and run the application and be able to run POV-Ray and generate an image in the <code>images/</code> subdirectory of your project:</p>
</div>
<div class="openblock feature">
<div class="content">
<div class="imageblock xref-image left">
<div class="content">
<a class="image" href="../../_images/tutorials/povray_71_ch7_pic2.png"><img src="../../_images/tutorials/povray_71_ch7_pic2.png" alt="povray 71 ch7 pic2"></a>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_next_steps"><a class="anchor" href="#_next_steps"></a>Next Steps</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The <a href="../nbm-povray-8/" class="xref page">next section</a> will cover implementing <code>ViewService</code> and adding actions for that.</p>
</div>
</div>
</div>
<section class='tools'>
<ul class="menu align-center">
<li><a title="Facebook" href="https://www.facebook.com/NetBeans"><i class="fa fa-md fa-facebook"></i></a></li>
<li><a title="Twitter" href="https://twitter.com/netbeans"><i class="fa fa-md fa-twitter"></i></a></li>
<li><a title="Github" href="https://github.com/apache/netbeans"><i class="fa fa-md fa-github"></i></a></li>
<li><a title="YouTube" href="https://www.youtube.com/user/netbeansvideos"><i class="fa fa-md fa-youtube"></i></a></li>
<li><a title="Atom Feed" href="https://netbeans.apache.org/blogs/atom"><i class="fa fa-mf fa-rss"></i></a></li>
<li><a title="Slack" href="https://tinyurl.com/netbeans-slack-signup/"><i class="fa fa-md fa-slack"></i></a></li>
<li><a title="Issues" href="https://github.com/apache/netbeans/issues"><i class="fa fa-mf fa-bug"></i></a></li>
</ul>
<ul class="menu align-center">
<li><a href="https://github.com/apache/netbeans-antora-tutorials/edit/main/modules/ROOT/pages/tutorials/nbm-povray-7.adoc" title="See this page in github"><i class="fa fa-md fa-edit"></i> See this page in GitHub.</a></li>
</ul>
</section>
</div>
<div class='grid-container incubator-area' style='margin-top: 64px'>
<div class='grid-x grid-padding-x'>
<div class='large-auto cell text-center'>
<a href="https://www.apache.org/">
<img style="height: 60px" title="Apache Software Foundation" src="../../../../_/images/asf_logo_wide.svg" />
</a>
</div>
<div class='large-auto cell text-center'>
<a href="https://www.apache.org/events/current-event.html">
<img style="width:234px; height: 60px;" title="Apache Software Foundation current event" src="https://www.apache.org/events/current-event-234x60.png"/>
</a>
</div>
</div>
</div>
<footer>
<div class="grid-container">
<div class="grid-x grid-padding-x">
<div class="large-auto cell">
<h1><a href="../../../../front/main/about">About</a></h1>
<ul>
<li><a href="../../../../front/main/community/who">Who's Who</a></li>
<li><a href="https://www.apache.org/foundation/thanks.html">Thanks</a></li>
<li><a href="https://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li>
<li><a href="https://www.apache.org/security/">Security</a></li>
</ul>
</div>
<div class="large-auto cell">
<h1><a href="../../../../front/main/community">Community</a></h1>
<ul>
<li><a href="../../../../front/main/community/mailing-lists">Mailing lists</a></li>
<li><a href="../../../../front/main/community/committer">Becoming a committer</a></li>
<li><a href="../../../../front/main/community/events">NetBeans Events</a></li>
<li><a href="https://www.apache.org/events/current-event.html">Apache Events</a></li>
</ul>
</div>
<div class="large-auto cell">
<h1><a href="../../../../front/main/participate">Participate</a></h1>
<ul>
<li><a href="../../../../front/main/participate/submit-pr">Submitting Pull Requests</a></li>
<li><a href="../../../../front/main/participate/report-issue">Reporting Issues</a></li>
<li><a href="../../../../front/main/participate/#documentation">Improving the documentation</a></li>
</ul>
</div>
<div class="large-auto cell">
<h1><a href="../../../../front/main/help">Get Help</a></h1>
<ul>
<li><a href="../../../../front/main/help/#documentation">Documentation</a></li>
<li><a href="../../../../wiki/main/wiki">Wiki</a></li>
<li><a href="../../../../front/main/help/#support">Community Support</a></li>
<li><a href="../../../../front/main/help/commercial-support">Commercial Support</a></li>
</ul>
</div>
<div class="large-auto cell">
<h1><a href="../../../../front/main/download">Download</a></h1>
<ul>
<li><a href="../../../../front/main/download">Releases</a></li>
<li><a href="https://plugins.netbeans.apache.org/">Plugins</a></li>
<li><a href="../../../../front/main/download/#_daily_builds_and_building_from_source">Building from source</a></li>
<li><a href="../../../../front/main/download/#_older_releases">Previous releases</a></li>
</ul>
</div>
</div>
</div>
</footer>
<div class='footer-disclaimer'>
<div class="footer-disclaimer-content">
<p>Copyright &copy; 2017-2025 <a href="https://www.apache.org">The Apache Software Foundation</a>.</p>
<p>Licensed under the Apache <a href="https://www.apache.org/licenses/">license</a>, version 2.0</p>
<div style='max-width: 40em; margin: 0 auto'>
<p>Apache, Apache NetBeans, NetBeans, the Apache feather logo and the Apache NetBeans logo are trademarks of <a href="https://www.apache.org">The Apache Software Foundation</a>.</p>
<p>Oracle and Java are registered trademarks of Oracle and/or its affiliates.</p>
<p>The Apache NetBeans website conforms to the <a href="https://privacy.apache.org/policies/privacy-policy-public.html">Apache Software Foundation Privacy Policy</a></p>
</div>
</div>
</div>
<script src="../../../../_/js/vendor/lunr.js"></script>
<script src="../../../../_/js/search-ui.js" id="search-ui-script" data-site-root-path="../../../.." data-snippet-length="100" data-stylesheet="../../../../_/css/search.css"></script>
<script async src="../../../../search-index.js"></script>
<script src="../../../../_/js/vendor/jquery.min.js"></script>
<script src="../../../../_/js/vendor/what-input.min.js"></script>
<script src="../../../../_/js/vendor/foundation.min.js"></script>
<script src="../../../../_/js/vendor/jquery.colorbox-min.js"></script>
<script src="../../../../_/js/netbeans.js"></script>
<script>
$(function(){ $(document).foundation(); });
</script>
<script src="../../../../_/js/vendor/highlight.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', (event) => {
document.querySelectorAll('pre code').forEach((el) => {
hljs.highlightElement(el);
});
});
</script>
</body>
</html>