Professional Documents
Culture Documents
July04 JohnZ
July04 JohnZ
// 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
gridx
0
1
2
0
2
0
1
gridy
0
0
0
1
1
2
2
gridwidth
1
1
1
2
1
1
1
gridheight
1
1
1
1
2
1
1
JarFile(File file)
JarFile(File file, boolean verify)
JarFile(File file, boolean verify, int mode)
JarFile(String name)
JarFile(String name, boolean verify)
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
import
import
import
java.io.*;
java.util.*;
java.util.zip.*;
java.util.jar.*;
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 File trail
(http://java.sun.com/tutorial/jar/) in The Java Tutorial.
. . . . . . . . . . . . . . . . . . . . . . .
IMPORTANT: Please read our Terms of Use, Privacy, and Licensing
policies:
http://www.sun.com/share/text/termsofuse.html
http://www.sun.com/privacy/
http://developers.sun.com/dispatcher.jsp?uid=6910008
* FEEDBACK
Comments? Please enter your feedback on the Tech Tips at:
http://developers.sun.com/contact/feedback.jsp?category=sdn
* SUBSCRIBE/UNSUBSCRIBE
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 JDC publications:
- Go to the JDC Newsletters and Publications page,
(http://developer.java.sun.com/subscription/),
choose the newsletters you want to subscribe to and click
"Update".
- To unsubscribe, go to the subscriptions page,
(http://developer.java.sun.com/subscription/),
uncheck the appropriate checkbox, and click "Update".
- To use our one-click unsubscribe facility, see the link at
the end of this email:
- ARCHIVES
You'll find the Core Java Technologies Tech Tips archives at:
http://java.sun.com/developer/TechTips/index.html
- COPYRIGHT
Copyright 2004 Sun Microsystems, Inc. All rights reserved.
4150 Network Circle, Santa Clara, California 95054 USA.
This document is protected by copyright. For more information, see:
http://java.sun.com/jdc/copyright.html
Core Java Technologies Tech Tips
July 27, 2004
Trademark Information: http://www.sun.com/suntrademarks/
Java, J2SE, J2EE, J2ME, and all Java-based marks are trademarks
or registered trademarks of Sun Microsystems, Inc. in the
United States and other countries.