-
Bug
-
Resolution: Fixed
-
P4
-
1.2.2
-
beta
-
generic
-
generic
Name: skT88420 Date: 11/11/99
java version "1.2.2"
Classic VM (build JDK-1.2.2-W, native threads, symcjit)
Creating a custom AbstractButton implementation that behaves like a JButton
doesn't work with Metal Look&Feel (Windows and Motif l&f are ok).
Below is a source code that doesn't work (to be compiled with JDK 1.2.x).
//-----------------------------------
// MyCustomButton.java
import javax.swing.*;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.IOException;
import javax.accessibility.*;
import java.awt.image.*;
import javax.swing.plaf.*;
import javax.swing.event.*;
class MyCustomButton extends AbstractButton {
public static void main(String[] args) {
try {
// Windows & Motif l&f are correct
//UIManager.setLookAndFeel(new
com.sun.java.swing.plaf.windows.WindowsLookAndFeel());
//UIManager.setLookAndFeel(new
com.sun.java.swing.plaf.motif.MotifLookAndFeel());
// Metal l&f is not!
UIManager.setLookAndFeel(new javax.swing.plaf.metal.MetalLookAndFeel());
JFrame frame = new JFrame("Sun Bug Report");
MyCustomButton button = new MyCustomButton();
frame.getContentPane().add(button);
frame.setSize(200,200);
frame.setVisible(true);
} catch (Exception e) { e.printStackTrace();}
}
//////////////////////////////////////////
// Original SWING 1.2.2 JButton Implementation
//////////////////////////////////////////
/*
* @version 1.73 09/01/98
* @author Jeff Dinkins
* @see ButtonGroup
*/
//public class JButton extends AbstractButton implements Accessible {
/**
* @see #getUIClassID
* @see #readObject
*/
private static final String uiClassID = "ButtonUI";
private boolean defaultCapable = true;
/**
* Creates a button with no set text or icon.
*/
public MyCustomButton() {
this(null, null);
}
/**
* Creates a button with an icon.
*
* @param icon the Icon image to display on the button
*/
public MyCustomButton(Icon icon) {
this(null, icon);
}
/**
* Creates a button with text.
*
* @param text the text of the button
*/
public MyCustomButton(String text) {
this(text, null);
}
/**
* Creates a button with initial text and an icon.
*
* @param text the text of the button.
* @param icon the Icon image to display on the button
*/
public MyCustomButton(String text, Icon icon) {
// Create the model
setModel(new DefaultButtonModel());
// initialize
init(text, icon);
}
/**
* Notification from the UIFactory that the L&F
* has changed.
*
* @see JComponent#updateUI
*/
public void updateUI() {
setUI((ButtonUI)UIManager.getUI(this));
}
/**
* Returns a string that specifies the name of the L&F class
* that renders this component.
*
* @return "ButtonUI"
* @see JComponent#getUIClassID
* @see UIDefaults#getUI
* @beaninfo
* expert: true
* description: A string that specifies the name of the L&F class.
*/
public String getUIClassID() {
return uiClassID;
}
/**
* Returns whether or not this button is the default button
* on the RootPane.
*
* @return "boolean"
* @see JRootPane#setDefaultButton
* @beaninfo
* description: Whether or not this button is the default button
*/
public boolean isDefaultButton() {
JRootPane root = SwingUtilities.getRootPane(this);
if (root != null) {
return (AbstractButton) root.getDefaultButton() == this;
}
return false;
}
/**
* Returns whether or not this button is capable of being
* the default button on the RootPane.
*
* @return "boolean"
* @see #setDefaultCapable
* @see #isDefaultButton
* @see JRootPane#setDefaultButton
*/
public boolean isDefaultCapable() {
return defaultCapable;
}
/**
* Sets whether or not this button is capable of being
* the default button on the RootPane.
*
* @return "boolean"
* @see #isDefaultCapable
* @beaninfo
* bound: true
* attribute: visualUpdate true
* description: Whether or not this button can be the default button
*/
public void setDefaultCapable(boolean defaultCapable) {
boolean oldDefaultCapable = this.defaultCapable;
this.defaultCapable = defaultCapable;
firePropertyChange("defaultCapable", oldDefaultCapable, defaultCapable);
}
/**
* See readObject() and writeObject() in JComponent for more
* information about serialization in Swing.
*/
private void writeObject(ObjectOutputStream s) throws IOException {
s.defaultWriteObject();
if ((ui != null) && (getUIClassID().equals(uiClassID))) {
ui.installUI(this);
}
}
/**
* Returns a string representation of this JButton. This method
* is intended to be used only for debugging purposes, and the
* content and format of the returned string may vary between
* implementations. The returned string may be empty but may not
* be <code>null</code>.
*
* @return a string representation of this JButton.
*/
protected String paramString() {
String defaultCapableString = (defaultCapable ? "true" : "false");
return super.paramString() +
",defaultCapable=" + defaultCapableString;
}
/////////////////
// Accessibility support
////////////////
/**
* Get the AccessibleContext associated with this JComponent
*
* @return the AccessibleContext of this JComponent
* @beaninfo
* expert: true
* description: The AccessibleContext associated with this Button.
*/
public AccessibleContext getAccessibleContext() {
if (accessibleContext == null) {
accessibleContext = new AccessibleJButton();
}
return accessibleContext;
}
/**
* The class used to obtain the accessible role for this object.
* <p>
* <strong>Warning:</strong>
* Serialized objects of this class will not be compatible with
* future Swing releases. The current serialization support is appropriate
* for short term storage or RMI between applications running the same
* version of Swing. A future release of Swing will provide support for
* long term persistence.
*/
protected class AccessibleJButton extends AccessibleAbstractButton {
/**
* Get the role of this object.
*
* @return an instance of AccessibleRole describing the role of the
* object
* @see AccessibleRole
*/
public AccessibleRole getAccessibleRole() {
return AccessibleRole.PUSH_BUTTON;
}
} // inner class AccessibleJButton
}
//----------------------------------------
The execution of this class generates the following exception:
============================================
Exception occurred during event dispatching:
java.lang.ClassCastException: MyCustomButton
at
javax.swing.plaf.metal.MetalBorders$ButtonBorder.paintBorder(MetalBorders.java:6
2)
at javax.swing.border.CompoundBorder.paintBorder(CompoundBorder.java:99)
at javax.swing.JComponent.paintBorder(JComponent.java:484)
at javax.swing.AbstractButton.paintBorder(AbstractButton.java:752)
at javax.swing.JComponent.paint(JComponent.java:639)
at javax.swing.JComponent.paintWithBuffer(JComponent.java:3701)
at javax.swing.JComponent._paintImmediately(JComponent.java:3646)
at javax.swing.JComponent.paintImmediately(JComponent.java:3496)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:365)
at
javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(SystemEventQueueU
tilities.java:191)
at
javax.swing.SystemEventQueueUtilities.processRunnableEvent(SystemEventQueueUtili
ties.java:366)
at
javax.swing.SystemEventQueueUtilities.access$0(SystemEventQueueUtilities.java:36
2)
at
javax.swing.SystemEventQueueUtilities$RunnableTarget.processEvent(SystemEventQue
ueUtilities.java:403)
at java.awt.Component.dispatchEventImpl(Component.java:2394)
at java.awt.Component.dispatchEvent(Component.java:2307)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:287)
at
java.awt.EventDispatchThread.pumpOneEvent(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:92)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:83)
Exception occurred during event dispatching:
java.lang.ClassCastException: MyCustomButton
at
javax.swing.plaf.metal.MetalBorders$ButtonBorder.paintBorder(MetalBorders.java:6
2)
at javax.swing.border.CompoundBorder.paintBorder(CompoundBorder.java:99)
at javax.swing.JComponent.paintBorder(JComponent.java:484)
at javax.swing.AbstractButton.paintBorder(AbstractButton.java:752)
at javax.swing.JComponent.paint(JComponent.java:639)
at javax.swing.JComponent.paintChildren(JComponent.java:452)
at javax.swing.JComponent.paint(JComponent.java:641)
at javax.swing.JComponent.paintChildren(JComponent.java:452)
at javax.swing.JComponent.paint(JComponent.java:641)
at javax.swing.JLayeredPane.paint(JLayeredPane.java:547)
at javax.swing.JComponent.paintChildren(JComponent.java:452)
at javax.swing.JComponent.paint(JComponent.java:626)
at java.awt.Container.paint(Container.java:773)
at sun.awt.windows.WComponentPeer.handleEvent(WComponentPeer.java:117)
at java.awt.Component.dispatchEventImpl(Component.java:2447)
at java.awt.Container.dispatchEventImpl(Container.java:1035)
at java.awt.Window.dispatchEventImpl(Window.java:749)
at java.awt.Component.dispatchEvent(Component.java:2307)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:287)
at
java.awt.EventDispatchThread.pumpOneEvent(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:92)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:83)
==============================================================
The problem is caused by line 62 of file MetalBorders.java, that reads
JButton button = (JButton) c;
instead it should be (like it is in the other look&feel code)
AbstractButton button = (AbstractButton) c;
Regards
(Review ID: 97750)
======================================================================