实验十五 GUI编程练习与应用程序部署
一、知识学习部分
清单文件
每个JAR文件中包含一个用于描述归档特征的清单文件(manifest)。清单文件被命名为MANIFEST.MF,它位于JAR文件的一个特殊的META-INF子目录中。
最小的符合标准的清单文件是很简单的:Manifest-Version:1.0复杂的清单文件包含多个条目,这些条目被分成多个节。第一节被称为主节,作用于整个JAR文件。随后的条目用来指定已命名条目的属性,可以是文件、包或者URL。
清单文件的节与节之间用空行分开,最后一行必须以换行符结束。否则,清单文件将无法被正确地读取。
– 创建一个包含清单的JAR文件,应该运行:
jar cfm MyArchive.jar manifest.mf com/*.class
要更新一个已有JAR文件的清单,则需要将增加的部分
放置到一个文本文件中,运行如下命令:
jar ufm MyArchive.jar manifest-additions.mf
运行JAR文件
用户可以通过下面的命令来启动应用程序:
java –jar MyProgram.jar
窗口操作系统,可通过双击JAR文件图标来启动应用程序。
资源
Java中,应用程序使用的类通常需要一些相关的数据文件,这些文件称为资源(Resource)。
–图像和声音文件。
–带有消息字符串和按钮标签的文本文件。
–二进制数据文件,如:描述地图布局的文件。
类加载器知道如何搜索类文件,直到在类路径、存档文件或Web服务器上找到为止。
利用资源机制对于非类文件也可以进行同样操作,具体步骤如下:
– 获得资源的Class对象。
– 如果资源是一个图像或声音文件,那么就需要调用getresource(filename)获得资源的URL位置,然后利用getImage或getAudioClip方法进行读取。
– 如果资源是文本或二进制文件,那么就可以使用getResouceAsStream方法读取文件中的数据。
资源文件可以与类文件放在同一个目录中,也可以将资源文件放在其它子目录中。具体有以下两种方式:
–相对资源名:如data/text/about.txt它会被解释为相对于加载这个资源的类所在的包。
–绝对资源名:如/corejava/title.txt
ResourceTest.java程序演示了资源加载的过程。
编译、创建JAR文件和执行这个程序的命令如下: – javac ResourceTest.java – jar cvfm ResourceTest.jar ResourceTest.mf *.class *.gif *.txt – java –jar ResourceTest.jar
实验时间 2018-12-6
1、实验目的与要求
(1) 掌握Java应用程序的打包操作;
(2) 了解应用程序存储配置信息的两种方法;
(3) 掌握基于JNLP协议的java Web Start应用程序的发布方法;
(5) 掌握Java GUI 编程技术。
2、实验内容和步骤
实验1: 导入第13章示例程序,测试程序并进行代码注释。
测试程序1
1.在elipse IDE中调试运行教材585页程序13-1,结合程序运行结果理解程序;
2.将所生成的JAR文件移到另外一个不同的目录中,再运行该归档文件,以便确认程序是从JAR文件中,而不是从当前目录中读取的资源。
3.掌握创建JAR文件的方法;
1 package resource;
2
3 import java.awt.*; 4 import java.io.*; 5 import java.net.*; 6 import java.util.*; 7 import javax.swing.*; 8 9 /** 10 * @version 1.41 2015-06-12 11 * @author Cay Horstmann 12 */ 13 public class ResourceTest 14 { 15 public static void main(String[] args) 16 { 17 EventQueue.invokeLater(() -> { 18 JFrame frame = new ResourceTestFrame(); 19 frame.setTitle("ResourceTest"); 20 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 21 frame.setVisible(true); 22 }); 23 } 24 } 25 26 /** 27 * 一个加载图像和文本资源的框架。 28 */ 29 class ResourceTestFrame extends JFrame 30 { 31 private static final int DEFAULT_WIDTH = 300; 32 private static final int DEFAULT_HEIGHT = 300; 33 34 public ResourceTestFrame() 35 { 36 setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); 37 URL aboutURL = getClass().getResource("about.gif"); 38 Image img = new ImageIcon(aboutURL).getImage(); 39 setIconImage(img); 40 41 JTextArea textArea = new JTextArea(); 42 InputStream stream = getClass().getResourceAsStream("about.txt"); 43 try (Scanner in = new Scanner(stream, "UTF-8")) 44 { 45 while (in.hasNext()) 46 textArea.append(in.nextLine() + "\n"); 47 } 48 add(textArea); 49 } 50 }
测试程序2
1.在elipse IDE中调试运行教材583页-584程序13-2,结合程序运行结果理解程序;
2.了解Properties类中常用的方法;
1 package properties;
2
3 import java.awt.EventQueue; 4 import java.awt.event.*; 5 import java.io.*; 6 import java.util.Properties; 7 8 import javax.swing.*; 9 10 /** 11 * 一个测试属性的程序。 程序记住帧的位置、大小和标题 12 * @version 1.01 2015-06-16 13 * @author Cay Horstmann 14 */ 15 public class PropertiesTest 16 { 17 public static void main(String[] args) 18 { 19 EventQueue.invokeLater(() -> { 20 PropertiesFrame frame = new PropertiesFrame(); 21 frame.setVisible(true); 22 }); 23 } 24 } 25 26 /** 27 * 从属性文件和更新恢复位置和大小的框架。退出时的属性。 28 */ 29 class PropertiesFrame extends JFrame 30 { 31 private static final int DEFAULT_WIDTH = 300; 32 private static final int DEFAULT_HEIGHT = 200; 33 34 private File propertiesFile; 35 private Properties settings; 36 37 public PropertiesFrame() 38 { 39 // 从属性获取位置、大小、标题 40 41 String userDir = System.getProperty("user.home"); 42 File propertiesDir = new File(userDir, ".corejava"); 43 if (!propertiesDir.exists()) propertiesDir.mkdir(); 44 propertiesFile = new File(propertiesDir, "program.properties"); 45 46 Properties defaultSettings = new Properties(); 47 defaultSettings.setProperty("left", "0"); 48 defaultSettings.setProperty("top", "0"); 49 defaultSettings.setProperty("width", "" + DEFAULT_WIDTH); 50 defaultSettings.setProperty("height", "" + DEFAULT_HEIGHT); 51 defaultSettings.setProperty("title", ""); 52 53 settings = new Properties(defaultSettings); 54 55 if (propertiesFile.exists()) 56 try (InputStream in = new FileInputStream(propertiesFile)) 57 { 58 settings.load(in); 59 } 60 catch (IOException ex) 61 { 62 ex.printStackTrace(); 63 } 64 65 int left = Integer.parseInt(settings.getProperty("left")); 66 int top = Integer.parseInt(settings.getProperty("top")); 67 int width = Integer.parseInt(settings.getProperty("width")); 68 int height = Integer.parseInt(settings.getProperty("height")); 69 setBounds(left, top, width, height); 70 71 // 如果没有标题,请询问用户 72 73 String title = settings.getProperty("title"); 74 if (title.equals("")) 75 title = JOptionPane.showInputDialog("Please supply a frame title:"); 76 if (title == null) title = ""; 77 setTitle(title); 78 79 addWindowListener(new WindowAdapter() 80 { 81 public void windowClosing(WindowEvent event) 82 { 83 settings.setProperty("left", "" + getX()); 84 settings.setProperty("top", "" + getY()); 85 settings.setProperty("width", "" + getWidth()); 86 settings.setProperty("height", "" + getHeight()); 87 settings.setProperty("title", getTitle()); 88 try (OutputStream out = new FileOutputStream(propertiesFile)) 89 { 90 settings.store(out, "Program Properties"); 91 } 92 catch (IOException ex) 93 { 94 ex.printStackTrace(); 95 } 96 System.exit(0); 97 } 98 }); 99 } 100 }
测试程序3
1.在elipse IDE中调试运行教材593页-594程序13-3,结合程序运行结果理解程序;
2.了解Preferences类中常用的方法;
1 package preferences;
2
3 import java.awt.*; 4 import java.io.*; 5 import java.util.prefs.*; 6 7 import javax.swing.*; 8 import javax.swing.filechooser.*; 9 10 /** 11 * 一个测试偏好设置的程序。程序记住框架。位置、大小和标题。 12 * @version 1.03 2015-06-12 13 * @author Cay Horstmann 14 */ 15 public class PreferencesTest 16 { 17 public static void main(String[] args) 18 { 19 EventQueue.invokeLater(() -> { 20 PreferencesFrame frame = new PreferencesFrame(); 21 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 22 frame.setVisible(true); 23 }); 24 } 25 } 26 27 /** 28 * 从用户偏好恢复位置和大小并在退出时更新首选项的框架。 29 */ 30 class PreferencesFrame extends JFrame 31 { 32 private static final int DEFAULT_WIDTH = 300; 33 private static final int DEFAULT_HEIGHT = 200; 34 private Preferences root = Preferences.userRoot(); 35 private Preferences node = root.node("/com/horstmann/corejava"); 36 37 public PreferencesFrame() 38 { 39 // 从偏好获得位置、大小、标题 40 41 int left = node.getInt("left", 0); 42 int top = node.getInt("top", 0); 43 int width = node.getInt("width", DEFAULT_WIDTH); 44 int height = node.getInt("height", DEFAULT_HEIGHT); 45 setBounds(left, top, width, height); 46 47 // 如果没有标题,请询问用户 48 49 String title = node.get("title", ""); 50 if (title.equals("")) 51 title = JOptionPane.showInputDialog("Please supply a frame title:"); 52 if (title == null) title = ""; 53 setTitle(title); 54 55 // 设置显示XML文件的文件选择器 56 57 final JFileChooser chooser = new JFileChooser(); 58 chooser.setCurrentDirectory(new File(".")); 59 chooser.setFileFilter(new FileNameExtensionFilter("XML files", "xml")); 60 61 // 设置菜单 62 63 JMenuBar menuBar = new JMenuBar(); 64 setJMenuBar(menuBar); 65 JMenu menu = new JMenu("File"); 66 menuBar.add(menu); 67 68 JMenuItem exportItem = new JMenuItem("Export preferences"); 69 menu.add(exportItem); 70 exportItem 71 .addActionListener(event -> { 72 if (chooser.showSaveDialog(PreferencesFrame.this) == JFileChooser.APPROVE_OPTION) 73 { 74 try 75 { 76 savePreferences(); 77 OutputStream out = new FileOutputStream(chooser 78 .getSelectedFile()); 79 node.exportSubtree(out); 80 out.close(); 81 } 82 catch (Exception e) 83 { 84 e.printStackTrace(); 85 } 86 } 87 }); 88 89 JMenuItem importItem = new JMenuItem("Import preferences"); 90 menu.add(importItem); 91 importItem 92 .addActionListener(event -> { 93 if (chooser.showOpenDialog(PreferencesFrame.this) == JFileChooser.APPROVE_OPTION) 94 { 95 try 96 { 97 InputStream in = new FileInputStream(chooser 98 .getSelectedFile()); 99 Preferences.importPreferences(in); 100 in.close(); 101 } 102