cornercorner
FeaturesPluginsDocs & SupportCommunityPartners

NetBeans 平台绘图应用程序教程

本教程介绍了一些有关使用 NetBeans IDE 在 NetBeans 平台上开发富客户端 (rich client) 应用程序的基础知识。在 NetBeans 平台上开发应用程序时,实际上就是在 NetBeans IDE 的核心上进行开发。IDE 中与您的应用程序无关的所有模块均排除在外,只保留一些有用的模块。通过重用 IDE 核心中提供的现成功能,您可以节省许多时间和精力。

注意:本文档针对的是 NetBeans IDE 6.5 发行版。如果使用的是 NetBeans IDE 6.x,请参见本文档的 6.0/6.1 版

目录

本页上的内容适用 NetBeans IDE 6.5

要学习本教程,您需要具备下表中列出的软件和资源。

软件或资源 要求的版本
NetBeans IDE 版本 6.5
Java Developer Kit (JDK) 版本 6 或
版本 5

绘图应用程序简介

本教程旨在帮助您尽快入门。您将在 NetBeans 平台上创建并安装一个简单的应用程序。通过该应用程序,用户可以在屏幕上绘图并保存结果:

完成后的应用程序的图像

该初始版本还远非一个完善的绘图应用程序,它只是演示了一个在 NetBeans 平台上创建应用程序的非常简单的示例。

注意:如果您希望了解 NetBeans 模块(而不是富客户端 (rich client) 应用程序),则 NetBeans 插件快速入门教程更适合您。

在本教程中,我们重新创建一个作为样例随 IDE 一起提供的应用程序。要查看最终产品,或者要在完成本教程的过程中解决疑难问题,请从“新建项目”向导中如下所示的位置获取样例:

“名称和位置”面板

设置绘图应用程序

在本节中,您将创建应用程序的结构。首先,您需要创建一个应用程序框架,可通过向导来完成此操作。该应用程序依赖于库,因此,您还会创建一个包含库的 JAR 文件的库包装模块。最后,将创建包含代码的模块。

创建应用程序框架

可以使用“NetBeans 平台应用程序”模板来创建应用程序框架。该框架包含一组模块,它们协同工作以形成应用程序的基础。将使用“项目属性”对话框来指定应用程序闪屏、应用程序名称以及要使用的 NetBeans 模块类型和数量。此外,您还可以利用一些操作,如创建 ZIP 分发和构建 Java WebStart (JNLP) 应用程序,它们是确保其他用户能够使用您的应用程序的重要工具。

  1. 选择“文件”>“新建项目”。在“类别”下选择“NetBeans 模块”。在“项目”下,选择“NetBeans 平台应用程序”:

    项目模板

    单击“下一步”。

  2. 在“名称和位置”面板的“项目名称”中键入 PaintApp。将项目位置更改为计算机上的任意目录。将“设置为主项目”复选框保留为选中状态。单击“完成”。

将在 IDE 中打开新应用程序框架。它在“项目”窗口中包含两个节点。第一个节点(“模块”节点)用于在应用程序中手动添加模块和库包装模块。此外,在使用模块向导或库包装模块向导时,可以自动将创建的模块添加到应用程序中。

创建库包装模块

库包装模块是这样一个模块,其 JAR 文件不包含任何代码,它只是一个指向库的指针。该模块会将库转换为 NetBeans 模块,这样 NetBeans 类加载器系统的所有保护措施都会应用于该库,您无需对原始的 JAR 文件执行修改。然后您的应用程序就可以依赖于库了,就好像该库只是另外一个 NetBeans 模块一样。此外,如果库存在更新的版本,则只需为包装库分发单个的 NetBeans 模块 (NetBeans Module, NBM) 文件即可,无需分发其他任何内容。

注意:在 NetBeans 平台上构建应用程序的一个优点是:其用户界面基于 Java 的标准用户界面工具包 Swing。由于 Swing 已被广泛使用了很长时间,因此许多 Swing 组件都可以在应用程序中重用。在本教程中,您将重用现有的颜色选择器 JavaBean(可以在 NetBeans CVS 中的 contrib/coloreditor 下找到其源代码)。该 JAR 文件名为 ColorChooser.jar。您可以从此处下载库。将其保存到文件系统中的任意位置。

请执行以下操作为 ColorChooser.jar 文件创建库包装模块:

  1. 选择“文件”>“新建项目”。在“类别”下选择“NetBeans 模块”。在“项目”下,选择“库包装模块”,然后单击“下一步”。
  2. 在“选择库”面板的“库”文本框中,键入 ColorChooser.jar 的路径,或者浏览到它所在的位置。
  3. 将“许可证”文本字段保留为空。如果希望分发完整的产品,则应该包括外部库的许可证文件。单击“下一步”。
  4. 在“名称和位置”面板中,填写项目名称,设置项目位置,并确保“添加到模块套件中”下拉列表显示模块将添加到应用程序中。单击“下一步”。
  5. 在“基本模块配置”面板的“代码名称基”中键入唯一名称,指定模块显示名称以及模块的本地化包位置:

    “名称和位置”面板

    单击“完成”。

选定 colorchooser.jar 的包装模块是由 IDE 创建的。新模块的结构将显示在“项目”窗口中。应用程序结构中的“模块”节点显示模块是应用程序的一部分。

创建模块

现在,您需要使用一个模块来包含将要编写的实际代码。

  1. 选择“文件”>“新建项目”。在“类别”下选择“NetBeans 模块”。在“项目”下选择“模块”,然后单击“下一步”。
  2. 在“名称和位置”面板的“项目名称”中键入 Paint。将项目位置更改为计算机上的任意目录。确保“添加到模块套件中”单选按钮处于选定状态,并在“模块套件”下拉列表中选定了 PaintApp 应用程序。选中“设置为主项目”复选框。单击“下一步”。
  3. 在“基本模块配置”面板中,键入 org.netbeans.paint。将“模块显示名称”保留为 Paint。保留本地化包的位置。单击“生成 XML 层”,并且不更改建议的位置,以便将本地化包和 XML 层文件存储在名为 org.netbeans.paint 的包中。

    这些文件将执行以下操作:

    • 本地化包。为国际化指定特定于语言的字符串。
    • XML 层。在 NetBeans 平台应用程序中注册菜单和工具栏按钮等项。

    单击“完成”。

IDE 将创建 Paint 项目。该项目包含所有源代码和项目 meta 数据,如项目的 Ant 生成脚本。此项目将会在 IDE 中打开。您可以在“项目”窗口 (Ctrl-1) 中查看其逻辑结构,在“文件”窗口 (Ctrl-2) 中查看其文件结构。例如,“项目”窗口应如下所示:

绘图应用程序

除了本地化包和 XML 层以外,此项目还包括以下重要文件:

  • 模块清单。声明项目是一个模块。此外,它还设定了一些特定于模块的设置,如 XML 层的位置、本地化包的位置以及模块版本。
  • 生成脚本。提供一个位置,供您创建自己的 Ant 目标并覆盖在 nbproject/build-impl.xml 中指定的 Ant 目标。
  • 项目 Meta 数据。包含一些信息,如项目的类型、内容、平台、类路径、依赖关系以及项目命令与 Ant 脚本中的目标之间的映射。

您在本教程中不需要修改其中的任何文件。

指定模块的依赖关系

您需要根据一些属于 NetBeans API 的类创建子类。此外,该项目还依赖于 ColorChooser.jar 文件。由于所有 NetBeans API 都是由模块实现的,因此完成这两个任务实际上就意味着:将某些模块添加到保证我们的模块正常运行所需的模块列表中。

  1. 在“项目”窗口中右键单击 Paint 项目节点,然后选择“属性”。将打开“项目属性”对话框。在“类别”下单击“库”。
  2. 对于下表中列出的每个 API,单击“添加依赖关系...”,然后在“过滤器”文本框中开始键入要创建子类的类名称。

    API
    用途
    ColorChooser ColorChooser 所创建的颜色选择器组件的库包装模块
    DataObject Datasystems API 包含 DataObject 类的 NetBeans 模块
    DialogDisplayer 对话框 API 用于创建并显示用户通知(对话框的描述)
    AbstractFile 文件系统 API 提供了以统一方式访问文件的通用 API
    AbstractNode 节点 API 用作 NetBeans 中进行对象可视化的主要工具
    StatusDisplayer UI 实用程序 API 用于编写主窗口中状态栏的 StatusDisplayer 类
    WeakListeners 实用程序 API 包含 WeakListeners 类
    TopComponent 窗口系统 API 包含 TopComponent JPanel 类

    上表中的第一列列出了将在本教程中创建子类的所有类。在每种情况下,当在“过滤器”中键入类名时,可观察到“模块”列表的选择范围逐渐缩小。使用表的第二列可以从缩小的“模块”列表中选取适当的 API(对于 ColorChooser,应选取库),然后单击“确定”以确认选择:

    initial-proj-window

  3. 单击“确定”退出“项目属性”对话框。
  4. 在“项目”窗口中,如果尚未展开 "Paint" 模块的项目节点,请将其展开。然后展开“重要文件”节点,再双击“项目 Meta 数据”节点。请注意,您所选择的 API 已声明为与该模块具有依赖关系。

创建并嵌入画布

创建画布

下一步将创建用户可以在上面绘图的实际组件。对于本教程,您将使用一个纯 Swing 组件,因此,让我们跳过该组件的实现细节,只利用它的最终版本。在此面板的源代码中,将使用您已为其创建库包装模块的颜色选择器 Bean,当您运行完成的应用程序时,会在用于编辑图像的面板的工具栏中看到它。

  1. 在“项目”窗口中,展开 Paint 节点,然后展开“源包”节点,再右键单击 org.netbeans.paint 节点。选择“新建”>“Java 类”。
  2. 在“类名”中输入 PaintCanvas。请确保“包”中列出的是 org.netbeans.paint。单击“完成”。将在源代码编辑器中打开 PaintCanvas.java
  3. 将文件的缺省内容替换为此处的内容。如果为包指定 org.netbeans.paint 以外的名称,请在源代码编辑器中更正包名。

准备 TopComponent 类

现在您将编写第一个与 NetBeans API 交互的类。它是一个 TopComponent 类。TopComponent 类正是一个 NetBeans 的窗口系统知道如何与其进行交互的 JPanel 类,因此可以将其置于主窗口中的标签化容器内。

  1. 在“项目”窗口中,展开 Paint 节点,然后展开“源包”节点,再右键单击 org.netbeans.paint 节点。选择“新建”>“Java 类”。
  2. 在“类名”中输入 PaintTopComponent。请确保“包”中列出的是 org.netbeans.paint。单击“完成”。将在源代码编辑器中打开 PaintTopComponent.java
  3. 在该文件的顶部附近,将类声明改为以下代码:
    public class PaintTopComponent extends TopComponent implements ActionListener, ChangeListener {
  4. 按 Ctrl-Shift-I 组合键修复导入,然后在对话框中单击“确定”。IDE 会将所需的 import 包声明置于文件顶部。

    请注意刚刚输入的类声明下面的红线。将光标放置在该行上,您会注意到其左侧空白处显示了一个灯泡图标。单击该灯泡图标(或按 Alt-Enter 组合键),如下所示:

    灯泡图标。

    选择“实现所有抽象方法”。IDE 将生成两个方法框架 - actionPerformed()stateChanged()。您将在本教程的后面部分填充这些方法。

  5. 将以下三个变量声明添加到 PaintTopComponent 类的顶部,然后修复 import 语句 (Ctrl-Shift-I)。
        private PaintCanvas canvas = new PaintCanvas(); //The component the user draws on
        private JComponent preview; //A component in the toolbar that shows the paintbrush size
        private static int ct = 0; //A counter you use to provide names for new images
  6. 现在需要实现两个样板方法。第一个方法通知窗口系统在应用程序关闭时忽略打开的窗口;第二个方法提供一个基本字符串作为组件的唯一字符串 ID。每个 TopComponent 都有一个唯一的字符串 ID,此 ID 在保存 TopComponent 时使用。在 PaintTopComponent 类中插入以下两个方法:
        @Override
        public int getPersistenceType() {
            return PERSISTENCE_NEVER;
        }
    
        @Override
        public String preferredID() {
            return "Image";
        }

该类现在应如下所示:

public class PaintTopComponent extends TopComponent implements ActionListener, ChangeListener {
    
    private PaintCanvas canvas = new PaintCanvas(); //The component the user draws on
    private JComponent preview; //A component in the toolbar that shows the paintbrush size
    private static int ct = 0; //A counter you use to provide names for new images
    
    public PaintTopComponent() {
    }
    
    @Override
    public void actionPerformed(ActionEvent arg0) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    
    @Override
    public void stateChanged(ChangeEvent arg0) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    
    @Override
    public int getPersistenceType() {
        return PERSISTENCE_NEVER;
    }
    
    @Override
    public String preferredID() {
        return "Image";
    }
    
}

初始化 TopComponent 类

在本节中,我们添加初始化用户界面的代码。

  1. 定义构造函数,然后修复 import 语句 (Ctrl-Shift-I):
        public PaintTopComponent() {
    
            initComponents();
    
            String displayName = NbBundle.getMessage(
                    PaintTopComponent.class,
                    "UnsavedImageNameFormat",
                    new Object[] { new Integer(ct++) }
            );
    
            setDisplayName(displayName);
    
        }
  2. 此处的代码非常简单。首先调用的是尚未编写的方法 initComponents(),该方法用于在 TopComponent 中添加一个工具栏和一个 PaintCanvas。由于尚未编写该方法,因此它下面会显示一条红线。如前面所述,单击灯泡图标(或按 Alt-Enter 组合键),并接受建议的内容:

    灯泡图标。

    将为您生成 initComponents() 方法框架。

  3. 在“项目”窗口中展开 org.netbeans.paint 包。双击 Bundle.properties 文件,以便在源代码编辑器中将其打开。将以下代码行添加到该文件的末尾:
        UnsavedImageNameFormat=Image {0}

    此代码用于指定在用户保存一个新的图像文件之前,应用程序中标识此图像的文本。例如,当用户第一次在完成的应用程序中单击 "New Canvas" 时,源代码编辑器的上方将显示一个带有文本 'Image 0' 的标签。确保保存此文件,然后再继续。

填充框架方法

在本节中,我们将编写应用程序用户界面的代码。还可以使用 IDE 的 GUI 生成器以可视方式设计布局。

  1. initComponents() 方法用于安装面板中的组件,以便用户可以与其进行交互。在上一节,已在 PaintTopComponent.java 类中生成了它的框架方法。请按如下所示填充该方法:
        private void initComponents() {
    
            setLayout(new BorderLayout());
            JToolBar bar = new JToolBar();
    
            ColorChooser fg = new ColorChooser();
            preview = canvas.createBrushSizeView();
    
            //Now build our toolbar:
    
            //Make sure components don't get squished:
            Dimension min = new Dimension(32, 32);
            preview.setMaximumSize(min);
            fg.setPreferredSize(new Dimension(16, 16));
            fg.setMinimumSize(min);
            fg.setMaximumSize(min);
    
            JButton clear = new JButton(
              	    NbBundle.getMessage(PaintTopComponent.class, "LBL_Clear"));
    
            JLabel fore = new JLabel(
             	    NbBundle.getMessage(PaintTopComponent.class, "LBL_Foreground"));
    
            fg.addActionListener(this);
            clear.addActionListener(this);
    
            JSlider js = new JSlider();
            js.setMinimum(1);
            js.setMaximum(24);
            js.setValue(canvas.getDiam());
            js.addChangeListener(this);
    
            fg.setColor(canvas.getColor());
    
            bar.add(clear);
            bar.add(fore);
            bar.add(fg);
            JLabel bsize = new JLabel(
         	    NbBundle.getMessage(PaintTopComponent.class, "LBL_BrushSize"));
    
            bar.add(bsize);
            bar.add(js);
            bar.add(preview);
    
            JLabel spacer = new JLabel("   "); //Just a spacer so the brush preview
            //isn't stretched to the end of the
            //toolbar
    
            spacer.setPreferredSize(new Dimension(400, 24));
            bar.add(spacer);
    
            //And install the toolbar and the painting component:
            add(bar, BorderLayout.NORTH);
            add(canvas, BorderLayout.CENTER);
            
        }
  2. 按 Ctrl-Shift-I 组合键生成所需的 import 语句。

  3. 填充您生成的另外两个方法。它们用于侦听 PaintTopComponent 类:
        public void actionPerformed(ActionEvent e) {
    
            if (e.getSource() instanceof JButton) {
               canvas.clear();
            } else if (e.getSource() instanceof ColorChooser) {
               ColorChooser cc = (ColorChooser) e.getSource();
               canvas.setPaint (cc.getColor());
            }
            
            preview.paintImmediately(0, 0, preview.getWidth(), preview.getHeight());
            
        }
        public void stateChanged(ChangeEvent e) {
    
            JSlider js = (JSlider) e.getSource();
            canvas.setDiam (js.getValue());
            preview.paintImmediately(0, 0, preview.getWidth(), preview.getHeight());
            
        }
  4. Bundle.properties 文件的末尾添加以下键值对:
        LBL_Clear = Clear
        LBL_Foreground = Foreground 
        LBL_BrushSize = Brush Size
    

    确保保存此文件,然后再继续。

将图像保存到硬盘

在新的应用程序中,允许用户保存所创建的图像是一个非常好的想法。在 PaintTopComponent 类中包括以下代码可激活此功能。

  1. PaintTopComponent 类中插入以下代码:
        public void save() throws IOException {
    
            if (getDisplayName().endsWith(".png")) {
    	    doSave(new File(getDisplayName()));
            } else {
    	    saveAs();
            }
            
        }
        public void saveAs() throws IOException {
    
            JFileChooser ch = new JFileChooser();
            if (ch.showSaveDialog(this) == JFileChooser.APPROVE_OPTION && ch.getSelectedFile() != null) {
    
    	    File f = ch.getSelectedFile();
                
    	    if (!f.getPath().endsWith(".png")) {
    	        f = new File(f.getPath() + ".png");
    	    }
                
    	    if (!f.exists()) {
                
    	        if (!f.createNewFile()) {
    		    String failMsg = NbBundle.getMessage(
    		             PaintTopComponent.class,
    			    "MSG_SaveFailed", new Object[] { f.getPath() }
    	            );
    		    JOptionPane.showMessageDialog(this, failMsg);
    		    return;
    	        }
                    
    	    } else {
    	        String overwriteMsg = NbBundle.getMessage(
    		    PaintTopComponent.class,
                        "MSG_Overwrite", new Object[] { f.getPath() }
    	        );
                    
    	        if (JOptionPane.showConfirmDialog(this, overwriteMsg)
    	        != JOptionPane.OK_OPTION) {
    		    return;
    	        }
                    
    	    }
                
    	    doSave(f);
                
            }
            
        }
        private void doSave(File f) throws IOException {
    
            BufferedImage img = canvas.getImage();
            ImageIO.write(img, "png", f);
            String statusMsg = NbBundle.getMessage(PaintTopComponent.class,
                "MSG_Saved", new Object[] { f.getPath() });
            StatusDisplayer.getDefault().setStatusText(statusMsg);
            setDisplayName(f.getName());
            
        }
  2. 将以下代码行添加到 Bundle.properties 文件中:
        MSG_SaveFailed = Could not write to file {0}
        MSG_Overwrite = {0} exists.  Overwrite?
        MSG_Saved = Saved image to {0}

    确保保存此文件,然后再继续。

  3. 按 Ctrl-Shift-I 组合键修复 import 语句。您会注意到 File 类有两个全限定名称。请选择 java.io.File 选项。

创建 "New Canvas" 菜单项

使用“模块开发”文件模板,可以创建基本的模块功能。使用文件模板时,IDE 将在 layer.xml 文件中注册您创建的项。使用向导创建文件模板后,您可以使用 NetBeans API 继续开发模块。

  1. 在“项目”窗口中右键单击 Paint 模块的项目节点,然后选择“新建”>“其他”。在“新建文件”向导中的“类别”下选择“模块开发”,然后在“文件类型”下选择“操作”。单击“下一步”。
  2. 在“操作类型”面板中,接受缺省设置。单击“下一步”。
  3. 在“GUI 注册”面板中,选择“全局菜单项”,然后选择“全局工具栏按钮”。设置以下值:

    • 类别:编辑
    • 菜单:文件
    • 位置:您需要的任何位置!
    • 工具栏:文件
    • 位置:您需要的任何位置!

    注意:将操作置于什么位置并不重要,只要在“文件”菜单和“文件”工具栏中即可。

    您现在应该看到如下所示的屏幕:

    “GUI 注册”面板。

    单击“下一步”。

  4. 在“名称、图标和位置”面板的“类名”中键入 NewCanvasAction,并在“显示名称”中键入 New Canvas

    在“图标”中,浏览至以下图标(右键单击该图标,然后将其保存在 org.netbeans.paint 文件夹中):New Canvas 图标。

  5. 单击“完成”。

    IDE 将在 org.netbeans.paint 中创建 NewCanvasAction.java,并在源代码编辑器中将其打开。将会显示以下内容:

    /*
     * To change this template, choose Tools | Templates
     * and open the template in the editor.
     */
    package org.netbeans.paint;
    
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    
    public final class NewCanvasAction implements ActionListener {
    
        public void actionPerformed(ActionEvent e) {
            // TODO implement action body
        }
        
    }

    与“GUI 注册”面板中指定的一样,IDE 在 layer.xml 文件中将操作类注册为菜单项和工具栏按钮,该文件还包含有关图标和显示名称的信息。

  6. 在源代码编辑器中,打开 NewCanvasAction.java 并按如下所示填充 performAction() 方法:
        public void performAction() {
    
            PaintTopComponent tc = new PaintTopComponent();
    	tc.open();
    	tc.requestActive();       
        }

    该方法的作用只是创建一个图像编辑组件的新实例、打开该实例(使其显示在主窗口中),以及通过向其发送键盘焦点和选择其标签来激活该实例。

创建 "Save Canvas" 菜单项

像上一节一样,使用“新建操作”向导来创建一个菜单项,但这次是用来保存图像。

  1. 在“项目”窗口中右键单击 Paint 模块的项目节点,然后选择“新建”>“其他”。在“新建文件”向导中的“类别”下选择“模块开发”,然后在“文件类型”下选择“操作”。单击“下一步”。
  2. 在“操作类型”面板中,接受缺省设置。单击“下一步”。
  3. 在“GUI 注册”面板中,选择“全局菜单项”,然后选择“全局工具栏按钮”。设置以下值:

    • 类别:编辑
    • 菜单:文件
    • 位置:您需要的任何位置!
    • 工具栏:文件
    • 位置:您需要的任何位置!

    注意:将操作置于什么位置并不重要,只要在“文件”菜单和“文件”工具栏中即可。

    单击“下一步”。

  4. 在“名称、图标和位置”面板的“类名”中键入 SaveCanvasAction,并在“显示名称”中键入 Save Canvas

    在“图标”中,粘贴以下图标(右键单击该图标,然后将其保存到 org.netbeans.paint 文件夹中):Save Canvas 图标。

  5. 单击“完成”。

    IDE 将在 org.netbeans.paint 中创建 SaveCanvasAction.java,并在源代码编辑器中将其打开。

  6. 更改类签名,以扩展 CallableSystemAction 并实现 PropertyChangeListener
    public final class SaveCanvasAction extends CallableSystemAction implements PropertyChangeListener
  7. 在源代码编辑器中,确保打开 SaveCanvasAction.java,然后按如下所示填充 performAction() 方法:
        @Override
        public void performAction(ActionEvent e) {
            TopComponent tc = TopComponent.getRegistry().getActivated();
    
            if (tc instanceof PaintTopComponent) {
    
                try {
                    ((PaintTopComponent) tc).saveAs();
                } catch (IOException ioe) {
                    ErrorManager.getDefault().notify(ioe);
                }
    
            } else {
    
                //Theoretically the active component could have changed
                //between the time the menu item or toolbar button was
                //pressed and when the action was invoked.  Not likely,
                //but theoretically possible
                Toolkit.getDefaultToolkit().beep();
    
            }
        }

    按 Ctrl-Shift-I 组合键生成所需的 import 语句:

    修复导入。

  8. 按如下方式填充 CallableSystemAction 类中的方法:
        @Override
        public String getName() {
            return "Save Canvas";
        }
    
        @Override
        public HelpCtx getHelpCtx() {
            return null;
        }
    

  9. 按如下方式填充 PropertyChangeListener 中的 propertyChange() 方法:
        @Override    
        public void propertyChange(PropertyChangeEvent evt) {
    
            if (TopComponent.Registry.PROP_ACTIVATED.equals(evt.getPropertyName())){
    	    updateEnablement();
            }
            
        }

    当出现红线时,单击 Alt + Enter 组合键可以使 IDE 在 SaveCanvasAction 类中创建 updateEnablement() 方法。

    接下来,定义 updateEnablement() 方法:

        private void updateEnablement() {
    
            setEnabled(TopComponent.getRegistry().getActivated()
            instanceof PaintTopComponent);
    
        }

    最后,定义构造函数:

        public SaveCanvasAction() {  
    
            TopComponent.getRegistry().addPropertyChangeListener (
    	    WeakListeners.propertyChange(this,
    	    TopComponent.getRegistry()));
           
            updateEnablement();
            
        }

    当出现红线时,单击 Alt + Enter 组合键可以使 IDE 导入 org.openide.util.WeakListeners

    代码的主要目的在于添加属性更改侦听程序。TopComponent.Registry 是系统中所有打开的 TopComponents(即所有打开的标签)的注册表。我们的目的是要对该注册表进行侦听以获知其更改,并根据焦点所在的对象启用和禁用操作。

    注意:您在此调用的是 WeakListeners.propertyChange(),而不是直接连接属性更改侦听程序。这样做的目的在于:生成的属性更改侦听程序对操作造成的影响较弱。实际上,只要该应用程序是打开的,您的操作就会处于活动状态,因此,作为一种最佳做法(同时出于前瞻性的考虑),当您打算连接侦听程序,但又不存在中断调用侦听程序的代码时,建议使用弱化的侦听程序。否则,将会出现潜在的内存泄漏 - 由于注册表在其侦听程序列表中一直保存着对该操作的引用,因此不会对该操作进行垃圾回收。

以下是您现在应该在“项目”窗口中看到的内容:

“项目”窗口的最终视图

包装

当然,您希望创建的是尽善尽美的应用程序,因此,您最后可能还需要再执行几个步骤。首先,为应用程序创建闪屏,然后创建 ZIP 分发文件和 JNLP 应用程序。

  1. 运行 PaintApp 项目。该应用程序启动后,将主屏幕适当缩小,然后绘制一个闪屏。使用“保存”按钮保存该闪屏。
  2. 在原始项目中,右键单击 PaintApp 节点,选择“属性”,然后在“项目属性”对话框中单击“生成”。
  3. 选择“创建独立的应用程序”。现在可以指定标记名称(将是 IDE 可以为您生成的启动器名称)和应用程序标题(将显示在应用程序的标题栏中)。缺省情况下,您会看到以下内容:

    闪屏

  4. 单击“闪屏”。浏览到您的闪屏。如果没有闪屏,可以使用此闪屏。单击“确定”将其添加到应用程序中:
  5. 闪屏

  6. 现在,在 Paint 模块的 layer.xml 文件中,将以下标记添加到 "Menu" 文件夹中。这些标记用于删除 Paint 应用程序不需要的 "GoTo" 和 "View" 菜单。

    <file name="GoTo_hidden"/>
    <file name="View_hidden"/>

    或者,也可以删除 layer.xml 文件的 <上下文中的此层> 节点中的文件夹,而不是手动添加上述标记。为此,请展开 <上下文中的此层>,然后展开 "Menu Bar" 节点。右键单击 "GoTo" 和 "View" 节点,然后从弹出式菜单中选择“删除”。

  7. 最后,再次运行该应用程序,请注意观察闪屏。应用程序启动后,您可以看到标题栏中将显示您所指定的标题。此外,还少了很多菜单项、工具栏按钮和其他功能:

    无菜单的结果

创建分发

现在该选择分发介质了。右键单击 PaintApp 节点,并选择“生成 ZIP 分发”,以便将整个应用程序连同所有需要的模块和文件一起打包为一个 zip 文件。此外,还可以选择“生成 JNLP 应用程序”来创建 JavaWebStart™ 版本的应用程序,您可以将该版本的应用程序放到 Web 服务器上,并直接通过 Web 页链接到该应用程序(您需要设置正确的 URL - 生成的描述符使用 file: 协议才能在本地对可通过 Web 启动的分发执行测试)。

以上就是本教程的内容!至此,您已在 NetBeans 平台上构建了第一个完整的应用程序。下一站:NetBeans 平台 Feed Reader 教程