Java语言课程设计报告

                       摘    要

随着电子信息时代的飞速发展,Internet应用在全球范围内日益普及,当今社会正快速向信息化社会前进,信息自动化的作用也越趋重要。更大的自动化软件可以使我们从繁杂的事务中获得轻松,提高了我们的工作效率。

图书管理系统更加人性化操作是我们一直以来都追求的,良好的人机界面给管理人员还有使用的学生带来便利,同时也可以让借阅者更好的了解到自己的需求,这样就有理于学生的学习,还有管理人员的管理工作。

   本系统将会涉及到图书馆日常管理工作的基本常见细节,诸如新图书的入库登记,图书的查询,图书的预定、退还手续的登记,费旧图书的清理撤除等,本系统所要实现的这些功能基本上涵盖了图书馆的日常管理工作,基本能够满足校园图书馆的工作人员的管理需要;同时还有读者系统个人信息查询,借阅情况查询,修改密码,方便了借阅者的借书需求;同时还人性化的提供了游客查询系统。

在对本系统的具体开发过程当中,将采用Java语言进行开发,以Access实现后台数据库,本系统是完全基于Swing图形化用户界面的单机版本。

【关键字】人性化 游客查询  图形化用户界面

目     录

一  课程设计的内容................................................................................................................... 2

(一)课程设计主要内容................................................................................................................... 2

(二)设计要求................................................................................................................................. 2

设计方案.................................................................................................................................. 2

(一)数据流图.......................................................................................................................... 2

(二)总体设计.......................................................................................................................... 2

(三)个体设计.......................................................................................................................... 4

   (1)各个模块的介绍............................................................................................................ 4

   (2)流程图...........................................................................................................................

   (3)代码实现.................................................................................................................... 15 

三 结果及数据分析

结论........................................................................................................................................ 15

问题与讨论........................................................................................................................... 16

六 参考文献................................................................................................................................ 16

课程设计的内容

(一)课程设计主要内容

   自学Swing图形界面设计和数据库程序设计。开发用于某学校的图书馆管理系统。该系统要求实现面向管理员的图书管理功能和面向读者的图书及个人信息查询。具体包括以下功能模块:借阅管理、图书管理、借阅证管理、图书查询和读者信息查询。

(二)设计要求

   要求实现面向管理员的图书管理功能和面向读者的图书及个人信息查询。具体包括以下功能模块:借阅管理、图书管理、借阅证管理、图书查询和读者信息查询,可根据实际情况增加功能模块。所写报告要表达清楚,让老师明白你做了哪些工作,掌握了哪些知识。你所做的课程设计有何特点和优点。

设计方案

(一)数据流图

 


  数据库流图

(二)总体设计

系统设计的总体任务是实现图书信息管理的系统化,规范化和自动化。要求实现的功能有1.图书信息的输入,包括图书书名、作者、出版社、出版日期、数量及定价等。2. 图书信息的查询,包括根据用户的要求实现利用图书信息的查询。3  图书信息的修改,要求能包括根据用户的要求实现利用图书信息的修改等

首先,考虑到由于操作人员的计算机知识可能较差,要求有良好的人机界面,所以决定使用图形界面。利用图形界面,提供一个更加友好的方式。用户就不会面对黑乎乎的命令行界面,可以利用鼠标来实现图书信息的修改删除,这样的系统就可以降低对用户的要求,通过将系统的各种功能封装,只是提供给用户一个简单的按钮,用户通过简单的利用鼠标点击按钮,就可以实现各种复杂的操作,这样就可以,提高系统的可用性。 当然 复杂的实现过程对用户来说是不可以见的。

其次,考虑到使用图形界面的方式,当有很多数据时,就有必要使用数据库来保存数据了,使用数据库可以很好的利用数据库的海量存储功能,保存信息更加的方便。理由之二是由于本系统管理的对象图书,都是学生,且每个数据内容具有较强的关联性,涉及的过程不是很复杂。因此,比较适合于采用数据库管理。理由之三是因为当对数据进行各种修改操作时,使用数据库可以更加方便的保存用户的各种修改操作。理由之四是将数据库与图形界面向结合能提供一个更加友好的界面。

最后一点,是在进行图书信息的插入,修改,删除时,要求能显示执行结果,成功或者失败,在操作失败时要求能提供失败信息,主要是通过判断执行语句的返回值是否为真。为真说明执行成功,为假则说明操作失败,这时系统会打印堆栈信息,同时提示用户操作失败。如果操作成功要求能自动刷新,将最新结果显示出来,这主要是通过refresh的事件监听实现的,当操作成功时,重新执行查询操作,查询数据库中最新的结果。并显示出来,以上是基本思路。

   

 (三)个体设计

     (1)各个模块的介绍

1.登陆界面

 

打开程序后可以看到有两个可供选择的按钮,分别为“登陆”、“图书检索”,其分别实现的功能是以学生/管理员身份登陆图书馆 ,对图书馆系统进行各项操作;另外一个则是以游客身份查询图书,不需要登陆就可以查询图书,方便了在图书馆的查询以及防止个人信息的泄漏。

2.游客查询界面

以游客身份进入图书管理系统,这个功能主要是在图书馆内部查询机使用的,这样的一个功能可以不需要进行登录操作,就可以进行查询操作,方便借阅者查询图书还有保护个人信息。这个功能的实现其实是跟登录后对图书进行查询是完全一样的,只是界面有点不同,且少了一些操作。

class  ConsultinformationsFrame  extends JFrame

{

    private JPanel contentPane;

    private FlowLayout myLayout=new FlowLayout( );  //构造XYLayout布局管理器

       //创建显示信息使用的组件

    private JLabel label1=new JLabel("书名 : ");

    private JTextField noField=new JTextField(8);

    private JButton addRecordButton =new JButton("搜索");

    private JButton backdButton =new JButton("退出");

    Vector vector;

    String title[]={"书名","作者","出版社","出版日期","单价","可借数量"};   // 表头

    Connection connect=null; //声明Connection接口对象connect

    ResultSet rSet=null;        //定义数据库查询的结果集

    Statement stat=null;   //定义查询数据库的Statement对象

    AbstractTableModel tm;      //声明一个AbstractTableModel类对象tm

    public ConsultinformationsFrame()

    {

        enableEvents(AWTEvent.WINDOW_EVENT_MASK);

        try{

            jbInit();

        }catch(Exception e)

        {

            e.printStackTrace();

        }}

 private void jbInit() throws Exception {

        contentPane=(JPanel) this.getContentPane();  //初始化组件

        contentPane.setLayout(myLayout);   //设置容器的布局管理对象

        setSize(new Dimension(1020,600));   //设置容器窗口的大小

        setTitle("学生信息管理系统");  

     addRecordButton.addActionListener(new java.awt.event.ActionListener( )

        {   //注册按钮事件监听对象,实现ActionListener接口的actionPerformed方法

            public void actionPerformed(ActionEvent e)

            {  queryByNoButton_actionPerformed(e);  }});

     backdButton.addActionListener(new java.awt.event.ActionListener( )

        {//注册按钮事件监听对象,实现ActionListener接口的actionPerformed方法

           public void actionPerformed(ActionEvent e)

            {  backButton_actionPerformed(e);   }});

        createTable();  //在初始化函数中调用createtable()函数显示表格

        contentPane.add(label1);

        contentPane.add(noField);

        contentPane.add(addRecordButton);

        contentPane.add(backdButton);      }

    void createTable() {

           JTable table;

           JScrollPane scroll;

           vector=new Vector();

           tm=new AbstractTableModel()

        {   public int getColumnCount()

            {  return title.length;  }

            public int getRowCount()

            {  return vector.size(); }

            public Object getValueAt(int row,int column)

            {    if(!vector.isEmpty())

                    return ((Vector)vector.elementAt(row)).elementAt(column);

                 else return null;     }

            public void setValueAt(Object value,int row,int column{}

            public String getColumnName(int column)

            {   return title[column];  }

             public Class getColumnClass(int c)

             {  return getValueAt(0,c).getClass();  }

             public boolean isCellEditable(int row,int column)

            {   return false;   }};

        table=new JTable(tm);   //生成数据表

        table.setToolTipText("Display Query Result");   //设置帮助提示

        table.setAutoResizeMode(table.AUTO_RESIZE_ALL_COLUMNS); //设置表格调整尺寸模式

        table.setCellSelectionEnabled(false);   //设置单元格选择方式

        table.setShowHorizontalLines(true); //设置是否显示单元格之间的分割线

        table.setShowVerticalLines(true);

        scroll=new JScrollPane(table);  //给表格加上滚动杠

        scroll.setPreferredSize(new Dimension(1000,450));

        contentPane.add(scroll);}

      protected void processWindowEvent(WindowEvent e)

    {   super.processWindowEvent(e);

           if(e.getID()==WindowEvent.WINDOW_CLOSING)

        {   System.exit(0);  }}

    void queryByNoButton_actionPerformed(ActionEvent e) {

          Properties prop =new Properties();

          prop.put("charSet", "gb2312");

            String sql;       

           try{

           Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");  //实例化JDBC-ODBC桥的驱动

                  String url="jdbc:odbc:book1";    //设置连接字符串

                  connect=DriverManager.getConnection(url,prop);//连接数据库  stat=connect.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);

             if(noField.getText().isEmpty())

                    sql="select * from information";

               else

                    sql="select * from information where [name]='"+noField.getText()+"'";

                  rSet=stat.executeQuery(sql);

                  if(rSet.next()==false)

              {    JOptionPane.showMessageDialog(ConsultinformationsFrame.this, "数据库中没有您查询的书籍!","书籍查询",1);     }

                  else {vector.removeAllElements();

                         tm.fireTableStructureChanged();

                         rSet.previous();

                         while(rSet.next()){

                                Vector rec_vector=new Vector();

                                 rec_vector.addElement(new String(rSet.getBytes(1),"gbk"));

                                 rec_vector.addElement(new String(rSet.getBytes(2),"gbk"));

                                 rec_vector.addElement(new String(rSet.getBytes(3),"gbk"));

                                 rec_vector.addElement(new String(rSet.getBytes(4),"gbk"));

                           rec_vector.addElement(new String(rSet.getBytes(5),"gbk"));

                           rec_vector.addElement(rSet.getInt(6) +"");

                        vector.addElement(rec_vector);//向量rec_vector加入向量vector中

                      }}}

           catch(SQLException ex){

            System.out.println("/nSQL操作异常/n");

            while(ex!=null){

                   System.out.println("异常信息:"+ex.getMessage());

                   System.out.println("SQL状态:"+ex.getSQLState());

                   ex=ex.getNextException();

                         }}

            catch(Exception ex) {

               ex.printStackTrace();}

            finally

        {   try{ if(stat!=null)

                       stat.close();

                if(connect!=null)

                       connect.close();

            }catch(SQLException ex){

                   System.out.println("/nSQL操作异常/n");

                   System.out.println("异常信息:"+ex.getMessage());

                   System.out.println("SQL状态:"+ex.getSQLState());

            }}}

  void backButton_actionPerformed(ActionEvent e)

    {   this.dispose();

        MainJFrame m=new MainJFrame();

        m.setLocation(300, 200);

        m.setVisible(true);

    }}

 这部分的代码基本是参考课本的,然后进行主要项目进行修改,数据库的桥连、调用、显示、读取在这里代码给出,后面其他部分调用、使用部分就不重复出现了,在图书查询方面,这个程序做得还是有很大的缺陷的,但是由于时间关系,关键字查询功能不够好,在查询的时候需要完全输入才能查询到数据,如果要进行更进一步的修进的话,可以设置多关键字查询,如作者、图书分类、出版社等进行图书的更好筛选,这样就能更好的让读者可以查询借阅到自己需要的书籍。

3.学生界面

登陆界面后选择学生身份登陆,会调用到学生的账号密码的数据库,调用数据库进行匹配,若匹配成功则进入学生界面,学生界面如上图,具有查询个人信息、个人借阅情况、修改密码、图书查询与预约。个人信息与借阅情况的代码基本是相似的,程序中我们把个人信息与借阅情况都存放在数据库内,通过把登陆时输入的账号赋给Vector vector=new Vector();  

再进行传递,就能实现对数据在数据库的筛选,再通过settext()显示出来。

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         

        PrivateJFrame P=new PrivateJFrame();

        P.setLocation(300, 200);

        P.setVisible(true);     }          

修改密码部分,在写程序的时候遇到的困难是在修改一个密码的时候会整一列的数据全部都修改了,没有进行匹配就全部修改掉,后来知道是没有对其匹配, Privateconsult P = null;然后只对P的数据进行修改就不会出现同样的问题 P.setVisible(true)。

学生查询预订部分,查询的功能跟游客查询的完全一样的,区别在于这里多了一个预约的选项,窗口截图如下:

 private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {                                        

        // TODO add your handling code here:

        Privateconsult P = null;

        try { P = new Privateconsult(); }

        catch (ParseException ex)

    {    Logger.getLogger(StudentJFrame.class.getName()).log(Level.SEVERE, null, ex); }

        P.setLocation(300, 200);      

        P.setVisible(true);

        this.dispose();

    }                           

为了简化程序的难度,在这里的操作只是把预约的书直接当借了处理,更好的名字应该是叫借书,同时这部分也存在一点错误就是对于一些数量为1的书,但是数量大于1的书就预约不了,不知道在哪里出了错误。

4.管理员界面

      1.修改密码

修改密码部分跟学生的操作是一样的,加入的操作是可以对其他管理员的密码进行修改。但是同样问题还是出现了,如果正常去想的话,输入的账号是本来存在的,你修改密码并不会出现什么错误,但是我突然想到既然账号可以填写,我填一个数据库内没有的试试,结果问题真的来了。

我输入一个不存在的账号,密码好像是默认跟登录账号一样的,确定后,提示修改成功,但我有到数据库查找,发现没有增加这个记录项,所以这是一个Bug,不修改好的话,这个图书管理系统可能会被破坏的可能性,问题到打印前还是没有解决,代码如下:

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                        

        // TODO add your handling code here:

        Newpassword N=new Newpassword();

         N.setLocation(300,200);

         N.setVisible(true);

    }                                       

    private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {                                        

        // TODO add your handling code here:

        NewAdmin N=new NewAdmin();

        N.setLocation(300, 200);

        N.setVisible(true);

    }                 

   2.书籍管理

这部分还是有用到前面的图书查询模块,这里增加的功能是管理功能,包括了图书的添加、删除、修改。其中有两个操作不知道问题出在哪里,做添加还有修改的操作是时候会出现这个提示/nSQL操作异常/n    异常信息:[Microsoft][ODBC Microsoft Access Driver] INSERT INTO 语句的语法错误。   但是引用基本一样的代码的学生管理模块,这两项就完全没有错误,两个模块的代码只是修改了应该修改的专属部分,但是却一个可以运行,另外一个却出现了问题,现在也是一筹莫展。

public Informationbook()

    {   informationbookFrame frame=new informationbookFrame();

        if(packOk)   frame.pack();

        else  frame.validate();

        Dimension screenSize=Toolkit.getDefaultToolkit().getScreenSize();

        Dimension frameSize=frame.getSize();

        if(frameSize.height>screenSize.height)

            frameSize.height=screenSize.height-100;

        if(frameSize.width>screenSize.width)

            frameSize.width=screenSize.width;        frame.setLocation((screenSize.width-frameSize.width)/2,(screenSize.height-frameSize.height)/2);

        frame.setVisible(true); }

public static void main(String[] args) {        try{ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());}

catch(Exception e)

        {      e.printStackTrace();   }        new Informationbook( );  }}

class informationbookFrame extends JFrame{

    private JPanel contentPane;

    private FlowLayout myLayout=new FlowLayout( );  //构造XYLayout布局管理器

       //创建显示信息使用的组件

    private JLabel label1=new JLabel("书名");

    private JTextField nameField=new JTextField(8);

    private JLabel label2=new JLabel("作者");

    private JTextField authorField=new JTextField(16);

    private JLabel label3=new JLabel("出版社");

    private JTextField placeField=new JTextField(8);

    private JLabel label4=new JLabel("出版时间");

    private JTextField yearField=new JTextField(8);

    private JLabel label5=new JLabel("单价");

    private JTextField valueField=new JTextField(8);

    private JLabel label6=new JLabel("可借数量");

    private JTextField quanlityField=new JTextField(8);

    private JButton addRecordButton =new JButton("添加");

    private JButton deleteButton=new JButton("删除");

    private JButton updateButton=new JButton("修改");

    private JButton queryByNoButton=new JButton("书籍查询");

    private JButton allRecordButton=new JButton("全部记录");

    private JButton backButton=new JButton("退出");

    Vector vector;

    String title[]={"书名","作者","出版社","出版时间","单价","可借数量"};   // 表头

    Connection connect=null; //声明Connection接口对象connect

    ResultSet rSet=null;        //定义数据库查询的结果集

    Statement stat=null;   //定义查询数据库的Statement对象

    AbstractTableModel tm;      //声明一个AbstractTableModel类对象tm

    public informationbookFrame()

    {  enableEvents(AWTEvent.WINDOW_EVENT_MASK);

        try{ jbInit();}

        catch(Exception e){e.printStackTrace();}}

    private void jbInit() throws Exception{

        contentPane=(JPanel) this.getContentPane();

        //初始化组件

        contentPane.setLayout(myLayout);   //设置容器的布局管理对象

        setSize(new Dimension(1020,600));   //设置容器窗口的大小

        setTitle("书本信息管理系统");

           addRecordButton.addActionListener(new java.awt.event.ActionListener( )

        {//注册按钮事件监听对象,实现ActionListener接口的actionPerformed方法

            public void actionPerformed(ActionEvent e)

            {addRecordButton_actionPerformed(e);}});

        deleteButton.addActionListener(new java.awt.event.ActionListener()  {

           public void actionPerformed(ActionEvent e){deleteButton_actionPerformed(e);}});

        updateButton.addActionListener(new java.awt.event.ActionListener(){

            public void actionPerformed(ActionEvent e)

              { updateButton_actionPerformed(e); }});

        queryByNoButton.addActionListener(new java.awt.event.ActionListener()

        {  public void actionPerformed(ActionEvent e){

                   queryByNoButton_actionPerformed(e);}});

        allRecordButton.addActionListener(new java.awt.event.ActionListener()

        {public void actionPerformed(ActionEvent e)

 {allRecordButton_actionPerformed(e);   // 触发显示所有记录的按钮,显示更新后的结果

       }});

             backButton.addActionListener(new java.awt.event.ActionListener()

       {public void actionPerformed(ActionEvent e)

       {backButton_actionPerformed(e);   // 触发显示所有记录的按钮,显示更新后的结果

            }});

        createTable();  //在初始化函数中调用createtable()函数显示表格

        contentPane.add(label1);

        contentPane.add(nameField);

        contentPane.add(label2);

        contentPane.add(authorField);

        contentPane.add(label3);

        contentPane.add(placeField);

        contentPane.add(label4);

        contentPane.add(yearField);     

        contentPane.add(label5);

        contentPane.add(valueField);     

        contentPane.add(label6);

        contentPane.add(quanlityField);

        contentPane.add(addRecordButton);

        contentPane.add(deleteButton);

        contentPane.add(updateButton);

        contentPane.add(queryByNoButton);

        contentPane.add(allRecordButton);

        contentPane.add(backButton);}

    void createTable(){

           JTable table;

           JScrollPane scroll;

           vector=new Vector();

           tm=new AbstractTableModel(){

            public int getColumnCount(){

                   return title.length;}

            public int getRowCount()

            {return vector.size(); }

            public Object getValueAt(int row,int column){

                if(!vector.isEmpty())

                    return ((Vector)vector.elementAt(row)).elementAt(column);

                else return null;    }

            public void setValueAt(Object value,int row,int column)

            {}

            public String getColumnName(int column)

            {return title[column];}

            public Class getColumnClass(int c)

            {return getValueAt(0,c).getClass();}

            public boolean isCellEditable(int row,int column)

            {return false;} };

        table=new JTable(tm);   //生成数据表

        table.setToolTipText("Display Query Result");   //设置帮助提示

        table.setAutoResizeMode(table.AUTO_RESIZE_ALL_COLUMNS); //设置表格调整尺寸模式

        table.setCellSelectionEnabled(false);   //设置单元格选择方式

        table.setShowHorizontalLines(true); //设置是否显示单元格之间的分割线

        table.setShowVerticalLines(true);

        scroll=new JScrollPane(table);  //给表格加上滚动杠

        scroll.setPreferredSize(new Dimension(1000,450));

        contentPane.add(scroll);

    }protected void processWindowEvent(WindowEvent e){

           super.processWindowEvent(e);

           if(e.getID()==WindowEvent.WINDOW_CLOSING)

        {System.exit(0);}

}

3.注册管理员

      

 private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                        

       try{ Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");//实例化JDBC-ODBC桥的驱动

            connect=DriverManager.getConnection("jdbc:odbc:Admi");//连接数据库

            stat=connect.createStatement();

            String sql="select * from Admins where [count]='"+ jTextField1.getText()+"'";

            rSet=stat.executeQuery(sql);

            if(rSet.next()==true){              

JOptionPane.showMessageDialog(NewAdmin.this, "该管理员已经存在!请选择别的账号!","添加记录",1);              }

这部分就是往数据库添加一个新的项目,没有什么特别可说明注释的。

  4.学生管理

功能、操作类似图书管理,但是这里操作都正常不会出错,只有上面图书管理上出了错。

5.数据库设计

                      管理员信息表(Admin)

                          总书库信息表(book1)

                             个人书库(book2)

     

                                 学生信息表(student)

三 结果及数据分析

这部分的结果以及数据分析都在二中个体功能带过了,这里就略过。

结论

本次课程设计使用了access数据库和Java Swing来实现图形界面的设计,在使用数据库存储图书信息时,遇到了很多问题,有很多问题都解决了,但是还是有很多在写课程报告的时候还没能解决,例如学生界面的预订操作,只是把预订简单的理解为借书处理;以及管理员界面的图书管理里面的添加、修改。都存在问题,程序里面有类似的代码,放在这里就出错误了,很难解。问题还是存在的,但是解决的问题也有很多,所以自己觉得这次课程设计还是有很大的收获的。

       本次课程设计综合考察了我们对Java程序设计知识的掌握熟练程度和实际运用能力。其间,涉及到了Java 中的很多知识点,如Java的类与对象、Java的异常处理机制、Java中的集合框架、Java Swing 图形界面,ODBC的应用,还涉及到图形的布局方式,Java事件监听与处理,Swing组件的使用方面的知识,在使用Java Swing来设计图形界面时,要注意界面的布局方式,一般来说,很少使用单一的布局方式,大多数情况下是综合使用多种布局方式,Swing组件处理布局以外,还要根据实际要求处理是否该组件添加事件处理,比如说是否处理组合框的变化,是否处理复选框的变化以及在如何响应组件状态的变化,这里可以举一个简单的例子,比如说性别组合框,当用户改变选择时,就要求根据用户的选择更新用户的性别信息,当然实际情况是不可能只是监听一个组件状态的变化的,这就要求根据组件的不同选择不同的监听方式,可以采用匿名类来处理,也可以采用外部类来处理

本次课程设计要求实现图书信息的管理,虽然完成了基本的图书信息管理功能,但还是有很多的不足,比如说图形界面不是很美观,出错处理不够,再有就是存储的图书信息的不是很多,只存储了常用的几种图书信息,这主要是考虑到实用性,所以忽略了很多不常用的图书信息,如果在实际应时是则必须添上,如果信息不是很重要,在设计数据表时,可以指定可以为空,但是在显示是就不能简单的将图书信息全部显示出来,还有判断是否为空,以及为空时的处理,这样的程序当然很全面,但是作为一个课程设计,是没有必要储存如此多的图书信息的。

问题与讨论

存在问题:为什么在图书的添加、修改上跟学生资料的代码基本完全一样,但是却会出问题?

有待讨论改进程序方向:图书馆所有书籍的分类管理、图书查询时实现多关键字操作、对出版时间的限制(月份天数)、从目前的单机版->网络版。

六 参考文献

[1]  JAVA灵感编程[M]. 北京: 电子工业出版社, 2002.7

[2]  皮德常. Java简明教程[M]. 清华大学出版社, 2011.2

[3] Harvey M.Deitel.java程序设计教程.机械工业出版社,2004.9

[4]  D.M.吉瑞, A.L.麦克莱伦. JAVA图形设计[M]. 机械工业出版社, 1997.7

相关推荐