使用Netbeans开发简单的Java数据库应用程序(续)_xianhua_新浪博客

    六、添加新增记录对话框   

   

   

    如图所示,本节内容包括以下内容:

  • 创建对话框以编辑主窗体中的每个表的数据
  • 创建中间 Bean 以便在对话框和窗体之间传输数据
  • 将对话框中的字段绑定到中间 Bean
  • 为对话框中的按钮创建事件处理程序

    1、创建产品对话框
    右键单击包含类的包databaseapplication,然后选择“新建”-->“其他”;选择“Swing GUI 窗体”-->“JDialog 窗体”模板,并将其命名为 ProductEditor。编辑对话框设计如下图所示:

     选择整个 JDialog 窗体,在“属性”窗口中,将“标题”属性更改为 Product Editor。

     2、绑定产品对话框字段
     现在,需要将各种字段绑定到表中的相应列。因为无法在“绑定”对话框中直接绑定到其他窗体中的组件,因此,必须创建一个 Products 类型的中间 Bean 属性以保存记录。在用户单击 "New" 按钮时,将会为该 Bean 属性分配空记录值,用户可以在对话框中对其进行修改。在用户单击对话框中的 "保存" 时,该 Bean 属性中的值将传回到主窗体和数据库。

    生成中间 Bean 属性:

    在 ProductEditor窗体类代码的某个位置,如构造函数下面的一行,按 Alt-Insert 组合键(或单击鼠标右键并选择“插入代码”,然后选择“添加属性”。在“添加属性”对话框中,将该属性命名为 currentRecord,将其类型指定为 Products,选择“生成 getter 和 setter”,然后选择“生成属性更改支持”。单击“确定”以生成该属性。 如下图所示:

使用Netbeans开发简单的Java数据库应用程序(续)

    现在,您需要定制生成的 setCurrentRecord 方法以触发属性更改通知:

    触发属性更改通知:

    public void setCurrentRecord(Products currentRecord) {
        Products oldRecord = this.currentRecord;
        this.currentRecord = currentRecord;
        propertyChangeSupport.firePropertyChange("currentRecord", oldRecord, currentRecord);
    }

    现在,需要添加代码,以便在用户单击 "New" 按钮时打开 "Product Editor" 对话框。

    添加代码以从主视图中打开对话框:打开 DataBaseView 类并选择“源”视图。导航至 newRecord() 方法,在该方法底部粘贴以下代码:

    JFrame mainFrame = DataBaseApplication.getApplication().getMainFrame();       

    ProductEditor pe = new ProductEditor(mainFrame, false);       

    pe.setCurrentRecord(p);       

    pe.setVisible(true);

    绑定Product对话框的字段:

    在“设计”视图中打开 ProductEditor 类。
    选择 PROD_TYPE 的文本字段,在“属性”窗口中,选择“绑定”类别,选择 text 属性,然后单击该属性旁边的省略号 (...) 按钮。在“绑定”对话框中,从“绑定源”中选择 "Form",然后从“绑定表达式”中选择 "currentRecord" --> "prodType";

    选择BRAND的文本字段,在“属性”窗口中,选择“绑定”类别,选择 text 属性,类似地在“绑定”对话框中,从“绑定源”中选择 "Form",然后从“绑定表达式”中选择 "currentRecord" --> "brand"; 

    选择MODEL的文本字段,在“属性”窗口中,选择“绑定”类别,选择 text 属性,类似地在“绑定”对话框中,从“绑定源”中选择 "Form",然后从“绑定表达式”中选择 "currentRecord" --> "model";

    选择PRICE的文本字段,在“属性”窗口中,选择“绑定”类别,选择 text 属性,类似地在“绑定”对话框中,从“绑定源”中选择 "Form",然后从“绑定表达式”中选择 "currentRecord" --> "price"。

    3、xx对话框中的 "保存" 和 "取消" 按钮
    现在,需要完成为对话框和主窗体之间关联编写代码的工作。

    首先,将对话框中的按钮与相应的事件处理代码关联。目前已经具有随框架应用程序提供的 save() 和 refresh() 操作。可以为该对话框编写代码,以使这些按钮重用这些操作。可通过在对话框中设置一个布尔属性来完成此操作:在按 "保存" 按钮时,该属性返回 true;在选择 "取消" 时,该属性返回 false。根据关闭对话框时返回的值,将从 DataBaseView 类中运行 save() 或 refresh() 操作。

    要设置该属性,请执行以下操作:

    打开 ProductEditor 文件并选择“源”视图;将光标放在 propertyChangeSupport 字段的上方,按组合键 Alt-Insert ,然后选择“添加属性”;在“添加属性”对话框中,键入 productConfirmed 作为属性名称。
将类型设置为布尔类型,确保选中了“生成 getter 和 setter”复选框单击“确定”关闭该对话框并生成代码。
    然后在这些按钮的事件处理代码中设置该属性的值。

    创建事件侦听程序和处理程序:

    切换到 ProductEditor 类的“设计”视图,在 ProductEditor 窗体中选择 "Save" 按钮,在“属性”窗口中,单击“事件”按钮,单击 actionPerformed 属性旁边的省略号 (...) 按钮。在“actionPerformed 的处理程序”对话框中,添加一个名为 saveProduct 的处理程序。
    在源代码编辑器中的 saveProduct 方法内(创建新处理程序后光标跳转到的位置),键入以下代码:

    setProductConfirmed(true);

    setVisible(false);
    对于 "Cancel" 按钮,重复以上步骤,并将其处理程序命名为 cancelProduct。在 cancelProduct 方法中,键入以下内容:

    setProductConfirmed(false);

    setVisible(false);
    在 DataBaseView 类中,导航至 newRecord() 方法,并在该方法底部添加以下代码:

        if (pe.isProductConfirmed()) {
            save().run();
        }
        else {
            refresh().run();
        }

    由于 save() 和 refresh() 操作应用于在应用程序会话期间进行的任何更改,因此,应该将对话框设置为模态对话框,并将主窗体中的表设置为不可编辑。将对话框设置为模态对话框的另一个原因是:在用户按 "保存" 或 "取消" 按钮时,setVisible() 方法在运行事件处理程序(它包括 setProductConfirmed 方法)后才会返回内容。另外,如果不把对话框设置为模态对话框,可能还会出现其它错误(如不能新增与保存记录等)。

    将对话框设置为模态对话框:

    打开 ProductEditor 类的“设计”视图,选择该对话框,在“属性”窗口中,单击“属性”,然后选中 modal 属性的复选框。

    这时运行项目,产品添加功能已可以正常使用,但在显示Countries数据表时,点击new按钮,仍然是添加产品。实际上,应该在new按钮的点击方法newRecord()中判断一下当前正在显示和编辑那个表,并把代码放在判断语句块中:

    if(tableName == "Products"){
            databaseapplication.Products p = new databaseapplication.Products();
            ......

            if (pe.isProductConfirmed()) {
                save().run();
            }
            ......

    }

    七、添加Countries表新增记录对话框,并修改相关代码

    按照新增Products记录对话框的实现方法,添加Countries表新增记录对话框,将其命名为CountryEditor,如图所示:

    同样在对话框中添加Bean属性,名称为currentRecord,类型为Countries(注意要选择“生成属性更改支持”)。

    同样,您需要定制生成的 setCurrentRecord 方法以触发属性更改通知:

    触发属性更改通知:

    public void setCurrentRecord(Countries currentRecord) {
        Countries oldRecord = this.currentRecord;
        this.currentRecord = currentRecord;
        propertyChangeSupport.firePropertyChange("currentRecord", oldRecord, currentRecord);
    }

    在“设计”视图中打开 CountryEditor 类。
    选择国家名文本字段,在“属性”窗口中,选择“绑定”类别,选择 text 属性,然后单击该属性旁边的省略号 (...) 按钮。在“绑定”对话框中,“绑定源”选择 "Form",“绑定表达式”选择 "currentRecord" --> "country"。

    与产品对话框一样,还需要添加一个属性,以判断是点击了保存还是取消按钮。打开 CountryEditor 源文件,将光标放在 propertyChangeSupport 字段的上方,按组合键 Alt-Insert ,然后选择“添加属性”(或者右键选择插入代码-->添加属性);在“添加属性”对话框中,键入 countryConfirmed 作为属性名称。将类型设置为布尔类型,确保选中了“生成 getter 和 setter”复选框单击“确定”关闭该对话框并生成代码。

    现在,需要添加代码,以便在显示Countries表时,当用户单击 "New" 按钮时将打开 "Country Editor" 对话框。

    添加代码以从主视图中打开对话框:打开 DataBaseView 类并选择“源”视图。导航至 newRecord() 方法,在该方法底部粘贴以下代码:

    if(tableName == "Countries"){
            Countries c = new Countries();
            entityManager.persist(c);
            //list.add(c);//有错误
            //int row = list.size()-1;

            cList.add(c);
            int row = cList.size()-1;
            masterTable.setRowSelectionInterval(row, row);
            masterTable.scrollRectToVisible(masterTable.getCellRect(row, 0, true));
            setSaveNeeded(true);
            JFrame mainFrame = DataBaseApplication.getApplication().getMainFrame();
            CountryEditor ce = new CountryEditor(mainFrame, false);
            ce.setCurrentRecord(c);
            ce.setVisible(true); 

            if (ce.isCountryConfirmed()) {
                save().run();

                refresh().run();//增加这一句是因为JTable不自动显示新添加的记录内容,尚未查明原因
            }
            else {
                refresh().run();
                     
     }

    这时会发现系统在list.add(c)处提示一个错误,这是因为list的定义为:

    private java.util.List<databaseapplication.Products> list;

    而向list中添加的是Countries对象。要解决这个问题,需要一个Countries对象列表cList:

    private java.util.List<databaseapplication.Countries> cList;

    然后将上述方法中的list.add(c)修改为cList.add(c)。

    除此之外,还需要修改以下方法代码:

    public void deleteRecord() {
        if(tableName == "Products"){
            //保留原代码

            ......

        }

        //添加如下代码        
        if(tableName == "Countries"){
            int[] selected = masterTable.getSelectedRows();
            List<Countries> toRemove = new ArrayList<Countries>(selected.length);
            for (int idx=0; idx<selected.length; idx++) {
                Countries c = cList.get(masterTable.convertRowIndexToModel(selected[idx]));
                toRemove.add(c);
                entityManager.remove(c);
            }
            cList.removeAll(toRemove);
            setSaveNeeded(true);
        }
    }

    SaveTask方法:

    private class SaveTask extends Task {
        ......

        @Override protected Void doInBackground() {
            try {
                entityManager.getTransaction().commit();
                entityManager.getTransaction().begin();
            } catch (RollbackException rex) {
                rex.printStackTrace();
                entityManager.getTransaction().begin();
                if(tableName == "Products"){
                    //保持原代码

                    ......

                }

                //添加如下代码
                if(tableName == "Countries"){
                    List<Countries> merged = new ArrayList<Countries>(cList.size());
                    for (databaseapplication.Countries c : cList) {
                        merged.add(entityManager.merge(c));
                    }
                    cList.clear();
                    cList.addAll(merged);
                              
            }
            return null;
        }
        ......

    }

    RefreshTask方法:

    将方法中的有关list的两句代码替换为下面代码:

    if(tableName == "Products"){
         list.clear();
         list.addAll(data);
    }
    if(tableName == "Countries"){
         cList.clear();
         cList.addAll(data);
    }

    BindTable()方法:

    把if(tableName == "Countries")语句块中的list都替换为cList,即获取Countries表记录添加到cList,并将cList绑定到JTable。

    下面应该添加按钮点击事件处理方法了。创建事件侦听程序和处理程序:

    切换到 CountryEditor 类的“设计”视图,在 CountryEditor 窗体中选择 "Save" 按钮,在“属性”窗口中,单击“事件”按钮,单击 actionPerformed 属性旁边的省略号 (...) 按钮。在“actionPerformed 的处理程序”对话框中,添加一个名为 saveCountry 的处理程序。
    在源代码编辑器中的 saveCountry 方法内(创建新处理程序后光标跳转到的位置),键入以下代码:

    setCountryConfirmed(true);

    setVisible(false);
    对于 "Cancel" 按钮,重复以上步骤,并将其处理程序命名为 cancelCountry。在 cancelCountry 方法中,键入以下内容:

    setCountryConfirmed(false);

    setVisible(false);
    由于 save() 和 refresh() 操作应用于在应用程序会话期间进行的任何更改,因此,应该将对话框设置为模态对话框,并将主窗体中的表设置为不可编辑。将对话框设置为模态对话框的另一个原因是:在用户按 "保存" 或 "取消" 按钮时,setVisible() 方法在运行事件处理程序(它包括 setCountryConfirmed 方法)后才会返回内容。另外,如果不把对话框设置为模态对话框,可能还会出现其它错误(如不能新增与保存记录等)。

    将对话框设置为模态对话框:

    打开 CountryEditor 类的“设计”视图,选择该对话框,在“属性”窗口中,单击“属性”,然后选中 modal 属性的复选框。

    八、进一步完善程序

    1、验证记录删除
    现在已经将大多数主要操作的访问位置从主窗体移至对话框。{wy}的例外是 Delete 操作。以前,在应用程序中通过按 "Save" 来确认删除以及按 "Refresh" 来取消删除。由于 "Save" 和 "Refresh" 按钮不再位于主窗体中(save按钮放在了对话框;增加删除验证后,refresh按钮也不再需要),因此需要替换此功能。可通过在 deleteRecord() 方法中添加确认对话框来实现此操作。如果用户单击 "OK",则会调用 save() 方法,因而将{yj}删除记录。如果用户单击 "Cancel",则会调用 refresh() 方法并xxxx。

    下面是修改后的deleteRecord方法:

    public void deleteRecord() {

        //按 Ctrl-Shift-I 组合键以添加缺少的 import 语句

        int n = JOptionPane.showConfirmDialog(null, "Delete the records permanently?",

              "Warning",JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null);
        if (n == JOptionPane.YES_OPTION){
            if(tableName == "Products"){
                 ......

                 //修改setSaveNeeded(true)语句为保存记录
                 save().run();
            }
            if(tableName == "Countries"){
                 ......

                 cList.removeAll(toRemove);
                 //修改setSaveNeeded(true)语句
                 save().run();
            }
        }
        else {
            refresh().run();
        }
    }

    现在就可以在主窗体中删除refresh和save按扭了。

    2、在对话框中添加编辑功能
    现在,您可以运行应用程序并单击 "New" 以添加新记录。在对话框中按 "保存" 时,将保存记录。按取消时,将回滚已更改的新记录。不过,无法再编辑现有记录,因为已禁止编辑主窗体中的表。为解决该问题,将在主窗体中添加编辑按钮,以便编辑现有记录。

    要添加按钮及其相应的事件处理代码,请执行以下操作:

    打开 DataBaseView 类并选择“设计”视图;将 "New" 按钮略微向左拖动;将一个按钮从组件面板拖到刚挪出的空白区域;右键单击按钮,然后选择“设置操作”;在“操作”字段中选择“创建新操作”;在“操作方法”中键入 editRecord;在“文本”中键入"Edit";单击“高级”标签,然后从“启用的属性”中选择 recordSelected。这会生成一个标注属性,以确保仅在选择记录时才会启用操作的按钮和任何其他触发器(如菜单项)。单击“确定”关闭该对话框。将会显示该文件的“源”视图,并且光标位于新生成的 editRecord() 方法中。在该方法中粘贴以下代码:

    public void editRecord() {
        if(tableName == "Products"){
            setSaveNeeded(true);
            JFrame mainFrame = DataBaseApplication.getApplication().getMainFrame();
            ProductEditor pe = new ProductEditor(mainFrame, false);
            pe.setCurrentRecord(list.get(masterTable

                           .convertRowIndexToModel(masterTable.getSelectedRow())));
            pe.setVisible(true);
            if (pe.isProductConfirmed()) {
                save().run();
            }
            else {
                refresh().run();
            }
        }
        if(tableName == "Countries"){
            setSaveNeeded(true);
            JFrame mainFrame = DataBaseApplication.getApplication().getMainFrame();
            CountryEditor ce = new CountryEditor(mainFrame, false);
            ce.setCurrentRecord(cList.get(masterTable

                    .convertRowIndexToModel(masterTable.getSelectedRow())));
            ce.setVisible(true);
            if (ce.isCountryConfirmed()) {
                save().run();
                refresh().run();
            }
            else {
                refresh().run();
            }
        }
    }
    至此,该程序以比较完善,您可以根据需要再进行其它修改。

    九、多窗体应用程序的其它方法

    除了以上方法开发数据库窗体应用程序外,还可以采用下述多窗体方法开发数据库应用程序。这样,在主窗体中点击不同的菜单,将弹出不同的数据显示和编辑子窗体。

    1、可以创建一个桌面应用程序程序框架,右键点击项目名(或程序包名)添加JInternalFrame子窗体,在子窗体中进行数据的显示、修改等操作。在主窗体的菜单命令方法中打开子窗体。参考代码如下:

    @Action
    public void DisplayProduct() {
        ProductFrame childFrame=new ProductFrame();
        JDesktopPane desk=new JDesktopPane();
        //desk.setOpaque(true);
        //desk.setBackground(Color.red);

        desk.add(childFrame);
        mainPanel.setLayout(new BorderLayout());
        mainPanel.add(desk);
        childFrame.setVisible(true);
    }

    2、创建Java应用程序,系统将生成只包含一个Main.java(含main方法)的程序框架。右键点击项目,添加JFrame主窗体,在窗体中添加菜单条、菜单项。参考代码如下:

    public class MainFrame extends javax.swing.JFrame {

        public MainFrame() {
            initComponents();       
        }
        private void jMenuItem1ActionPerformed(java.awt.event.ActionEvent evt)       

                                                 
            //JInternalFrame child=new JInternalFrame("字体窗体",true,true,true);
            ChildFrame child=new ChildFrame();
            JDesktopPane desk=new JDesktopPane();
            //desk.setOpaque(true);
            //desk.setBackground(Color.red);
            desk.add(child);
            //没有下一语句,子窗体不显示
            this.getContentPane().setLayout(new BorderLayout());
            this.getContentPane().add(desk);
            //没有下一语句,子窗体不显示
            child.setSize(300,200);
            child.setVisible(true);        
        }

        ......

        private javax.swing.JMenu jMenu1;
        private javax.swing.JMenuBar jMenuBar1;
        private javax.swing.JMenuItem jMenuItem1;  

         ......

    }

    右键点击主窗体所在包名,创建JInternalFrame窗体,在窗体中添加JTable组件。右键选择JTable组件,选择"绑定"-->"elements",点击将数据导入窗体,为JTable绑定数据库表。参考代码如下:

    public class ChildFrame extends javax.swing.JInternalFrame {

        public ChildFrame() {
            super("Products",true,true,true,true);
            initComponents();
       

        ......

    }

    main.java的参考代码:

    public static void main(String[] args) {
        // TODO code application logic here
        new MainFrame().setVisible(true);
    }

    3、类似第二种方式,不过主窗体代码为手工编写,参考代码如下:

    import test.ChildFrame;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class InternalFrameDemo extends JFrame
{
 private JInternalFrame inner1;
 private JInternalFrame inner2;
 private JDesktopPane desk;
 public InternalFrameDemo(String title)
 {
  super(title);
  JMenuBar bar=new JMenuBar();
  JMenu fileMenu=new JMenu("文件");
  JMenuItem openFont=new JMenuItem("打开字体");
  JMenuItem openText=new JMenuItem("打开文本");
  JMenuItem closeFont=new JMenuItem("关闭字体");
  JMenuItem closeText=new JMenuItem("关闭文本");
  JMenuItem exitItem=new JMenuItem("退出");
  fileMenu.add(openFont);
  fileMenu.add(openText);
  fileMenu.add(closeFont);
  fileMenu.add(closeText);
  fileMenu.addSeparator();
  fileMenu.add(exitItem);
  bar.add(fileMenu);
  //inner1=new JInternalFrame("字体窗体",true,true,true);
                inner1=new ChildFrame();
  inner2=new JInternalFrame("文本窗体",true,true,true);
  desk=new JDesktopPane();
  desk.setOpaque(true);
  desk.setBackground(Color.red);
  desk.add(inner1);
  desk.add(inner2);
  this.getContentPane().add(desk);
  this.setJMenuBar(bar);
  exitItem.addActionListener(
   new ActionListener()
   {
    public void actionPerformed(ActionEvent e)
    {
     System.exit(0);
    }
   }
  );
  openFont.addActionListener(
   new ActionListener()
   {
    public void actionPerformed(ActionEvent e)
    {
     inner1.setSize(200,100);
     inner1.setVisible(true);
    }
   }
  );
  openText.addActionListener(
   new ActionListener()
   {
    public void actionPerformed(ActionEvent e)
    {
     inner2.setSize(200,100);
     inner2.setVisible(true);
    }
   }
  );
  closeFont.addActionListener(
   new ActionListener()
   {
    public void actionPerformed(ActionEvent e)
    {
     inner1.setVisible(false);
    }
   }
  );
  closeText.addActionListener(
   new ActionListener()
   {
    public void actionPerformed(ActionEvent e)
    {
     inner2.setVisible(false);
    }
   }
  );
  this.setSize(400,300);
  this.setVisible(true);
  this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 }
 public static void main(String[] args)
 {
  new InternalFrameDemo("主窗体");
 }
}

    这部分代码来自网络,其中ChildFrame为新创建的JInternalFrame,绑定了数据库表。

 

已投稿到:
  • 评论加载中,请稍候...

验证码:

郑重声明:资讯 【使用Netbeans开发简单的Java数据库应用程序(续)_xianhua_新浪博客】由 发布,版权归原作者及其所在单位,其原创性以及文中陈述文字和内容未经(企业库qiyeku.com)证实,请读者仅作参考,并请自行核实相关内容。若本文有侵犯到您的版权, 请你提供相关证明及申请并与我们联系(qiyeku # qq.com)或【在线投诉】,我们审核后将会尽快处理。
—— 相关资讯 ——