Thanks,
--
Knute Johnson
I don't see anyway to differentiate the foreground color of a menu item
when it's enabled vs when it's disabled. You could use a change
listener, which will fire whenever the state is changed from enabled to
disabled or vice-versa.
JMenuItem jMenuItem2 = ...
jMenuItem2.addChangeListener(new javax.swing.event.ChangeListener()
{
public void stateChanged(javax.swing.event.ChangeEvent evt) {
jMenuItem2StateChanged(evt);
}
});
...
private void jMenuItem2StateChanged(
javax.swing.event.ChangeEvent evt)
{
System.out.println( "jMenuItem2StateChanged - "+ evt );
JMenuItem jm = ((JMenuItem)evt.getSource());
System.out.println( "Enabled: "+jm.isEnabled() );
if( jm.isEnabled() ) {
jm.setForeground( Color.red );
} else {
jm.setForeground( Color.yellow );
}
}
This seemed to work reliably for me, changing the menu text color from
red when enabled and yellow ("brighter") when disabled. You could
encapsulate this into a new kind of JMenuItem if you need it really
frequently, I suppose.
Thanks for that but apparently I asked the wrong question. Why can't I
change the foreground color on my JMenuItem like you can? I'm running
1.7 on Windows XP. It may be something different with the LookAndFeel.
--
Knute Johnson
> Thanks for that but apparently I asked the wrong question. Why can't I
> change the foreground color on my JMenuItem like you can? I'm running
> 1.7 on Windows XP. It may be something different with the LookAndFeel.
I'm running Java 7 on Windows 7. My LNF is just the default one (might
be Synth). I was running within NetBeans 7.0.1 IDE. Can't say why it
doesn't work for you.
Have the related UI defaults for MenuItem.* changed?
<http://tips4java.wordpress.com/2008/10/09/uimanager-defaults/>
--
John B. Matthews
trashgod at gmail dot com
<http://sites.google.com/site/drjohnbmatthews>
I don't know.
> <http://tips4java.wordpress.com/2008/10/09/uimanager-defaults/>
I hadn't remembered that technique for changing the defaults but I only
want to change one JMenuItem's disabled foreground color. That defaults
do work just fine to change them all. I tried setting a new UI on the
JMenuItem but that doesn't seem to work either (see SSCCE below). When
I started this I didn't think it was going to take two days of messing
around with it :-).
import java.awt.*;
import javax.swing.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.*;
public class test extends JFrame {
public test() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JMenuBar mb = new JMenuBar();
setJMenuBar(mb);
JMenu menu = new JMenu("test");
mb.add(menu);
JMenuItem mi = new JMenuItem("This is default disabled");
mi.setEnabled(false);
menu.add(mi);
class NewUI extends BasicMenuItemUI {
public NewUI() {
disabledForeground = Color.RED;
}
};
mi = new JMenuItem("This I want to be bright red");
mi.setEnabled(false);
mi.setUI(new NewUI());
menu.add(mi);
JPanel p = new JPanel();
p.setPreferredSize(new Dimension(100,100));
add(p);
pack();
setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
new test();
}
});
}
}
Thanks,
--
Knute Johnson
BasicMenuItemUI has this:
protected void paintText(Graphics g, JMenuItem menuItem, Rectangle textRect, String text) {
ButtonModel model = menuItem.getModel();
FontMetrics fm = SwingUtilities2.getFontMetrics(menuItem, g);
int mnemIndex = menuItem.getDisplayedMnemonicIndex();
if(!model.isEnabled()) {
// *** paint the text disabled
if ( UIManager.get("MenuItem.disabledForeground") instanceof Color ) {
g.setColor( UIManager.getColor("MenuItem.disabledForeground") );
SwingUtilities2.drawStringUnderlineCharAt(menuItem, g,text,
mnemIndex, textRect.x, textRect.y + fm.getAscent());
} else {
...
so it doesn't appear to use the disabledForeground member anyway. Perhaps
that is your problem?
Of course, other L&F may do different things.
Your SSCCE didn't work for me as well. Just letting you know.
Thanks for that, I should have looked in the source to see what was up.
I'm not sure why they don't use their own field for this but this code
has probably been around for a long time.
For those interested, here is a horrible solution but the only one I
could come up with for now.
Thanks,
import java.awt.*;
import javax.swing.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.*;
import sun.swing.*;
class NewBasicMenuItemUI extends BasicMenuItemUI {
public void setDisabledForeground(Color color) {
disabledForeground = color;
}
protected void paintText(Graphics g, JMenuItem menuItem,
Rectangle textRect, String text) {
ButtonModel model = menuItem.getModel();
FontMetrics fm = SwingUtilities2.getFontMetrics(menuItem,g);
int mnemIndex = menuItem.getDisplayedMnemonicIndex();
if(!model.isEnabled()) {
// *** paint the text disabled
if (UIManager.get("MenuItem.disabledForeground") instanceof
Color) {
g.setColor( disabledForeground );
SwingUtilities2.drawStringUnderlineCharAt(menuItem,
g,text,mnemIndex, textRect.x,
textRect.y + fm.getAscent());
} else {
g.setColor(menuItem.getBackground().brighter());
SwingUtilities2.drawStringUnderlineCharAt(menuItem, g,
text,mnemIndex, textRect.x, textRect.y +
fm.getAscent());
g.setColor(menuItem.getBackground().darker());
SwingUtilities2.drawStringUnderlineCharAt(menuItem,
g,text,mnemIndex, textRect.x - 1, textRect.y +
fm.getAscent() - 1);
}
} else {
// *** paint the text normally
if (model.isArmed() ||
(menuItem instanceof JMenu && model.isSelected())) {
g.setColor(selectionForeground); // Uses protected field.
}
SwingUtilities2.drawStringUnderlineCharAt(menuItem, g,text,
mnemIndex, textRect.x, textRect.y + fm.getAscent());
}
}
}
import java.awt.*;
import javax.swing.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.*;
import sun.swing.*;
public class test extends JFrame {
public test() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JMenuBar mb = new JMenuBar();
setJMenuBar(mb);
JMenu menu = new JMenu("test");
mb.add(menu);
JMenuItem mi = new JMenuItem("This is default disabled");
mi.setEnabled(false);
menu.add(mi);
mi = new JMenuItem("This I want to be bright red");
mi.setEnabled(false);
NewBasicMenuItemUI newUI = new NewBasicMenuItemUI();
newUI.setDisabledForeground(Color.RED);
mi.setUI(newUI);
menu.add(mi);
JPanel p = new JPanel();
p.setPreferredSize(new Dimension(100,100));
add(p);
pack();
setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
new test();
}
});
}
}
--
Knute Johnson
> On 8/19/2011 4:01 AM, John B. Matthews wrote:
> > In article<j2kfm1$tai$1...@dont-email.me>, markspace<-@.> wrote:
> >
> >> On 8/18/2011 4:06 PM, Knute Johnson wrote:
> >>
> >>> Thanks for that but apparently I asked the wrong question. Why
> >>> can't I change the foreground color on my JMenuItem like you can?
> >>> I'm running 1.7 on Windows XP. It may be something different with
> >>> the LookAndFeel.
> >>
> >>
> >> I'm running Java 7 on Windows 7. My LNF is just the default one
> >> (might be Synth). I was running within NetBeans 7.0.1 IDE. Can't
> >> say why it doesn't work for you.
> >
> > Have the related UI defaults for MenuItem.* changed?
>
> I don't know.
>
> > <http://tips4java.wordpress.com/2008/10/09/uimanager-defaults/>
>
> I hadn't remembered that technique for changing the defaults but I only
> want to change one JMenuItem's disabled foreground color. That defaults
> do work just fine to change them all. I tried setting a new UI on the
> JMenuItem but that doesn't seem to work either (see SSCCE below). When
> I started this I didn't think it was going to take two days of messing
> around with it :-).
I'm not sure it's the best way, but the approach shown below may offer a
temporary workaround. IIUC, disabled isn't just a color; it's a
platform specific implementation intended to be visibly distinct from
enabled text, irrespective of color.
import java.awt.*;
import javax.swing.*;
public class test extends JFrame {
private static final String disabled = "MenuItem.disabledForeground";
private static final Color disColor = (Color) UIManager.get(disabled);
public test() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JMenuBar mb = new JMenuBar();
setJMenuBar(mb);
JMenu menu = new JMenu("test");
mb.add(menu);
JMenuItem mi = new JMenuItem("This is default disabled");
mi.setEnabled(false);
menu.add(mi);
UIManager.put(disabled, Color.red);
mi = new JMenuItem("This is disabled red");
mi.setEnabled(false);
menu.add(mi);
UIManager.put(disabled, disColor);
mi = new JMenuItem("Default restored");
mi.setEnabled(false);
menu.add(mi);
JPanel p = new JPanel();
p.setPreferredSize(new Dimension(100, 100));
add(p);
pack();
setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new test();
}
});
}
}
Cf. the JTextComponent, which has setDisabledTextColor():
John:
Does that work when you run it on your linux box? Because on my windows
xp it shows all of the menu items greyed out. JMenuItem doesn't keep
the disabled foreground color in the its field. The colors are
extracted from the UIManager when the component is repainted so if you
reset the value of MenuItem.disabledForeground anywhere it will paint
all of them with that color.
--
Knute Johnson
> Cf. the JTextComponent, which has setDisabledTextColor():
When I saw that I thought there you go, that's an easy fix but
JMenuItem.getComponent() returns a JMenuItem not a JTextComponent.
--
Knute Johnson
> Does that work when you run it on your linux box? Because on my
> windows xp it shows all of the menu items greyed out. JMenuItem
> doesn't keep the disabled foreground color in the its field. The
> colors are extracted from the UIManager when the component is
> repainted so if you reset the value of MenuItem.disabledForeground
> anywhere it will paint all of them with that color.
I see the result you describe on Ubuntu; my suggested workaround fails.
Altering the UI delegate is effective, but you'll want to check the
result on your target platforms: a dim red may show poor contrast on a
L&F's default background.