| <!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>NetBeans Visual Database Explorer Tutorial</title> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <meta name="description" content="NetBeans Visual Database Explorer Tutorial - Apache NetBeans"> |
| <meta name="author" content="Apache NetBeans"> |
| <meta name="description" content="NetBeans Visual Database Explorer Tutorial - Apache NetBeans"> |
| <meta name="keywords" content="Apache NetBeans Platform, Platform Tutorials, NetBeans Visual Database Explorer Tutorial"> |
| <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">NetBeans Visual Database Explorer Tutorial</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-visual_library2.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="#_setting_up_the_module">Setting Up the Module</a></li> |
| <li><a href="#_creating_the_action">Creating the Action</a></li> |
| <li><a href="#_creating_the_window">Creating the Window</a></li> |
| <li><a href="#_creating_the_scene">Creating the Scene</a></li> |
| <li><a href="#_connect_the_database_to_the_scene">Connect the Database to the Scene</a></li> |
| <li><a href="#_next_steps">Next Steps</a></li> |
| </ul> |
| </div> |
| <div id="preamble"> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>In this tutorial, you will learn how to create a visualizer on top of the content of a database. You will create an action, attach it to a connection node, and then use it to connect to the database, visualizing its content in a Visual Library scene, as shown below:</p> |
| </div> |
| <div class="imageblock"> |
| <div class="content"> |
| <img src="../../_images/tutorials/db_69-db-1.png" alt="db 69 db 1"> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>All the information you need to know for working with the Visual Library API, as well as with the Database Explorer API, is collected at the following locations:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><a href="../../../../front/main/projects/graph/" class="xref page">Visual Library Project Page</a></p> |
| </li> |
| <li> |
| <p><a href="https://bits.netbeans.org/dev/javadoc/org-netbeans-api-visual/org/netbeans/api/visual/widget/doc-files/documentation.html">Visual Library 2.0 - Documentation</a></p> |
| </li> |
| <li> |
| <p><a href="https://bits.netbeans.org/dev/javadoc/org-netbeans-api-visual/overview-summary.html">Visual Library API Javadoc</a></p> |
| </li> |
| <li> |
| <p><a href="https://bits.netbeans.org/dev/javadoc/org-netbeans-modules-db/overview-summary.html">Database Explorer API Javadoc</a></p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Also, see <a href="http://www.javalobby.org/eps/netbeans_visual_library/">Roman Strobl’s Visual Library Screencast</a> on Javalobby.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Before continuing, you are assumed to have read the <a href="../nbm-visual_library/" class="xref page">NetBeans Visual Library Tutorial</a>, which gives you the basics for working with the Visual Library. The basics discussed in that tutorial will not be repeated here.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="_setting_up_the_module"><a class="anchor" href="#_setting_up_the_module"></a>Setting Up the Module</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>In this section, we use wizards to create a module project and a custom window component.</p> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic" start="1"> |
| <li> |
| <p>Choose File > New Project (Ctrl+Shift+N). Under Categories, select NetBeans Modules. Under Projects, select Module. Click Next.</p> |
| </li> |
| </ol> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic" start="2"> |
| <li> |
| <p>In the Name and Location panel, type <code>DatabaseExplorerDemo</code> in the Project Name field. Change the Project Location to any directory on your computer. Leave the Standalone Module option and Set as Main Project checkbox selected. Click Next.</p> |
| </li> |
| </ol> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic" start="3"> |
| <li> |
| <p>In the Basic Module Configuration panel, type <code>org.demo</code> in Code Name Base.</p> |
| </li> |
| </ol> |
| </div> |
| <div class="paragraph"> |
| <p>1. |
| Select "Generate XML Layer". Leave the locations of both the localizing bundle and the XML layer file so that they will be stored in a package with the name <code>org/demo</code> . Click Finish.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The IDE creates the <code>DatabaseExplorerDemo</code> project. The project contains all of your sources and project metadata, such as the project’s Ant build script. The project opens in the IDE. You can view its logical structure in the Projects window (Ctrl+1) and its file structure in the Files window (Ctrl+2).</p> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic" start="5"> |
| <li> |
| <p>Right-click the project, choose Properties, click Libraries in the Project Properties dialog box and declare a dependency on the following APIs:</p> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><a href="https://bits.netbeans.org/dev/javadoc/org-netbeans-modules-db/overview-summary.html">Database Explorer</a></p> |
| </li> |
| <li> |
| <p><a href="https://bits.netbeans.org/dev/javadoc/org-openide-nodes/overview-summary.html">Nodes API</a></p> |
| </li> |
| <li> |
| <p><a href="https://bits.netbeans.org/dev/javadoc/org-openide-awt/overview-summary.html">UI Utilities API</a></p> |
| </li> |
| <li> |
| <p><a href="https://bits.netbeans.org/dev/javadoc/org-openide-util/overview-summary.html">Utilities API</a></p> |
| </li> |
| <li> |
| <p><a href="https://bits.netbeans.org/dev/javadoc/org-netbeans-api-visual/overview-summary.html">Visual Library API</a></p> |
| </li> |
| <li> |
| <p><a href="https://bits.netbeans.org/dev/javadoc/org-openide-windows/overview-summary.html">Window System API</a></p> |
| </li> |
| </ul> |
| </div> |
| </li> |
| </ol> |
| </div> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| You need to set an implementation dependency on the Database Explorer API. Do so by selecting the Database Explorer item in the Libraries panel of the Project Properties dialog, clicking Edit, and then clicking 'Implementation Version'. By doing this, you are setting a dependency on internal classes that will change in future releases. Currently there is no other way of completing the scenario in this tutorial than to set an implementation dependency. |
| </td> |
| </tr> |
| </table> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic" start="6"> |
| <li> |
| <p>Click OK to close the Project Properties dialog.</p> |
| </li> |
| </ol> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic" start="7"> |
| <li> |
| <p>Create a package named "org.demo.resources" and put the following images into it:</p> |
| </li> |
| </ol> |
| </div> |
| <div class="imageblock"> |
| <div class="content"> |
| <img src="../../_images/tutorials/db_cancelGlyph.png" alt="db cancelGlyph"> |
| </div> |
| </div> |
| <div class="imageblock"> |
| <div class="content"> |
| <img src="../../_images/tutorials/db_command_16.png" alt="db command 16"> |
| </div> |
| </div> |
| <div class="imageblock"> |
| <div class="content"> |
| <img src="../../_images/tutorials/db_custom_displayable_16.png" alt="db custom displayable 16"> |
| </div> |
| </div> |
| <div class="imageblock"> |
| <div class="content"> |
| <img src="../../_images/tutorials/db_item_16.png" alt="db item 16"> |
| </div> |
| </div> |
| <div class="imageblock"> |
| <div class="content"> |
| <img src="../../_images/tutorials/db_list_16.png" alt="db list 16"> |
| </div> |
| </div> |
| <div class="imageblock"> |
| <div class="content"> |
| <img src="../../_images/tutorials/db_postCodeGlyph.png" alt="db postCodeGlyph"> |
| </div> |
| </div> |
| <div class="imageblock"> |
| <div class="content"> |
| <img src="../../_images/tutorials/db_preCodeGlyph.png" alt="db preCodeGlyph"> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="_creating_the_action"><a class="anchor" href="#_creating_the_action"></a>Creating the Action</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>We will create an action that will only be enabled if the activated node has the <code>ConnectionNode</code> from the Database Explorer API in its Lookup.</p> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic" start="1"> |
| <li> |
| <p>Right-click the module project, and create a new class extending the <code>BaseAction</code> class from the Database Explorer API:</p> |
| </li> |
| </ol> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">import java.sql.Connection; |
| import org.netbeans.api.db.explorer.ConnectionManager; |
| import org.netbeans.api.db.explorer.DatabaseConnection; |
| import org.netbeans.modules.db.explorer.action.BaseAction; |
| import org.openide.nodes.Node; |
| import org.openide.util.HelpCtx; |
| |
| public final class ShowDatabaseStructureAction extends BaseAction { |
| |
| @Override |
| protected void performAction(Node[] nodes) { |
| |
| } |
| |
| @Override |
| protected boolean enable(Node[] activatedNodes) { |
| return true; |
| } |
| |
| @Override |
| public String getName() { |
| return "Show Database Structure"; |
| } |
| |
| @Override |
| public HelpCtx getHelpCtx() { |
| return HelpCtx.DEFAULT_HELP; |
| } |
| |
| }</code></pre> |
| </div> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic" start="2"> |
| <li> |
| <p>Register the Action class as follows:</p> |
| </li> |
| </ol> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlightjs highlight"><code class="language-xml hljs" data-lang="xml"><folder name="Databases"> |
| <folder name="Explorer"> |
| <folder name="Connection"> |
| <folder name="Actions"> |
| <file name="org-demo-ShowDatabaseStructureAction.instance"/> |
| </folder> |
| </folder> |
| </folder> |
| </folder></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>You have now registered an Action such that it will be attached to the connection node in the Services window:</p> |
| </div> |
| <div class="imageblock"> |
| <div class="content"> |
| <img src="../../_images/tutorials/db_69-db-3.png" alt="db 69 db 3"> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="_creating_the_window"><a class="anchor" href="#_creating_the_window"></a>Creating the Window</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>In this section, we create a new window component that will hold our scene.</p> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic" start="1"> |
| <li> |
| <p>Right-click the module project, choose New > Other and choose Window from the Module Development category. Click Next.</p> |
| </li> |
| </ol> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic" start="2"> |
| <li> |
| <p>Choose <code>editor</code> in the drop-down list. Do not select Open on Application Start. Click Next.</p> |
| </li> |
| </ol> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic" start="3"> |
| <li> |
| <p>Type <code>Demo</code> in Class Name Prefix. Optionally, add an icon with a dimension of 16x16 pixels. Click Finish.</p> |
| </li> |
| </ol> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic" start="4"> |
| <li> |
| <p>Right-click in the <code>DemoTopComponent</code> in Design mode, choose Set Layout, and select BorderLayout.</p> |
| </li> |
| </ol> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic" start="5"> |
| <li> |
| <p>Switch to Source mode and change the <code>getPersistenceType</code> method to return <code>TopComponent.PERSISTENCE_NEVER</code> .</p> |
| </li> |
| </ol> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="_creating_the_scene"><a class="anchor" href="#_creating_the_scene"></a>Creating the Scene</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>Programming with the Visual Library API is similar to programming in Swing. You build and modify a tree of visual elements that are called "widgets". The root of the tree is represented by a Scene class which holds all the visual data of the scene. The scene is a widget. You have to create a scene view, which is a JComponent. You must then add the JComponent to a JScrollPane.</p> |
| </div> |
| <div class="paragraph"> |
| <p>In this section, we add a JScrollPane to our TopComponent. Then we create a new Visual Library scene in a separate Java source file. Next, we pass the scene to the TopComponent, so that it can be displayed in the TopComponent’s JScrollPane. We then install the module project and display our first scene.</p> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic" start="1"> |
| <li> |
| <p>Use the Palette (Ctrl-Shift-8) to drop a <code>JScrollPane</code> on the TopComponent.</p> |
| </li> |
| </ol> |
| </div> |
| <div class="paragraph"> |
| <p>1. |
| In the <code>org.demo</code> package, create a Java class called <code>DBGraphScene</code> . Let the class extend <code>VMDGraphScene</code> .</p> |
| </div> |
| <div class="paragraph"> |
| <p>A red error underline and a lightbulb appears. Let the IDE generate the import statement.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A red error underline and a lightbulb appears again. Let the IDE generate the class’s abstract methods.</p> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic" start="3"> |
| <li> |
| <p>Replace the content of the class with the following:</p> |
| </li> |
| </ol> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">import java.awt.Image; |
| import java.awt.Point; |
| import java.util.Arrays; |
| import java.util.List; |
| import org.netbeans.api.visual.vmd.VMDGraphScene; |
| import org.netbeans.api.visual.vmd.VMDNodeWidget; |
| import org.netbeans.api.visual.vmd.VMDPinWidget; |
| import org.openide.util.ImageUtilities; |
| |
| public class DBGraphScene extends VMDGraphScene{ |
| |
| private static final Image IMAGE_LIST = ImageUtilities.loadImage("org/demo/resources/list_16.png"); // NOI18N |
| private static final Image IMAGE_CANVAS = ImageUtilities.loadImage("org/demo/resources/custom_displayable_16.png"); // NOI18N |
| private static final Image IMAGE_COMMAND = ImageUtilities.loadImage("org/demo/resources/command_16.png"); // NOI18N |
| private static final Image IMAGE_ITEM = ImageUtilities.loadImage("org/demo/resources/item_16.png"); // NOI18N |
| private static final Image GLYPH_PRE_CODE = ImageUtilities.loadImage("org/demo/resources/preCodeGlyph.png"); // NOI18N |
| private static final Image GLYPH_POST_CODE = ImageUtilities.loadImage("org/demo/resources/postCodeGlyph.png"); // NOI18N |
| private static final Image GLYPH_CANCEL = ImageUtilities.loadImage("org/demo/resources/cancelGlyph.png"); // NOI18N |
| private static int nodeID = 1; |
| private static int edgeID = 1; |
| |
| public DBGraphScene() { |
| String mobile = createNode (this, 100, 100, IMAGE_LIST, "menu", "List", null); |
| createPin (this, mobile, "start", IMAGE_ITEM, "Start", "Element"); |
| String game = createNode (this, 600, 100, IMAGE_CANVAS, "gameCanvas", "MyCanvas", Arrays.asList (GLYPH_PRE_CODE, GLYPH_CANCEL, GLYPH_POST_CODE)); |
| createPin (this, game, "ok", IMAGE_COMMAND, "okCommand1", "Command"); |
| createEdge (this, "start", game); |
| createEdge (this, "ok", mobile); |
| } |
| |
| private static String createNode (VMDGraphScene scene, int x, int y, Image image, String name, String type, List<Image> glyphs) { |
| String nodeID = "node" + DBGraphScene.nodeID ++; |
| VMDNodeWidget widget = (VMDNodeWidget) scene.addNode (nodeID); |
| widget.setPreferredLocation (new Point (x, y)); |
| widget.setNodeProperties (image, name, type, glyphs); |
| scene.addPin (nodeID, nodeID + VMDGraphScene.PIN_ID_DEFAULT_SUFFIX); |
| return nodeID; |
| } |
| |
| |
| private static void createPin (VMDGraphScene scene, String nodeID, String pinID, Image image, String name, String type) { |
| ((VMDPinWidget) scene.addPin (nodeID, pinID)).setProperties (name, null); |
| } |
| |
| |
| private static void createEdge (VMDGraphScene scene, String sourcePinID, String targetNodeID) { |
| String edgeID = "edge" + DBGraphScene.edgeID ++; |
| scene.addEdge (edgeID); |
| scene.setEdgeSource (edgeID, sourcePinID); |
| scene.setEdgeTarget (edgeID, targetNodeID + VMDGraphScene.PIN_ID_DEFAULT_SUFFIX); |
| } |
| |
| }</code></pre> |
| </div> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic" start="4"> |
| <li> |
| <p>Add an instance variable for the scene to the top of the TopComponent’s source code:</p> |
| </li> |
| </ol> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">private DBGraphScene scene = new DBGraphScene();</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Add the scene to the JScrollPane’s ViewportView, at the end of the TopComponent’s constructor:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">jScrollPane1.setViewportView( scene.createView() );</code></pre> |
| </div> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic" start="5"> |
| <li> |
| <p>Before continuining, check that the content of the filesystem tags in your layer.xml file is as follows:</p> |
| </li> |
| </ol> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlightjs highlight"><code class="language-xml hljs" data-lang="xml"><filesystem> |
| <folder name="Actions"> |
| <folder name="Window"> |
| <file name="org-demo-DemoAction.instance"> |
| <attr name="component" methodvalue="org.demo.DemoTopComponent.findInstance"/> |
| <attr name="displayName" bundlevalue="org.demo.Bundle#CTL_DemoAction"/> |
| <attr name="instanceCreate" methodvalue="org.openide.windows.TopComponent.openAction"/> |
| </file> |
| </folder> |
| </folder> |
| <folder name="Menu"> |
| <folder name="Window"> |
| <file name="DemoAction.shadow"> |
| <attr name="originalFile" stringvalue="Actions/Window/org-demo-DemoAction.instance"/> |
| </file> |
| </folder> |
| </folder> |
| <folder name="Windows2"> |
| <folder name="Components"> |
| <file name="DemoTopComponent.settings" url="DemoTopComponentSettings.xml"/> |
| </folder> |
| <folder name="Modes"> |
| <folder name="editor"> |
| <file name="DemoTopComponent.wstcref" url="DemoTopComponentWstcref.xml"/> |
| </folder> |
| </folder> |
| </folder> |
| <folder name="Databases"> |
| <folder name="Explorer"> |
| <folder name="Connection"> |
| <folder name="Actions"> |
| <file name="org-demo-ShowDatabaseStructureAction.instance"/> |
| </folder> |
| </folder> |
| </folder> |
| </folder> |
| </filesystem></code></pre> |
| </div> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic" start="6"> |
| <li> |
| <p>Right-click the module and choose Run. Select "Demo" from the Window menu. The window component should open and show you the following:</p> |
| </li> |
| </ol> |
| </div> |
| <div class="imageblock"> |
| <div class="content"> |
| <img src="../../_images/tutorials/db_69-db-2.png" alt="db 69 db 2"> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="_connect_the_database_to_the_scene"><a class="anchor" href="#_connect_the_database_to_the_scene"></a>Connect the Database to the Scene</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>In this section, we connect to a selected database by using the Database Explorer API. We then pass the connection to the scene. In the scene, we parse the connection, extract the data, and visually display the data in the scene.</p> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic" start="1"> |
| <li> |
| <p>In your action class, you need to make a connection to a selected database and pass it to your window:</p> |
| </li> |
| </ol> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">import java.sql.Connection; |
| import org.netbeans.api.db.explorer.ConnectionManager; |
| import org.netbeans.api.db.explorer.DatabaseConnection; |
| import org.netbeans.modules.db.explorer.action.BaseAction; |
| import org.openide.nodes.Node; |
| import org.openide.util.HelpCtx; |
| |
| public final class ShowDatabaseStructureAction extends BaseAction { |
| |
| @Override |
| protected void performAction(Node[] nodes) { |
| DatabaseConnection dbconn = nodes[0].getLookup().lookup(DatabaseConnection.class); |
| if (dbconn.getJDBCConnection() == null) { |
| ConnectionManager.getDefault().showConnectionDialog(dbconn); |
| } |
| Connection connection = dbconn.getJDBCConnection(); |
| DemoTopComponent win = DemoTopComponent.findInstance(); |
| win.open(); |
| win.requestActive(); |
| win.setConnection(connection); |
| } |
| |
| @Override |
| protected boolean enable(Node[] activatedNodes) { |
| if (activatedNodes == null || activatedNodes.length != 1) { |
| return false; |
| } |
| boolean enabled = false; |
| DatabaseConnection dbconn = activatedNodes[0].getLookup().lookup(DatabaseConnection.class); |
| if (dbconn != null) { |
| enabled = true; |
| } |
| return enabled; |
| } |
| |
| @Override |
| public String getName() { |
| return "Show Database Structure"; |
| } |
| |
| @Override |
| public HelpCtx getHelpCtx() { |
| return HelpCtx.DEFAULT_HELP; |
| } |
| |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>A red error underline will appear below the last line in the <code>performAction</code> , because it refers to a statement that we have not defined yet. We will do so in the next step.</p> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic" start="2"> |
| <li> |
| <p>Back in your window component, you need to receive the connection and call the scene, as shown below:</p> |
| </li> |
| </ol> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">... |
| import java.sql.Connection; |
| ... |
| |
| final class DemoTopComponent extends TopComponent { |
| |
| private static DemoTopComponent instance; |
| |
| private static final String PREFERRED_ID = "DemoTopComponent"; |
| |
| private DBGraphScene scene; |
| |
| private DemoTopComponent() { |
| initComponents(); |
| setName(NbBundle.getMessage(DemoTopComponent.class, "CTL_DemoTopComponent")); |
| setToolTipText(NbBundle.getMessage(DemoTopComponent.class, "HINT_DemoTopComponent")); |
| } |
| |
| public void setConnection(Connection connection){ |
| scene = new DBGraphScene(connection); |
| jScrollPane1.setViewportView( scene.createView() ); |
| } |
| |
| ... |
| ... |
| ...</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>In the scene, the constructor that receives the connection does not exist yet. We will create it in the next step. Until then, reference to that constructor, above, is underlined in red.</p> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic" start="3"> |
| <li> |
| <p>In the <code>DBGraphScene</code> class, extend the 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">public class DBGraphScene extends VMDGraphScene { |
| |
| private static final Image IMAGE_LIST = ImageUtilities.loadImage("org/demo/resources/list_16.png"); // NOI18N |
| private static final Image IMAGE_ITEM = ImageUtilities.loadImage("org/demo/resources/item_16.png"); // NOI18N |
| |
| private static int edgeID = 1; |
| |
| public DBGraphScene(Connection connection) { |
| try { |
| createSceneFromConnection(connection); |
| } catch (SQLException e) { |
| e.printStackTrace(); |
| } |
| } |
| |
| private void createSceneFromConnection(Connection jdbcConnection) throws SQLException { |
| ArrayList<String> tables = new ArrayList<String>(); |
| DatabaseMetaData databaseMetaData = jdbcConnection.getMetaData(); |
| String[] names = {"TABLE"}; |
| ResultSet resultSet = databaseMetaData.getTables(null, "%", "%", names); |
| while (resultSet.next()) { |
| String table = resultSet.getString("TABLE_NAME"); |
| tables.add(table); |
| createNode(this, (int) (Math.random() * 800), (int) (Math.random() * 800), IMAGE_LIST, table, "Table", null); |
| ResultSet columns = jdbcConnection.getMetaData().getColumns(null, null, table.toUpperCase(), "%"); |
| while (columns.next()) { |
| String columnName = columns.getString("COLUMN_NAME"); |
| createPin(this, table, table + ":" + columnName, IMAGE_ITEM, columnName, columnName); |
| } |
| } |
| for (String string : tables) { |
| ResultSet resultSet1 = databaseMetaData.getExportedKeys(null, null, string); |
| while (resultSet1.next()) { |
| String pkTable = resultSet1.getString("PKTABLE_NAME"); |
| String pkColumn = resultSet1.getString("PKCOLUMN_NAME"); |
| String fkTable = resultSet1.getString("FKTABLE_NAME"); |
| String fkColumn = resultSet1.getString("FKCOLUMN_NAME"); |
| createEdge(this, fkTable + ":" + fkColumn, pkTable + ":" + pkColumn); |
| } |
| } |
| this.moveTo(null); |
| } |
| |
| private static String createNode(VMDGraphScene scene, int x, int y, Image image, String name, String type, java.util.List<Image> glyphs) { |
| String node = name; |
| VMDNodeWidget widget = (VMDNodeWidget) scene.addNode(node); |
| widget.setPreferredLocation(new Point(x, y)); |
| widget.setNodeProperties(image, name, type, glyphs); |
| return node; |
| } |
| |
| private static void createPin(VMDGraphScene scene, String nodeID, String pinID, Image image, String name, String type) { |
| ((VMDPinWidget) scene.addPin(nodeID, pinID)).setProperties(name, null); |
| } |
| |
| private static void createEdge(VMDGraphScene scene, String sourcePinID, String targetPinID) { |
| String edge = "edge" + DBGraphScene.edgeID++; |
| scene.addEdge(edge); |
| scene.setEdgeSource(edge, sourcePinID); |
| scene.setEdgeTarget(edge, targetPinID); |
| } |
| |
| private void moveTo(Point point) { |
| int index = 0; |
| for (String node : getNodes()) { |
| getSceneAnimator().animatePreferredLocation(findWidget(node), point != null ? point : new Point(++index * 100, index * 100)); |
| } |
| } |
| |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The <code>createSceneFromConnection</code> method gets the <code>DatabaseMetadata ( jdbcConnection.getMetaData() )</code> from the <code>Connection</code> . With the subsequent calls to <code>getTables</code> , the table structure is retrieved and the nodes of the graph are created. For every table, <code>getColumns</code> is called and a Pin is added for every column to the table node. These pins can be used in a subsequent step to create a connection between two tables. Now we iterate through the tables and call <code>getExportedKeys</code> to get hold of the <code>ForeignKeys</code> . For every exported key, an edge is created between the pins of the related columns. The <code>moveTo</code> method does the animation when the window is opened.</p> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic" start="4"> |
| <li> |
| <p>Run the module again. Open the Services window. Expand the Databases node. Select one of the connection nodes. The "Show Database Structure" menu item, under the File menu, should now be enabled. Select it and now your scene should open and look as follows:</p> |
| </li> |
| </ol> |
| </div> |
| <div class="imageblock"> |
| <div class="content"> |
| <img src="../../_images/tutorials/db_69-db-1.png" alt="db 69 db 1"> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Congratulations, you have completed a Visual Library scene that connects to a database and visually displays its content.</p> |
| </div> |
| <div class="paragraph"> |
| <p><a href="../../../../front/main/community/mailing-lists/" class="xref page">Send Us Your Feedback</a></p> |
| </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>For more information on working with the Visual Library API, see:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><a href="http://www.javalobby.org/eps/netbeans_visual_library/">Roman Strobl’s Visual Library Screencast</a> on Javalobby.</p> |
| </li> |
| <li> |
| <p><a href="../../../../front/main/projects/graph/" class="xref page">Visual Library Project Page</a></p> |
| </li> |
| <li> |
| <p><a href="https://bits.netbeans.org/dev/javadoc/org-netbeans-api-visual/org/netbeans/api/visual/widget/doc-files/documentation.html">Visual Library 2.0 - Documentation</a></p> |
| </li> |
| <li> |
| <p><a href="https://bits.netbeans.org/dev/javadoc/org-netbeans-api-visual/overview-summary.html">Visual Library API Javadoc</a></p> |
| </li> |
| <li> |
| <p><a href="https://bits.netbeans.org/dev/javadoc/org-netbeans-modules-db/overview-summary.html">Database Explorer API Javadoc</a></p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>With thanks to Toni Epple, who wrote the first version of this tutorial, <a href="../../../../wiki/main/wiki/VisualDatabaseExplorer/" class="xref page">A Visual Database Explorer for NetBeans</a>.</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-visual_library2.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 © 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> |