2. Planificación del proyecto
2.5. Gestión de recursos
Most developers stumble upon pitfalls sequentially, based on their experience level with Java. The setSize()pitfall usually presents itself shortly after Java developers begin serious GUI development, specifically when they try to set the size of their first newly created custom components. BadSetSize, as follows, creates a simple custom button that we want to size to 100 by 100 pixels. Here is the code to create our custom button:
class CustomButton extends Button {
public CustomButton(String title) {
super(title); setSize(100,100); }
}
In the constructor, developers often mistakenly assume that they can use set- Size()(width, height)in the same way they do when sizing a frame. The prob- lem arises when the developer hasn’t yet gained the knowledge of the Abstract Windowing Toolkit’s (AWT) inner workings to understand that this code will only work under certain situations. He or she has no idea that setSize()will fail to cor- rectly size the component. For example, when we place our custom button in the frame with other components using a simple grid layout, we get the results in Figure 16.1. Our button is 66 by 23, not 100 by 100! What happened to our call to setSize()? The method was executed, of course. However, it did not give the final word on the size of our component.
Listing 16.1 shows the source code for BadSetSize.java.
Figure 16.1 Run of BadSetSize.class.
5This pitfall was first published by JavaWorld(www.javaworld.com) in the article “Steer clear
of Java Pitfalls”, September 2000 (http://www.javaworld.com/javaworld/jw-09-2000 /jw-0922-javatraps.html?) and is reprinted here with permission. The pitfall has been updated from reader feedback.
01: package org.javapitfalls.item16; 02:
03: import java.awt.*; 04: import java.awt.event.*; 05:
06: class CustomButton extends Button 07: {
08: public CustomButton(String title) 09: { 10: super(title); 11: setSize(100,100); 12: } 13: } 14:
15: public class BadSetSize extends Frame 16: {
17: TextArea status; 18:
19: public BadSetSize() 20: {
21: super(“Bad Set Size”); 22:
23: setLayout(new GridLayout(2,0,2,2)); 24: Panel p = new Panel();
25: CustomButton button = new CustomButton(“Press Me”); 26: p.add(button);
27: add(p);
28: status = new TextArea(3, 50);
29: status.append(“Button size before display: “ + Æ button.getSize() + “\n”);
30: add(status);
31: addWindowListener(new WindowAdapter() 32: {
33: public void windowClosing(WindowEvent we) 34: { System.exit(1); }
35: }); 36: setLocation(100,100); 37: pack();
38: setVisible(true);
39: status.append(“Button size after display: “ + Æ button.getSize());
40: } 41:
42: public static void main(String args []) 43: {
44: new BadSetSize(); 45: }
46: }
Let’s examine the correct approach to sizing a component. The key to understand- ing why our code failed is to recognize that after we create the component, the layout manager—called GridLayout—reshapes the component in accordance with its own rules. This presents us with several solutions. We could eliminate the layout manager by calling setLayout(null), but as the layout manager provides numerous benefits to our code, this is a poor remedy. If the user resizes the window, we still want to be able to automatically resize our user interface, which is the layout manager’s chief benefit. Another alternative would be to call setSize()after the layout manager has completed its work. This only provides us with a quick fix: By calling repaint(), the size would change, yet again when the browser is resized. That leaves us with only one real option: Work with the layout manager only to resize the component. Below we rewrite our custom component:
class CustomButton2 extends Button {
public CustomButton2(String title) {
super(title);
// setSize(100,100); - unnecessary }
public Dimension getMinimumSize() { return new Dimension(100,100); } public Dimension getPreferredSize() { return getMinimumSize(); } }
Our custom component overrides the getMinimumSize()and getPreferred- Size()methods of the Componentclass to set the component size. The layout man- ager invokes these methods to determine how to size an individual component. Some layout managers will disregard these hints if their pattern calls for that. For example, if this button was placed in the center of a BorderLayout, the button would not be 100 by 100, but instead would stretch to fit the available center space. GridLayoutwill abide by these sizes and anchor the component in the center. The GoodSetSizeclass below uses the CustomButton2class.
01: package org.javapitfalls.item16; 02:
03: import java.awt.*; 04: import java.awt.event.*; 05:
06: class CustomButton2 extends Button 07: {
08: public CustomButton2(String title) 09: {
10: super(title);
11: System.out.println(“Size of button is : “ + this.getSize()); 12: }
13:
14: public Dimension getMinimumSize()
15: { return new Dimension(100,100); } 16:
17: public Dimension getPreferredSize()
18: { return getMinimumSize(); } 19: }
20:
21: public class GoodSetSize extends Frame 22: {
23: TextArea status; 24:
25: public GoodSetSize() 26: {
27: super(“Good Set Size”); 28:
29: setLayout(new GridLayout(2,0)); 30: Panel p = new Panel();
31: CustomButton2 button = new CustomButton2(“Press Me”); 32: p.add(button);
33: add(p);
34: status = new TextArea(3,50);
35: status.append(“Button size before display: “ + Æ button.getSize() + “\n”);
36: add(status);
37: addWindowListener(new WindowAdapter() 38: {
39: public void windowClosing(WindowEvent we) 40: { System.exit(1); }
41: }); 42: setLocation(100,100); 43: pack();
44: setVisible(true);
45: status.append(“Button size after display: “ + Æ button.getSize());
46: } 47:
48: public static void main(String args []) 49: {
50: new GoodSetSize(); 51: }
52: }
Figure 16.2 Run of GoodSetSize.class.
Running GoodSetSize.java results in Figure 16.2.
It is interesting to note that our solution to setting the size of a component involved not using the setSize()method. This pitfall is caused by the design complexity of a cross-platform user interface and a developer’s unfamiliarity with the chain of events necessary to display and resize an interface. Unfortunately, the supplied documenta- tion of setSize()fails to suggest these prerequisites.
This solution also highlights the importance of properly naming methods and para- meters. Should you use setSize()when you only need to set some internal values that may or may not be used by your display mechanisms? A better choice would be
setInternalValues(), which at least clearly warns a developer of the limited guar- antee this method offers.
Item 17: When Posting to a URL Won’t
6Now that the Simple Object Access Protocol (SOAP) and other variants of XML Remote Procedure Calls (RPC) are becoming popular, posting to a Uniform Resource Locator (URL) will be a more common and more important operation. While implementing a standalone SOAP server, I stumbled across multiple pitfalls associated with posting to a URL; starting with the nonintuitive design of the URL-related classes and ending with specific usability pitfalls in the URLConnectionclass.