NetBeans Visual Library Tutorial

最近都在学写netbeans的插件,感觉这个例子比较好。现在翻译后贴出来共享下。

例子简介:从palette中选择下列三个图形中的任意一个,左键拖动到主面板上,并可进行适量缩放及修改图形的ID。






建立Module

首先我们需要创建一个mudule工程和一个用户window component。
  1. 选择 文件 > 新建项目. 在新建项目的向导中,左边选择NetBeans Modules,右边选择 Module.点击下一步.在项目名处输入ShapeSample 并设置保存在本机上的位置。最后选择Standalone Module and Set as Main Project.点击下一步步.

  2. 在代码名处输入org.netbeans.shapesample,在模块显示名处输入 Shape Sample. 点击完成.

  3. 右键点击新建好的项目,选择Properties, 点击 Libraries,添加以下lib:

    • Visual Library API
    • Action APIs
    • Command Line Parsing API
    • Common Palette
    • Nodes API
    • Swing Layout Extensions integration
    • UI Utilities API
    • Utilities API
    • Windows System API

    点击确定。


  4. 右键点击该项目,选择新建
    New > Other 并在NetBeans Module Development category 中选择 Window Component . 点击下一步. 在第一个下拉列表中选择 editor 并选择 Open on Application Start. 点击下一步.

  5. 在类名中输入 Shape. 最好选择一副16px×16px的图片做图标,以便识别和更加专业:)。 点击完成.               这样多个文件将会被自动创建。其中有一个叫ShapeTopComponent. 打开它后你将看到如下视图:




  6. 右键点击ShapeTopComponent的面板中心, 选择Set Layout, 选咋 Border Layout.




创建Editor

  1. 选则ShapeTopComponent,从 Palette (Ctrl-Shift-8) 中途一个JScrollPane 到 TopComponent上. 选择属性中的名字,把它修改为shapePane.并在inspector面板中双击JScrollPane,把名字改为shapePane。
  2. 在包 org.netbeans.shapesample 中创建一个 GraphSceneImpl.java
    /
    This is just a exercise to hoe to use JTable.
    /
    package org.netbeans.shapesample;

    import java.awt.Graphics2D;
    import java.awt.Image;
    import java.awt.Point;
    import java.awt.Rectangle;
    import java.awt.datatransfer.DataFlavor;
    import java.awt.datatransfer.Transferable;
    import java.awt.datatransfer.UnsupportedFlavorException;
    import java.awt.geom.AffineTransform;
    import java.io.IOException;
    import javax.swing.JComponent;
    import org.netbeans.api.visual.action.AcceptProvider;
    import org.netbeans.api.visual.action.ActionFactory;
    import org.netbeans.api.visual.action.ConnectorState;
    import org.netbeans.api.visual.action.TextFieldInplaceEditor;
    import org.netbeans.api.visual.action.WidgetAction;
    import org.netbeans.api.visual.graph.GraphScene;
    import org.netbeans.api.visual.widget.LabelWidget;
    import org.netbeans.api.visual.widget.LayerWidget;
    import org.netbeans.api.visual.widget.Widget;
    import org.netbeans.api.visual.widget.general.IconNodeWidget;
    import org.netbeans.shapesample.palette.MyNode;
    import org.openide.util.Utilities;

    /**

    @author Vanessa <liyuan.li at Yunnan University>
    @version 1.0.0.0
    /
    public class GraphSceneImpl extends GraphScene<MyNode, String> {

    private LayerWidget mainLayer;
    private WidgetAction editorAction = ActionFactory.createInplaceEditorAction(new LabelTextFieldEditor());

    private class LabelTextFieldEditor implements TextFieldInplaceEditor {

    public boolean isEnabled(Widget widget) {
    return true;
    }

    public String getText(Widget widget) {
    return ((LabelWidget) widget).getLabel();
    }

    public void setText(Widget widget, String text) {
    ((LabelWidget) widget).setLabel(text);
    }
    }

    public GraphSceneImpl() {
    mainLayer = new LayerWidget(this);
    addChild(mainLayer);
    getActions().addAction(ActionFactory.createAcceptAction(new AcceptProvider() {

    public ConnectorState isAcceptable(Widget widget, Point point, Transferable transferable) {
    Image dragImage = getImageFromTransferable(transferable);
    JComponent view = getView();
    Graphics2D g2 = (Graphics2D) view.getGraphics();
    Rectangle visRect = view.getVisibleRect();
    view.paintImmediately(visRect.x, visRect.y, visRect.width, visRect.height);
    g2.drawImage(dragImage,
    AffineTransform.getTranslateInstance(point.getLocation().getX(),
    point.getLocation().getY()),
    null);
    return ConnectorState.ACCEPT;
    }

    public void accept(Widget widget, Point point, Transferable transferable) {
    Image image = getImageFromTransferable(transferable);
    Widget w = GraphSceneImpl.this.addNode(new MyNode(image));
    w.setPreferredLocation(widget.convertLocalToScene(point));
    }
    }));

    getActions().addAction(ActionFactory.createZoomAction());
    getActions().addAction(ActionFactory.createPanAction());
    }

    private Image getImageFromTransferable(Transferable transferable) {
    Object o = null;
    try {
    o = transferable.getTransferData(DataFlavor.imageFlavor);
    } catch (IOException ex) {
    ex.printStackTrace();
    } catch (UnsupportedFlavorException ex) {
    ex.printStackTrace();
    }
    return o instanceof Image ? (Image) o : Utilities.loadImage(“org/netbeans/shapesample/palette/shape1.png”);
    }

    @Override
    protected Widget attachNodeWidget(MyNode node) {
    IconNodeWidget widget = new IconNodeWidget(this);
    widget.setImage(node.getImage());
    widget.setLabel(Long.toString(node.hashCode()));

    //double-click, the event is consumed while double-clicking only:
    widget.getLabelWidget().getActions().addAction(editorAction);

    //single-click, the event is not consumed:
    widget.getActions().addAction(createSelectAction());

    //mouse-dragged, the event is consumed while mouse is dragged:
    widget.getActions().addAction(ActionFactory.createMoveAction());

    //mouse-over, the event is consumed while the mouse is over the widget:
    widget.getActions().addAction(createObjectHoverAction());

    mainLayer.addChild(widget);
    return widget;
    }

    @Override
    protected Widget attachEdgeWidget(String edge) {
    throw new UnsupportedOperationException(“Not supported yet.”);
    }

    @Override
    protected void attachEdgeSourceAnchor(String edge, MyNode oldSourceNode, MyNode sourceNode) {
    throw new UnsupportedOperationException(“Not supported yet.”);
    }

    @Override
    protected void attachEdgeTargetAnchor(String edge, MyNode oldTargetNode, MyNode targetNode) {
    throw new UnsupportedOperationException(“Not supported yet.”);
    }
    }
    在红线处右键选择Fix Imports。
  3. 在ShapeTopComponent.java中修改 getPersistenceType()如下
public int getPersistenceType() {
return TopComponent.PERSISTENCE_NEVER;
}

创建 Component Palette



  1. 新建org.netbeans.shapesample.palette包,并在其中船舰一下类:

    /
      Category.java
     

      Created on September 21, 2006, 9:00 PM
     

      To change this template, choose Tools | Template Manager
     
    and open the template in the editor.
     
     
    To understand this class, see http://platform.netbeans.org/tutorials/nbm-nodesapi3.html
     /

    package org.netbeans.shapesample.palette;

    /**
     

      @author Geertjan Wielenga
     
    /

    public class Category {
       
        private String name;
       
        / Creates a new instance of Category /
        public Category() {
        }
       
        public String getName() {
            return name;
        }
       
        public void setName(String name) {
            this.name = name;
        }
       
    }
    /

      CategoryChildren.java
     

      Created on September 21, 2006, 9:00 PM
     

      To change this template, choose Tools | Template Manager
     
    and open the template in the editor.
     
     
    To understand this class, see http://platform.netbeans.org/tutorials/nbm-nodesapi3.html
     */

    package org.netbeans.shapesample.palette;

    import org.openide.nodes.Children;
    import org.openide.nodes.Node;

    /

     
     
    @author Geertjan Wielenga
     /
    public class CategoryChildren extends Children.Keys {

        private String[] Categories = new String[]{
            “Shapes”};

        public CategoryChildren() {
        }

        protected Node[] createNodes(Object key) {
            Category obj = (Category) key;
            return new Node[] { new CategoryNode(obj) };
        }

        protected void addNotify() {
            super.addNotify();
            Category[] objs = new Category[Categories.length];
            for (int i = 0; i < objs.length; i++) {
                Category cat = new Category();
                cat.setName(Categories[i]);
                objs[i] = cat;
            }
            setKeys(objs);
        }

    }
    /

      CategoryNode.java
     

      Created on September 21, 2006, 9:02 PM
     

      To change this template, choose Tools | Template Manager
     
    and open the template in the editor.
     
     
    To understand this class, see http://platform.netbeans.org/tutorials/nbm-nodesapi3.html
     /

    package org.netbeans.shapesample.palette;

    import org.openide.nodes.AbstractNode;
    import org.openide.util.lookup.Lookups;

    /**
     

      @author Geertjan Wielenga
     
    /
    public class CategoryNode extends AbstractNode {

        / Creates a new instance of CategoryNode /
        public CategoryNode( Category category ) {
            super( new ShapeChildren(category), Lookups.singleton(category) );
            setDisplayName(category.getName());
        }
    }
    /

      PaletteSupport.java
     

      Created on September 25, 2006, 2:22 PM
     

      To change this template, choose Tools | Template Manager
     
    and open the template in the editor.
     
     
    To understand this class, see http://platform.netbeans.org/tutorials/nbm-nodesapi3.html
     */

    package org.netbeans.shapesample.palette;

    import java.awt.Image;
    import java.awt.datatransfer.DataFlavor;
    import java.awt.datatransfer.UnsupportedFlavorException;
    import java.beans.BeanInfo;
    import java.io.IOException;
    import javax.swing.Action;
    import org.netbeans.spi.palette.DragAndDropHandler;
    import org.netbeans.spi.palette.PaletteActions;
    import org.netbeans.spi.palette.PaletteController;
    import org.netbeans.spi.palette.PaletteFactory;
    import org.openide.nodes.AbstractNode;
    import org.openide.nodes.Node;
    import org.openide.util.Lookup;
    import org.openide.util.datatransfer.ExTransferable;

    /

     
     
    @author dave
     /
    public class PaletteSupport {
       
        public static PaletteController createPalette() {
            AbstractNode paletteRoot = new AbstractNode(new CategoryChildren());
            paletteRoot.setName(“Palette Root”);
            return PaletteFactory.createPalette( paletteRoot, new MyActions(), null, new MyDnDHandler() );
        }
       
        private static class MyActions extends PaletteActions {
            public Action[] getImportActions() {
                return null;
            }
           
            public Action[] getCustomPaletteActions() {
                return null;
            }
           
            public Action[] getCustomCategoryActions(Lookup lookup) {
                return null;
            }
           
            public Action[] getCustomItemActions(Lookup lookup) {
                return null;
            }
           
            public Action getPreferredAction(Lookup lookup) {
                return null;
            }
           
        }
       
        private static class MyDnDHandler extends DragAndDropHandler {

            public void customize(ExTransferable exTransferable, Lookup lookup) {
                Node node = lookup.lookup(Node.class);
                final Image image = (Image) node.getIcon(BeanInfo.ICON_COLOR_16x16);
                exTransferable.put(new ExTransferable.Single (DataFlavor.imageFlavor) {
                   
                    protected Object getData() throws IOException, UnsupportedFlavorException {
                        return image;
                    }
                   
                });
            }
           
        }

    }

    /

      Shape.java
     

      Created on September 21, 2006, 9:09 PM
     

      To change this template, choose Tools | Template Manager
     
    and open the template in the editor.
     
     
    To understand this class, see http://platform.netbeans.org/tutorials/nbm-nodesapi3.html
     /

    package org.netbeans.shapesample.palette;

    /**
     

      @author Geertjan Wielenga
     
    /
    public class Shape {

        private Integer number;
        private String category;
        private String title;
        private String image;

        / Creates a new instance of Instrument /
        public Shape() {
        }

        public Integer getNumber() {
            return number;
        }

        public void setNumber(Integer number) {
            this.number = number;
        }

        public String getCategory() {
            return category;
        }

        public void setCategory(String category) {
            this.category = category;
        }

        public String getImage() {
            return image;
        }

        public void setImage(String image) {
            this.image = image;
        }

    }
    /


      ShapeChildren.java

     


      Created on September 21, 2006, 9:10 PM

     


      To change this template, choose Tools | Template Manager

     
    and open the template in the editor.

     

     
    To understand this class, see http://platform.netbeans.org/tutorials/nbm-nodesapi3.html

     */





    package org.netbeans.shapesample.palette;



    import java.util.ArrayList;

    import org.openide.nodes.Index;

    import org.openide.nodes.Node;



    /


     

     
    @author Geertjan Wielenga

     /

    public class ShapeChildren  extends Index.ArrayChildren {



        private Category category;



        private String[][] items = new String[][]{

            {“0”, “Shapes”, “org/netbeans/shapesample/palette/image1.png”},

            {“1”, “Shapes”, “org/netbeans/shapesample/palette/image2.png”},

            {“2”, “Shapes”, “org/netbeans/shapesample/palette/image3.png”},

        };



        public ShapeChildren(Category Category) {

            this.category = Category;

        }



        protected java.util.List<Node> initCollection() {

            ArrayList childrenNodes = new ArrayList( items.length );

            for( int i=0; i<items.length; i++ ) {

                if( category.getName().equals( items[i][1] ) ) {

                    Shape item = new Shape();

                    item.setNumber(new Integer(items[i][0]));

                    item.setCategory(items[i][1]);

                    item.setImage(items[i][2]);

                    childrenNodes.add( new ShapeNode( item ) );

                }

            }

            return childrenNodes;

        }



    }
    • MyNode.java
    /

      This is just a exercise to hoe to use JTable.
     
    /

    package org.netbeans.shapesample.palette;

    import java.awt.Image;

    /
     
     
    @author Vanessa <liyuan.li at Yunnan University>
      @version 1.0.0.0
     
    /
    public class MyNode {
       
        private Image image;
       
        public MyNode(Image image) {
            this.image = image;
        }
       
        public Image getImage() {
            return image;
        }
    }

    /
     
    ShapeNode.java
     
     
    Created on September 21, 2006, 9:18 PM
     
     
    To change this template, choose Tools | Template Manager
      and open the template in the editor.
     

      To understand this class, see http://platform.netbeans.org/tutorials/nbm-nodesapi3.html
     
    /

    package org.netbeans.shapesample.palette;

    import org.openide.nodes.AbstractNode;
    import org.openide.nodes.Children;
    import org.openide.util.lookup.Lookups;

    /

     
     
    @author Geertjan Wielenga
     /
    public class ShapeNode extends AbstractNode {
       
        private Shape shape;
       
        /** Creates a new instance of InstrumentNode
    /
        public ShapeNode(Shape key) {
            super(Children.LEAF, Lookups.fixed( new Object[] {key} ) );
            this.shape = key;
            setIconBaseWithExtension(key.getImage());
        }
       
    }
  2. 在ShapeTopComponent.java的构造器中添加如下代码:

    associateLookup( Lookups.fixed( new Object[] { PaletteSupport.createPalette() } ) );


  3. 项目结构如下。

    <p><img src="http://platform.netbeans.org/images/tutorials/vislib/proj-window.png" border="1"></p></li></ol><br><br>示例演示:<br>
    


    1. CTRL+鼠标滚轮

    修改ID


    备注:

    1。以上是总结后的简略方法,原文参见http://platform.netbeans.org/tutorials/60/nbm-visual_library.html

    从原文中可以体会到每部分代码的作用。从而对netbeans platform有更加深刻的认识。

    2.有红线的地方请使用右键 选择Fix Imports。