Errata

Swing Hacks

Errata for Swing Hacks

Submit your own errata for this product.

The errata list is a list of errors and their corrections that were found after the product was released.

The following errata were submitted by our customers and have not yet been approved or disproved by the author or editor. They solely represent the opinion of the customer.

Color Key: Serious technical mistake Minor technical mistake Language or formatting error Typo Question Note Update

Version Location Description Submitted by Date submitted
Printed Page 51
Hack 11 source code example 1-27

In both Hack #11 (menu with drop shadow) & #12 (transparency to menu), demonstration source code compiles, but generates runtime errors relating to call to UIManager.put( --- ). Removing the call produces executable code, but without the intended menu effects. Runtime error is "UIDefaults.getUI() failed: no ComponentUI class for JPopupMenu"

Thomas Sharp  Jun 27, 2019 
Printed Page 68
Example 2-7

The code is not correct for shift/ctrl & click selections.
Examples:
- click on first item, then shift click on 5th item: only items 2 - 5 are checked
- select one item, then ctrl click on this item: the item should be unchecked but is still checked

Another problem is that the user is expecting that the checkboxes toggle if clicked. This is not true
if only one item is selected (i.e. you can check an item but not uncheck it)

Anonymous   
Printed Page 68
Last paragraph

Hi,
The hack for checkable JList's works correctly with one exception. Once an item is selected, and
being the only selected item, if we want to deselect it, it will not allow us.
The reason for this: the ListSelectionEvent doesn't go through, since at the JList level, the
selection is still the same. So in order to do it, one is forced to select another item, and then
come back to the previous one.
So we need an extra hack on top of this hack ;)
Below is the code and comments:
//inner class to CheckBoxJList
class MyMouseAdapter extends MouseAdapter {
/* note: this works because the ListSelection event always is produced before the MouseEvent */
public void mouseClicked(MouseEvent evt) {
if (!listEvtProduced) { //only react when a list event has not been produced
//instead of manipulating the model and cached selections, we simply produce the event so it gets
handled by the Listener method
VersionJList.this.valueChanged(new ListSelectionEvent(VersionJList.this, 0, 0, false));
} else { //reset
listEvtProduced = false;
}
}
}

//private field CheckBoxJList also for this added hack
private boolean listEvtProduced;

//finally, in the valueChanged() method, after the line:
addListSelectionListener(this);
the following line must be added:
listEvtProduced=true;

Anonymous   
Printed Page 86
Bottom Note

Hack # 17 - Reorder a JList with Drad-and-Drop.

To add an item after last item in list, simply add a blank list item to the back of the list. Prevent this item from being dragged. Therefore you can now drop before the last ( null ) empty which equates to adding an item to the end of the list.

Anonymous  Nov 05, 2008 
Printed Page 127
last sentence of second to last paragraph: "The book code has a sample..."

Well, the statement is "The book code has a sample of the latter with HSQLDB values as defaults."

I have yet to find such a sample and without it Hack #24 is almost impossible to run.

Anonymous   
Printed Page 236
Inside method actionPerformed of Example 6-9

The animated sheet hack works great, but only once - try calling the showJDialogAsSheet method again, and the incoming/outgoing sheet image is painted in the topleft corner of the glass pane.

I found that the following change fixes it:

##
// used by the Timer
public void actionPerformed (ActionEvent e) {
if (animating) {
// calculate height to show
float animationPercent =
(System.currentTimeMillis() - animationStart) /
ANIMATION_DURATION;
animationPercent = Math.min (1.0f, animationPercent);
int animatingHeight = 0;
if (animationDirection == INCOMING) {
animatingHeight =
(int) (animationPercent * sheet.getHeight());
} else {
animatingHeight =
(int) ((1.0f - animationPercent) * sheet.getHeight());
}
// clip off that much from sheet and blit it
// into animatingSheet
animatingSheet.setAnimatingHeight (animatingHeight);
- animatingSheet.repaint();
+ glass.revalidate();

if (animationPercent >= 1.0f) {
stopAnimation();
if (animationDirection == INCOMING) {
finishShowingSheet();
} else {
glass.removeAll();
glass.setVisible(false);
}
}
}
}
##

As glass.revalidate() triggers animatingSheet.repaint(), this modification ensures that everything continues to work smoothly.

Jan Schenkel  Feb 10, 2009 
Printed Page 311-312
Within the drawLiquidButton source code

protected void drawLiquidButton(Color base,
int width, int height,
String text, float scale,
Graphics2D g2) {

// calculate inset
int inset = (int)(scale*0.04f);
int w = width - inset*2 - 1;
int h = height - (int)(scale*0.1f) - 1;


g2.translate(inset,0);
drawDropShadow(w,h,scale,g2);

if(pressed) {
g2.translate(0, 0.04f*scale);
}

drawButtonBody(w,h,scale,base,g2);
drawText(w,h,scale,text,g2);
drawHighlight(w,h,scale,base,g2);
drawBorder(w,h,scale,g2);

if(pressed) {
g2.translate(0, 0.04f*scale);
}
g2.translate(-inset,0);
}
Is the drawLiquidButton method in the book, there are two if(pressed) blocks which translate the g2 object the same way, the second should actually read

if(pressed) {
g2.translate(0, -(0.04f*scale));
}

Colin Sowter  Sep 09, 2009 
PDF Page 397
Source code snippet at bottom

The following line of code is incorrect:

int bytesPerSec = format.getSampleSizeInBits() *
(int) format.getSampleRate();

This computes the bits per second, not bytes per second. As a result, the buffer is 8 times larger than it should be.

Vocaro  May 12, 2009 
Printed, PDF, Page 398
Example10-11

The source code has two significant errors.

1) The conversion of two bytes to a signed short has a serious flaw that fails to convert certain combinations properly. For example, the bytes 0xFA and 0xFB will improperly convert to -5 as opposed to -1285.

The code as printed is:

// deal with endianness
int hiByte = (bigEndian ? buffer[i] : buffer[i+1]);
int loByte = (bigEndian ? buffer[i+1] : buffer [i]);
if (signed) {
short shortVal = (short) hiByte;
shortVal = (short) ((shortVal << 8) | (byte) loByte);
value = shortVal;
} else {
value = (hiByte << 8) | loByte;
}

The proper conversion in Java of two bytes to a signed short is:

shortVal = (short) ((hiByte << 8) | (loByte & 0xFF));

This code yields a correct result of -1285 using the example values above.

2) The calculation of a maximum value in the algorithm is flawed if the data are signed. Pressure values in the sampled data can be negative. The calculation of the maximum should be absolute value, so as not to ignore negative pressure values. The change I suggest is that the TWO lines of

max = Math.max (max, value);

in the algorithm should be become

max = Math.max (max, Math.abs(value));

Christopher Fuhrman  Jan 28, 2012