» 您尚未 登录   注册 | 社区服务 | FTP中心 | 帮助 | 社区 | 无图版 | 测试百科  | 测试Blog 
软件测试基地论坛 -> 测试开发技术 -> [转帖]In this Issue
 XML   RSS 2.0   WAP 

--> 本页主题: [转帖]In this Issue 加为IE收藏 | 收藏主题 | 上一主题 | 下一主题
Fastpoint


该用户目前不在线
级别: 总版主
精华: 44
发帖: 5033
基地声望: 390 点
基地币: 1683 Bug
基地贡献: 0 点
好评度: 15 点
在线时间:818(小时)
注册时间:2005-10-08
最后登录:2008-07-22
查看作者资料 发送短消息 推荐此帖 引用回复这个帖子

[转帖]In this Issue

Welcome to the Core Java Technologies Tech Tips for July 27, 2004. Here you'll get tips on using core Java technologies and APIs, such as those in Java 2 Platform, Standard Edition (J2SE).

This issue covers:

-Using GridBagLayout
-Updating JAR Files

These tips were developed using Java 2 SDK, Standard Edition, v 1.4.2.

This issue of the Core Java Technologies Tech Tips is written by John Zukowski, president of JZ Ventures, Inc.

See the Subscribe/Unsubscribe note at the end of this newsletter to subscribe to Tech Tips that focus on technologies and products in other Java platforms.

For more Java technology content, visit these sites:

java.sun.com - The latest Java platform releases, tutorials, and newsletters.

java.net - A web forum for collaborating and building solutions together.

java.com - The marketplace for Java technology, applications and services.

.
.

USING GRIDBAGLAYOUT

Layout managers abstract away the rules for the layout of child components in a container. They help in the creation of cross-platform graphical user interfaces. Instead of relying on exact positioning, such as saying "place this button at position (100, 250)," you provide a set of rules to follow in the form of a layout manager. Then, through the layout manager, you position graphical components, such as buttons and labels, by following the rules. For instance, with the FlowLayout manager, components are placed next to each other. The components wrap when the screen width is too small to fit all of them on one line. With BorderLayout, you place components on the edges of the screen, using hints such as North, South, East, or West. Using the simpler layout managers such as FlowLayout and BorderLayout, you can place containers inside containers and in this way create many desired screen layouts. For more complicated screens, and as an alternative to placing containers inside containers, you can use the more complex GridBagLayout manager and its associated GridBagConstraints support class. The GridBagLayout manager and the GridBagConstraints class allow you to build more complicated screens inside a single container.

The basis of the GridBagLayout is positioning components inside a grid. Another layout manager, GridLayout, also works with a grid. GridLayout-managed components are typically positioned based on the order in which components are added to the container. The GridLayout doesn't offer the flexibility provided by GridBagLayout. You get more explicitly positioned components when using GridBagLayout, and you have additional options available regarding the number of row and columns to span, how to allocate additional screen area, and how much space to use for padding around components.

To demonstrate, the following program, GridBagSample, creates a screen with seven buttons in a three-by-three grid.

   import java.awt.*;
   import javax.swing.*;

   public class GridBagSample {

     // Shared empty insets
     private static final Insets insets = new Insets(0,0,0,0);

     public static void main(String args[]) {
       Runnable runner = new Runnable() {
         public void run() {
           JFrame frame = new JFrame("GridBagLayout");
           frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
           Container c = frame.getContentPane();
           c.setLayout(new GridBagLayout());

           JButton one = new JButton("One");
           GridBagConstraints constraints =
             new GridBagConstraints(
               0, 0, // gridx, gridy
               1, 1, // gridwidth, gridheight
               0.0, 0.0, // weightx, weighty
               GridBagConstraints.CENTER, // anchor
               GridBagConstraints.BOTH, // fill
               // GridBagConstraints.NONE, // fill
               // GridBagConstraints.VERTICAL, // fill
               // GridBagConstraints.HORIZONTAL, // fill
               insets, // insets
               0, // ipadx
               0); // ipady
           c.add(one, constraints);

           JButton two = new JButton("Two");
           constraints =
             new GridBagConstraints(
               1, 0, // gridx, gridy
               1, 1, // gridwidth, gridheight
               1.0, 0.0, // weightx, weighty
               GridBagConstraints.CENTER, // anchor
               GridBagConstraints.BOTH, // fill
               // GridBagConstraints.NONE, // fill
               // GridBagConstraints.VERTICAL, // fill
               // GridBagConstraints.HORIZONTAL, // fill
               insets, // insets
               0, // ipadx
               0); // ipady
           c.add(two, constraints);

           JButton three = new JButton("Three");
           constraints =
             new GridBagConstraints(
               2, 0, // gridx, gridy
               1, 1, // gridwidth, gridheight
               0.0, 0.0, // weightx, weighty
               GridBagConstraints.CENTER, // anchor
               GridBagConstraints.BOTH, // fill
               // GridBagConstraints.NONE, // fill
               // GridBagConstraints.VERTICAL, // fill
               // GridBagConstraints.HORIZONTAL, // fill
               insets, // insets
               0, // ipadx
               0); // ipady
           c.add(three, constraints);

           JButton four = new JButton("Four");
           constraints =
             new GridBagConstraints(
               0, 1, // gridx, gridy
               2, 1, // gridwidth, gridheight
               1.0, 1.0, // weightx, weighty
               GridBagConstraints.CENTER, // anchor
               GridBagConstraints.BOTH, // fill
               // GridBagConstraints.NONE, // fill
               // GridBagConstraints.VERTICAL, // fill
               // GridBagConstraints.HORIZONTAL, // fill
               insets, // insets
               0, // ipadx
               0); // ipady
           c.add(four, constraints);

           JButton five = new JButton("Five");
           constraints =
             new GridBagConstraints(
               2, 1, // gridx, gridy
               1, 2, // gridwidth, gridheight
               0.0, 1.0, // weightx, weighty
               GridBagConstraints.CENTER, // anchor
               GridBagConstraints.BOTH, // fill
               // GridBagConstraints.NONE, // fill
               // GridBagConstraints.VERTICAL, // fill
               // GridBagConstraints.HORIZONTAL, // fill
               insets, // insets
               0, // ipadx
               0); // ipady
           c.add(five, constraints);

           JButton six = new JButton("Six");
           constraints =
             new GridBagConstraints(
               0, 2, // gridx, gridy
               1, 1, // gridwidth, gridheight
               0.0, 0.0, // weightx, weighty
               GridBagConstraints.CENTER, // anchor
               GridBagConstraints.BOTH, // fill
               // GridBagConstraints.NONE, // fill
               // GridBagConstraints.VERTICAL, // fill
               // GridBagConstraints.HORIZONTAL, // fill
               insets, // insets
               0, // ipadx
               0); // ipady
           c.add(six, constraints);

          JButton seven = new JButton("Seven");
           constraints =
             new GridBagConstraints(
               1, 2, // gridx, gridy
               1, 1, // gridwidth, gridheight
               1.0, 0.0, // weightx, weighty
               GridBagConstraints.CENTER, // anchor
               GridBagConstraints.BOTH, // fill
               // GridBagConstraints.NONE, // fill
               // GridBagConstraints.VERTICAL, // fill
               // GridBagConstraints.HORIZONTAL, // fill
               insets, // insets
               0, // ipadx
               0); // ipady
           c.add(seven, constraints);
           frame.pack();
           frame.show();
         }
       };
       EventQueue.invokeLater(runner);
     }
   }

Looking at the screen output, notice how some buttons cross over multiple rows and columns. Resizing the screen also demonstrates another feature of GridBagLayout. You have total control over which rows and columns get additional space as a screen grows.

Each component added to a container that is being laid out by GridBagLayout should be associated with a constraints object, GridBagConstraints. This object communicates the specific constraints for that component to the layout manager.

There are many different types of constraints. Each controls the layout of the associated component. Each constraint is a public field of the class. Constraints can either be set all at once through the constructor, or individually through direct access to its field. There are no setter or getter methods for these fields.

Let's examine the constraints:

anchor

The anchor specifies the direction in which the component will drift when it is smaller than available space. CENTER is the default. The eight compass points represent the other settings. Each setting is a constant that can be assigned to the field. The possible settings are:

   CENTER
   EAST
   NORTH
   NORTHEAST
   NORTHWEST
   SOUTH
   SOUTHEAST
   SOUTHWEST
   WEST

Additional constraints are available that position components based on the current ComponentOrientation. Their settings for the typical English horizontal, left-to-right orientations are shown below following the constants:

   FIRST_LINE_END (NORTHEAST)
   FIRST_LINE_START  (NORTHWEST)
   LAST_LINE_END (SOUTHEAST)
   LAST_LINE_START (SOUTHWEST)
   LINE_END (EAST)
   LINE_START (WEST)
   PAGE_START (NORTH)
   PAGE_END (SOUTH)

fill

The value of fill controls the component's resize policy when more space is available.. If fill is set to NONE (the default), the GridBagLayout manager tries to give the component its preferred size. If fill is set to VERTICAL, the layout manager resizes the component's height (that is, if additional space is available). For HORIZONTAL, the layout manager resizes width. If fill is set to BOTH, the layout manager takes advantage of all the space available in both directions.

The previous example program, GridBagSample, had a fill of BOTH. Try running the program with another fill value: VERTICAL, HORIZONTAL, or NONE. Uncomment out the appropriate fill setting line to get the desired results. For example, here is the result produced if fill is set for all seven buttons to NONE.

gridx and gridy

The gridx and gridy variables specify the component's position in the grid. The gridx variable specifies the cell that contains the component's leftmost position. The gridy variable specifies the cell that contains the component's top position. Cell (0, 0) is the cell at the origin of the screen (top left). Because components can span multiple cells, the gridx, gridy location is typically the starting cell of the component. Although you can explicitly specify the cells directly, you can also use the RELATIVE constant for either setting. A gridx setting of RELATIVE results in the new component to the right of the prior one. For gridy, that component would start a new row and be below the prior one.

gridheight and gridwidth

The gridheight and gridwidth fields specify the number of cells along the horizontal (gridwidth) and vertical (gridheight) axis that a component should occupy. In addition to specifying the number of cells in a column and row, you can also use the class constants RELATIVE and REMAINDER. Specifying a RELATIVE setting for either field results in that component being the second-to-last component in the column (gridheight) or row (gridwidth). The REMAINDER setting is reserved for specifying the last element of the respective column or row. Until you are comfortable with using GridBagLayout, it tends to be easier to directly specify the gridx, gridy, gridheight, and gridwidth settings, instead of relying on RELATIVE and REMAINDER. Even after developing a level of comfort, you might find that you still prefer to avoid using RELATIVE and REMAINDER.

insets

The insets field specifies the external padding, in pixels, around the component. The padding represents empty space. Think of the padding as a transparent border around the component. In setting the insets field, you specify the values individually for the top, bottom, left, and right padding. Notice that in the GridBagSample program the insets setting is (0,0,0,0) and it's set for a common Insets object.

ipadx and ipady

The ipadx and ipady fields specify the internal padding for a component. The ipdax field adds padding to the width of a component. The ipady field adds padding to the height of a component. For instance, the ipadx setting reserves extra space around both the right and left sides of the component.

weightx and weighty

The weightx and weighty settings allow you to control which components grow or shrink when space is available in the container, for example, when the user resizes the screen. The weight settings are doubles (all the other settings besides insets are int values).

Typically, the weightx and weighty settings are in the range of 0.0 to 1.0. A setting of 0.0 means the component gets no extra space. A setting of 1.0 means the component gets all the extra space (or at least, the component shares the extra space with other components that have a setting of 1.0). Although you can limit the settings to be within 0.0 to 1.0, any settings are accepted. The system will allocate space proportionally to the sum of settings for a specific row or column. For instance, four components with a setting of 1.0 will share extra space equally. Three settings of 0.0 and one of 1.0 gives all the extra space to one component. One component at 0.0, two at 0.5, and one with a weight of 1.0 gives the 1.0 component half the extra space, and splits the remaining extra space between the two 0.5 components.

If your screen sizes are resizable, don't forget to think about what the various weight settings need to be. Smart use of the combined settings for anchor and weightx/weighty allow your components to "hug" screen edges on resize, and to grow proportionally, keeping screens in balance.

Try changing some of the GridBagConstraints settings in the GridBagSample program and see what happens. Here's a table that lists the initial GridBagConstraints settings in the program.

Component gridx gridy gridwidth gridheight
One 0 0 1 1
Two 1 0 1 1
Three 2 0 1 1
Four 0 1 2 1
Five 2 1 1 2
Six 0 2 1 1
Seven 1 2 1 1

For more information on using GridBagLayout and GridBagConstraints, see the How to Use GridBagLayout trail in the Java Tutorial.

Also, before you take advantage of GridBagLayout and its related GridBagConstraints, you might want to pick up some graph paper. As you design screens that require you to bridge multiple rows or columns, it might be helpful to draw the components in their grid positions beforehand.

.
.

UPDATING JAR FILES

As is the case for ZIP files, JAR files are used to package multiple files together, such as classes, images, and sounds. You have a choice of tools to create JAR files. You can use the jar command-line tool that comes with the J2SE Software Development Kit (SDK) or you can use the classes in the java.util.jar package. Although the command-line tool allows you to add files to an existing JAR file, there is no way to programmatically add a file. Also, there is no way using the SDK or the command-line tool to delete a single file from a JAR or delete multiple files. Instead, to update an existing JAR file, you must create a new JAR file and copy any desired content from the old JAR file.

Before showing how to update an existing JAR, let's examine the java.util.jar package and see how to list the contents of a JAR file. The key classes of the API are JarFile and JarEntry. The JarFile class provides a reference to the whole JAR file, the JarEntry class points to each of the files contained within the JAR.

There are five ways to create a JAR file using JarFile:

  • JarFile(File file)
  • JarFileFile file, boolean verify)
  • JarFile(File file, boolean verify, int mode)
  • JarFile(String name)
  • JarFile(String name, boolean verify)

Essentially, you can specify the location as either a File object or a text string. The verify flag indicates whether or not the file should be verified if it is signed. The default (if the flag is not specified) is to verify the file. If access is denied, the security manager throws a security exception. The mode setting is created with the help of two class constants of ZipFile: OPEN_READ or OPEN_READ | OPEN_DELETE. If OPEN_DELETE is set, the file is flagged for deletion by the system.

Here's an example of using JarFile:

  JarFile jar = new JarFile("myjar.jar");

After you have a reference to a JAR file, you get its list of entries with the entries method. This method returns an Enumeration of JarEntry objects. For each JarEntry object, you can get specific information about that entry. For example, you can get its name or size, with getName and getSize respectively. Most of these informational methods are inherited from the parent ZipEntry class.

Here's a simple program, ListJar, that lists the contents of JAR files specified from the command line. Because standard ZIP files are JAR files without the optional manifest, the program works with ZIP files, too.

   import java.io.*;
   import java.util.*;
   import java.util.jar.*;

   public class ListJar {
     public static void main(String args[]) {
       for (int i=0, n=args.length; i<n; i++) {
         try {
           listjar(args);
         } catch (IOException e) {
           System.err.println("Problems reading: " + args);
         }
       }
     }

     private static void listjar(String name) 
             throws IOException {
       System.out.println("Jar: " + name);
       JarFile jar = new JarFile(name);
       Enumeration e = jar.entries();
       while (e.hasMoreElements()) {
         listInfo((JarEntry)e.nextElement());
       }
       System.out.println();
     }

    private static void listInfo(JarEntry entry) {
       System.out.println("\t" + entry.getName());
    }
   }

For example, if you have a jar file named myjar.jar that contains three class files: AmbientEx, CutAndShuffle, and GridBagSample, running the ListJar program against the jar file:

    java ListJar myjar.jar

displays the following:

   META-INF/
   META-INF/MANIFEST.MF
   AmbientEx.class
   CutAndShuffle.class
   GridBagSample.class
   SpotEx.class

Now let's explore updating a JAR, by adding a new file. To update a JAR file, you must create a copy of the original, update the copy, remove the original JAR file, and then rename the updated JAR to the original name. Deletion generally works the same way, but instead of adding a new file to the JAR, you don't copy one or more of the entries.

The general process of updating a JAR works similarly to listing the contents. However instead of getting the name of each JarEntry, you get the InputStream for the entry and write the contents to the new destination. In addition to writing the bytes, you have to tell the JAR file about each entry through the putNextEntry method.

   while (entries.hasMoreElements()) {
     JarEntry entry = (JarEntry) entries.nextElement();
     InputStream is = jar.getInputStream(entry);
     newJar.putNextEntry(entry);
     while ((bytesRead = is.read(buffer)) != -1) {
       newJar.write(buffer, 0, bytesRead);
     }
  }

The output here is written to an instance of type JarOutputStream. It deals with the compression.

  File tempJar = File.createTempFile(nameOfJar, null);
  JarOutputStream newJar = 
    new JarOutputStream(
      new FileOutputStream(tempJar));

Provided that there are no problems with the update, don't forget to delete the original JAR file and rename the new file to the original. You don't want to use the OPEN_DELETE flag here, in case an error occurs during processing.

   if (success) {
     File origFile = new File(nameOfJar);
     origFile.delete();
     tempJar.renameTo(origFile);
   }

Here's a program that puts all these steps together for you.

   import java.io.*;
   import java.util.*;
   import java.util.zip.*;
   import java.util.jar.*;
   
   public class AddFileToJar {
   
     public static void main(String args[]) {
       if (args.length != 2) {
         System.err.println(
           "command: java AddFileToJar example.jar filetoadd.txt");
         System.exit(-1);
       }
   
       String nameOfJar = args[0];
       String nameToAdd = args[1];
   
       File tempJar = null;
       try {
         tempJar = File.createTempFile(nameOfJar, null);
       } catch (IOException e) {
         System.err.println("Unable to create intermediate file.");
         System.exit(-2);
       }
   
       JarFile jar = null;
       try {
         jar = new JarFile(nameOfJar);
       } catch (IOException e) {
         System.err.println("Unable to access original file.");
         System.exit(-3);
       }
   
       // Only rename file at end on success
       boolean success = false;
   
       try {
   
         JarOutputStream newJar =
           new JarOutputStream(
             new FileOutputStream(tempJar));
   
         byte buffer[] = new byte[1024];
         int bytesRead;
   
         try {
           FileInputStream fis = new FileInputStream(nameToAdd);
   
           // Add back the original files
   
           Enumeration entries = jar.entries();
   
           while (entries.hasMoreElements()) {
             // Prompt for copy
             JarEntry entry = (JarEntry) entries.nextElement();
             String name = entry.getName();
             System.out.println
               ("Copy " + name + " into new jar? (y or n)");
             BufferedReader reader = 
               new BufferedReader
                 (new InputStreamReader(System.in));
             String line = reader.readLine();
             if ("n".equals(line)) {
               // if user enters n, don't copy file, 
               // move to next name
               System.out.println("Skipping: " + name);
               continue;
             }
             InputStream is = jar.getInputStream(entry);
             newJar.putNextEntry(entry);
             while ((bytesRead = is.read(buffer)) != -1) {
               newJar.write(buffer, 0, bytesRead);
             }
           }
   
           // Add new file last
           try {
             JarEntry entry = new JarEntry(nameToAdd);
             newJar.putNextEntry(entry);
   
             while ((bytesRead = fis.read(buffer)) != -1) {
               newJar.write(buffer, 0, bytesRead);
             }
           } finally {
             fis.close();
           }
           success = true;
         } catch (IOException ex) {
           System.err.println
             ("Operation aborted due to : " + ex);
         } finally {
           try {
             newJar.close();
           } catch (IOException ignored) {
           }
         }
       } catch (IOException ex) {
         System.err.println(
           "Can't access new file");
       } finally {
         try {
           jar.close();
         } catch (IOException ignored) {
         }
   
         if (!success) {
           tempJar.delete();
         }
       }
   
       if (success) {
         File origFile = new File(nameOfJar);
         origFile.delete();
         tempJar.renameTo(origFile);
       }
     }
   }

The AddFileToJar program displays various prompts. If you run the program without specifying the required parameters (a target JAR file and a file to add), it displays:

   command: java AddFileToJar example.jar filetoadd.txt

The program also prompts you to copy each file to the target JAR file:

   Copy AmbientEx.class into new jar? (y or n)

To delete a file from the JAR, respond "n" to the prompt for that file.

Suppose you used AddFileToJar to add a file to myjar.jar:

   java AddFileToJar myjar.jar DirectionalEx.class

After responding "y" to all the prompts, you should see the added file in the JAR file contents:

    java ListJar myjar.jar
    
   META-INF/
   META-INF/MANIFEST.MF
   AmbientEx.class
   CutAndShuffle.class
   GridBagSample.class
   SpotEx.class
   DirectionalEx.class

If you copy all the original files to the new file, the program has roughly the same effect as using the -u option of the jar command line tool. Earlier versions of the tool did not have -u. Not copying an original file means you've deleted that file from the archive.

For more information on JAR files, see the Jar Files trail in The Java Tutorial.

.
.
Rate and Review
Tell us what you think of the content of this page.
Excellent   Good   Fair   Poor  
Comments:
If you would like a reply to your comment, please submit your email address:
Note: We may not respond to all submitted comments.
.
.

IMPORTANT: Please read our Licensing, Terms of Use, and Privacy policies:
http://developer.java.sun.com/berkeley_license.html

http://www.sun.com/share/text/termsofuse.html


Privacy Statement: Sun respects your online time and privacy (http://sun.com/privacy). You have received this based on your email preferences. If you would prefer not to receive this information, please follow the steps at the bottom of this message to unsubscribe.

Comments? Send your feedback on the Core Java Technologies Tech Tips to: http://developers.sun.com/contact/feedback.jsp?category=newslet

Subscribe to other Java developer Tech Tips:

- Enterprise Java Technologies Tech Tips. Get tips on using enterprise Java technologies and APIs, such as those in the Java 2 Platform, Enterprise Edition (J2EE).
- Wireless Developer Tech Tips. Get tips on using wireless Java technologies and APIs, such as those in the Java 2 Platform, Micro Edition (J2ME).

To subscribe to these and other Sun Developer Network publications:
- Go to the Sun Developer Network Subscriptions page, choose the newsletters you want to
subscribe to and click "Update".
- To unsubscribe, go to the
subscriptions page, uncheck the appropriate checkbox, and click "Update".


ARCHIVES: You'll find the Core Java Technologies Tech Tips archives at:
http://java.sun.com/developer/JDCTechTips/index.html


Copyright 2004 Sun Microsystems, Inc. All rights reserved.
4150 Network Circle, Santa Clara, CA 95054 USA.


This document is protected by copyright. For more information, see:
http://java.sun.com/developer/copyright.html


Java, J2SE, J2EE, J2ME, and all Java-based marks are trademarks or registered trademarks (http://www.sun.com/suntrademarks/) of Sun Microsystems, Inc. in the United States and other countries.



可不可不要这么样徘徊在目光内
你会察觉到我根本寂寞难耐
即使千多百个深夜曾在梦境内
我有吻过你这毕竟并没存在

人声车声开始消和逝
无声挣扎有个情感奴隶
是我多么的想她
但我偏偏只得无尽叹谓

其实每次见你我也着迷
无奈你我各有角色范围
就算在寂寞梦内超出好友关系
唯在暗里爱你暗里着迷
无谓要你惹上各种问题
共我道别吧别让空虚使我越轨
[楼 主] | Posted: 2006-03-15 10:15 顶端

软件测试基地论坛 -> 测试开发技术




软件测试基地上海测仕信息技术有限公司旗下网站
Copyright © 2005-2007 Cntesting.com, All Rights Reserved
沪ICP备06057721号

Powered by PHPWind Code © 2003-06 PHPWind
Total 0.161441(s) query 4, Time now is:11-24 04:14, Gzip disabled
You can contact us


每日一句:Loading...