Submitted On 23-OCT-2003
stephanemorin
may be i will say something stupid, but can't we do a extends
method which able/disable AND set black/grey in same time?
Submitted On 03-JAN-2004
daleanson
This class works fairly well, use it in place of JButton
where needed:
import javax.swing.*;
public class HtmlButton extends JButton {
private String html = "<html>";
private String disabledColor = "<font color=\"gray\">";
public HtmlButton() {
super();
}
public HtmlButton(String text) {
super(text);
}
public void setEnabled( boolean b ) {
if ( getText().startsWith( html ) ) {
String text = getText();
text = text.substring( html.length() );
if ( b ) {
if ( text.startsWith( disabledColor ) ) {
text = text.substring( disabledColor.length() );
text = html + text;
}
}
else {
text = html + disabledColor + text;
}
setText( text );
}
super.setEnabled( b );
}
}
Submitted On 07-MAY-2004
Okke.Harsta
HtmlWindowButtonUI extends WindowsButtonUI {
private final static HtmlWindowButtonUI
buttonUI = new HtmlWindowButtonUI ();
public static ComponentUI createUI(JComponent c) {
return buttonUI;
}
public void paint(Graphics g, JComponent
c) {
super.paint(g, c);
if (c.isEnabled()) {
c.setForeground
(someStaticConfiguredColor); //Color.BLACK
}
else {
c.setForeground
(someStaticConfiguredColor); //Color.GRAY
}
}
Submitted On 14-JUL-2004
OoPee
I like daleanson's helper class, but found you need to replace the "if(b)" block in setEnabled() by this:
if ( b ) {
if ( text.startsWith( disabledColor ) ) {
text = text.substring( disabledColor.length() );
}
text = html + text;
}
Otherwise, enabling an already enabled button removes
the HTML tag.
Submitted On 27-JUL-2004
jimhardwicktsi
In order to correctly handle multiple calls to setEnable(), change the class as follows:
import javax.swing.*;
public class HtmlButton extends JButton {
private String html = "<html>";
private String disabledColor = "<font color=\"gray\">";
public HtmlButton() {
super();
}
public HtmlButton(String text) {
super(text);
}
public void setEnabled(boolean b) {
if(getText().startsWith(html)) {
String text = getText();
text = text.substring(html.length());
if(text.startsWith(disabledColor)) {
text = text.substring(disabledColor.length());
}
if(b) {
text = html + text;
} else {
text = html + disabledColor + text;
}
setText(text);
}
super.setEnabled(b);
}
}
You can also extend a JToggleButton with this class if you'd like the disabled text on a toggle button.
Submitted On 14-MAR-2005
weiming_kang
There is a question about font where setText() on a jLabel : two charactors have lap over. Here is the part of resource:
<html>
webcom<font color=red>puting</font>
</html>
if i do it , charactor "m" and charactor "p" will lap over partially
Submitted On 27-OCT-2005
AKNet
I changed a little workaround to maximize performance:
public class HtmlButton2 extends JButton {
private String html = "<html>";
private String disabledColor = "<font color=\"gray\">";
String enabledText;
String disabledText;
boolean isHtml;
public HtmlButton2() {
super();
}
public HtmlButton2(String text) {
super(text);
}
public void setText(String text) {
if (text.startsWith(html)) {
isHtml = true;
enabledText = text;
text = text.substring(html.length());
disabledText = html + disabledColor + text;
if (isEnabled()) {
setTextImpl(enabledText);
}
else {
setTextImpl(disabledText);
}
}
else {
isHtml = false;
enabledText = text;
disabledText = text;
setTextImpl(enabledText);
}
}
protected void setTextImpl(String text) {
super.setText(text);
}
public void setEnabled(boolean b) {
if (isHtml) {
if (b) {
setTextImpl(enabledText);
}
else {
setTextImpl(disabledText);
}
}
super.setEnabled(b);
}
public static void main(String[] args) {
final HtmlButton2 hb2 = new HtmlButton2();
final HtmlButton2 hb3 = new HtmlButton2();
hb2.setText("<html> one <br> two </html>");
hb3.setText("<html> two <br> two </html>");
hb2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
hb3.setEnabled(true);
hb2.setEnabled(false);
}
});
hb3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
hb2.setEnabled(true);
hb3.setEnabled(false);
}
});
JFrame frame = new JFrame();
frame.getContentPane().add(hb2, BorderLayout.WEST);
frame.getContentPane().add(hb3, BorderLayout.EAST);
frame.pack();
frame.show();
}
}
Submitted On 08-NOV-2005
import java.awt.*;
import javax.swing.*;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicHTML;
import javax.swing.text.View;
import com.sun.java.swing.plaf.windows.WindowsButtonUI;
import java.awt.image.BufferedImage;
public class WindowsMLButtonUI
extends WindowsButtonUI
implements SwingConstants
{
// Shared UI object
private final static WindowsMLButtonUI buttonUI = new WindowsMLButtonUI();
private JComponent dummy = new JButton();
private WindowsMLButtonUI() {
super();
}
// ********************************
// Create PLAF
// ********************************
public static ComponentUI createUI(JComponent c)
{
return buttonUI;
}
/* These rectangles/insets are allocated once for all
* ButtonUI.paint() calls. Re-using rectangles rather than
* allocating them in each paint call substantially reduced the time
* it took paint to run. Obviously, this method can't be re-entered.
*/
private static Rectangle viewRect = new Rectangle();
private static Rectangle textRect = new Rectangle();
private static Rectangle iconRect = new Rectangle();
// ********************************
// Paint Methods
// ********************************
public void paint(Graphics g, JComponent c)
{
AbstractButton b = (AbstractButton) c;
ButtonModel model = b.getModel();
FontMetrics fm = g.getFontMetrics();
Insets i = c.getInsets();
viewRect.x = i.left;
viewRect.y = i.top;
viewRect.width = b.getWidth() - (i.right + viewRect.x);
viewRect.height = b.getHeight() - (i.bottom + viewRect.y);
textRect.x = textRect.y = textRect.width = textRect.height = 0;
iconRect.x = iconRect.y = iconRect.width = iconRect.height = 0;
Font f = c.getFont();
g.setFont(f);
// layout the text and icon
String text = SwingUtilities.layoutCompoundLabel(
c, fm, b.getText(), b.getIcon(),
b.getVerticalAlignment(), b.getHorizontalAlignment(),
b.getVerticalTextPosition(), b.getHorizontalTextPosition(),
viewRect, iconRect, textRect,
b.getText() == null ? 0 : b.getIconTextGap());
clearTextShiftOffset();
// perform UI specific press action, e.g. Windows L&F shifts text
if (model.isArmed() && model.isPressed())
{
paintButtonPressed(g, b);
}
// Paint the Icon
if (b.getIcon() != null)
{
paintIcon(g, c, iconRect);
}
if (text != null && !text.equals(""))
{
View v = (View) c.getClientProperty(BasicHTML.propertyKey);
if (v != null)
{
if (model.isEnabled())
{
v.paint(g, textRect);
}
else
{
// Draw the standard color html into a dummy graphic
// needed as this calculates if there is enough room for the text and resizes
// the button if there is not enough room.
Image dummyImg = b.createImage(1,1);
Graphics gDummy = dummyImg.getGraphics();
gDummy.setClip(0,0,1,1);
v.paint(gDummy, textRect);
Color color = UIManager.getColor("Button.disabledForeground");
Color shadow = UIManager.getColor("Button.disabledShadow");
// now draw the html in a brighter highlight
dummy.setForeground(shadow);
View disabledView = BasicHTML.createHTMLView(dummy, b.getText());
disabledView.paint(g, textRect);
// now draw the html in a darker disabled colour one pixel offset from the
// highlight
g.translate( -1, -1);
dummy.setForeground(color);
disabledView = BasicHTML.createHTMLView(dummy, b.getText());
disabledView.paint(g, textRect);
}
}
else
{
// Plain text button
super.paint(g,c);
}
}
if (b.isFocusPainted() && b.hasFocus())
{
// paint UI specific focus
paintFocus(g, b, viewRect, textRect, iconRect);
}
}
}
then create a button:
button.setUI((WindowsMLButtonUI)WindowsMLButtonUI.createUI(test));
Submitted On 15-MAR-2006
MichaelScheper
One point that most of you are overlooking is that inactive text is not always grey, or even 'gray'. Here's some code to make your solutions less platform-dependent:
private static String to2CharHexString(int i) {
byte b = (byte) i;
if (b > 15) {
return Integer.toHexString(b);
}
return "0" + Integer.toHexString(b);
}
String enabledHTML = "<font color=\"#" + to2CharHexString(SystemColor.textText.getRed()) + to2CharHexString(SystemColor.textText.getGreen()) + to2CharHexString(SystemColor.textText.getBlue()) + "\">";
String disabledHTML = "<font color=\"#" + to2CharHexString(SystemColor.textInactiveText.getRed()) + to2CharHexString(SystemColor.textInactiveText.getGreen()) + to2CharHexString(SystemColor.textInactiveText.getBlue()) + "\">";
Then just use those strings instead of the hard-coded <color> tags you're using.
Submitted On 18-JUL-2006
A solution I've found to work:
btn.setForeground(SystemColor.textInactiveText);
directly before/after your call to setEnable, and:
btn.setForeground(SystemColor.textText);
directly before/after your subsequent call. I've found it to have the exact same effect (And then some, for platform/skin independency) as merely adding <font color="gray"> right after <html>.
-Tianon
Submitted On 18-JUL-2006
Class implementing my work-around:
public class TButton extends JButton {
public void setEnabled(boolean b) {
if(getText().startsWith("<html>")) {
if(b)
setForeground(SystemColor.textText);
else
setForeground(SystemColor.textInactiveText);
}
super.setEnabled(b);
}
}
-Tianon
Submitted On 18-JUL-2006
About that class, you'll have to add the constructors you need yourself. Java isn't grabbing them automagically. (Forgot about that...)
My apologies,
-Tianon
Submitted On 09-JUN-2007
sad8c7wefv78
Tianon, unfortunately your fix looks bad on Windows.
Submitted On 26-JUN-2008
andrew_krieg
Both the disabledForeground and the disabledShadow should be updated when disabling components using HTML tags in their text. Not having this feature makes pluggable L&F sort of useless if you have to manually override these properties for every component type that displays text.
Submitted On 26-JUN-2008
fix the problem in java side
Submitted On 26-JUN-2008
fix the problem in java
Submitted On 26-JUN-2008
fix the problem in java side
Submitted On 19-AUG-2008
bencole
This is sort of like Tianon's method, but it queries the current L&F for the active & inactive foreground defaults:
import java.awt.Color;
import javax.swing.JLabel;
import javax.swing.UIManager;
public class Label extends JLabel {
//constructors & other methods...
public void setEnabled(boolean b) {
if (b == isEnabled()) return;
if (getText().startsWith("<html>")) {
setForeground(b ? (Color) UIManager.getDefaults().get("Label.foreground")
: (Color) UIManager.getDefaults().get("Label.disabledForeground"));
}
super.setEnabled(b);
}
}
or, for a JButton you could use (I believe):
setForeground(b ? (Color) UIManager.getDefaults().get("Button.foreground")
: (Color) UIManager.getDefaults().get("Button.disabledText"));
Submitted On 17-SEP-2008
girikm
since html is used with swing components, the pirority could be increased.
Submitted On 17-OCT-2008
Barend
Here's my take on a work-around, nicely self-contained.
/**
* Attaches to a JButton to work around Sun bug 4783068.
* <p>http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4783068</p>
*/
public final class SunBug4783068Fixer implements PropertyChangeListener {
private static final SunBug4783068Fixer INSTANCE = new SunBug4783068Fixer();
public static void attach(AbstractButton to) {
// Prevents adding it more than once to any single component.
to.removePropertyChangeListener(INSTANCE);
to.addPropertyChangeListener(INSTANCE);
}
public static void remove(AbstractButton from) {
from.removePropertyChangeListener(INSTANCE);
}
public void propertyChange(PropertyChangeEvent evt) {
if ((evt.getSource() instanceof AbstractButton)
&& "enabled".equals(evt.getPropertyName())) {
AbstractButton target = (AbstractButton) evt.getSource();
target.setForeground(target.isEnabled()
? (Color) UIManager.getDefaults().get("Button.foreground")
: (Color) UIManager.getDefaults().get("Button.disabledText"));
}
}
}
Submitted On 06-FEB-2009
lisc
Barend 's solution is pretty good!
PLEASE NOTE: JDK6 is formerly known as Project Mustang
|