即时更改 swing UIManager 颜色常量,并更新现有组件
Change swing UIManager color-constants on the fly, and update existing components
我们有一个大型应用程序。在启动时我们设置了一些 UIManager 属性,比如 Button.background 和 Panel.background。几乎所有组件都使用这些值,但某些组件具有自定义背景。
现在我们希望用户可以选择自定义他们的颜色,并且能够立即查看它们,而无需重新启动应用程序。
为 Button.background 和 Panel.background 等设置新值在新组件上工作正常,例如,如果用户打开一个新的 JDialog,但不会更新现有组件。我已经在组件上尝试了 SwingUtilities.updateComponentTreeUI、updateUI 等,但是背景似乎已经在现有组件上设置好了,不会更新。我无法遍历所有组件并相应地设置背景,因为某些背景具有自定义背景。我应该怎么办?我们使用 jgoodies look&feel,但它在标准 UIManager.getCrossPlatformLookAndFeelClassName() 中也不起作用。我将提供一个我想要的小编码示例。
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Div extends JFrame implements ActionListener{
private JButton green;
private JButton red;
public static void main(String[] args) throws Exception{
new Div();
}
public Div() throws Exception{
UIManager.put("Button.background", Color.green);
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
green = new JButton("Should be changed");
red = new JButton("Should not be changed");
JPanel cp = (JPanel)getContentPane(); cp.setLayout(new GridLayout(2,1));
cp.add(green);
cp.add(red);
red.setBackground(Color.red);
green.addActionListener(this);
setSize(200,100); setLocation(100,50);
setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
UIManager.put("Button.background", ((Color)UIManager.get("Button.background")).darker());
green.updateUI(); //Should update the green button with a new color, but doesn't
}
}
EDIT/SOLUTION:
camickrs 的回答似乎适用于我尝试过的所有组件,除了我提供的 JButton 示例(例如 Panel.background、ComboBox.background、TextField.background 等)而且我什至发现我们使用的 L&F, jgoodies,甚至尊重 JButton :-D 所以现在我很高兴。
因此对示例的代码更改为:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.ColorUIResource;
public class Div extends JFrame implements ActionListener{
private JButton green;
private JButton red;
private JPanel panel;
private JComboBox<?> box;
private JTextField txt;
public static void main(String[] args) throws Exception{
new Div();
}
public Div() throws Exception{
ColorUIResource r = new ColorUIResource(new Color(0,255,0));
UIManager.put("Button.background", r);
UIManager.put("Panel.background", r);
UIManager.put("ComboBox.background", r);
UIManager.put("TextField.background", r);
//UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); //Works, but not on JButtons
UIManager.setLookAndFeel("com.jgoodies.looks.plastic.PlasticXPLookAndFeel"); //Also works with JButton :-D
green = new JButton("Should be changed");
red = new JButton("Should not be changed");
panel = new JPanel();
box = new JComboBox();
txt = new JTextField();
JPanel cp = (JPanel)getContentPane(); cp.setLayout(new GridLayout(5,1));
cp.add(green);
cp.add(red);
cp.add(panel);
cp.add(box);
cp.add(txt);
red.setBackground(Color.red);
green.addActionListener(this);
setSize(200,200); setLocation(100,100);
setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
Color col = ((Color)UIManager.get("Button.background")).darker();
ColorUIResource r = new ColorUIResource(col);
UIManager.put("Button.background", r);
UIManager.put("Panel.background", r);
UIManager.put("ComboBox.background", r);
UIManager.put("TextField.background", r);
SwingUtilities.updateComponentTreeUI(this);
}
}
当 SWingUtilities 不工作时(它们不适合所有情况)这就是我所做的
例如:
JFrame frame = new JFrame("Window");
它里面有一些组件...
frame.dispose();
frame.setVisible(true);
快
它解决了 update();
的问题
也类似于 link 到 Whosebug similar problem
UIManager.put("Button.background", ((Color)UIManager.get("Button.background")).darker());
我认为代码应该是:
Color background = UIManager.getColor("Button.background").darker();
UIManager.put("Button.background", new ColorUIResource(background));
SwingUtilities.updateComponentTree(...);
UIManager 只会更新属于 LAF 的属性,因此您需要使用 ColorUIResource 包装器。
编辑:
主要思想是您需要最初设置 UIManager 颜色才能使用 ColorUIResource。这适用于 JTextField:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.*;
public class Div extends JFrame implements ActionListener{
private JTextField green;
private JTextField red;
public static void main(String[] args) throws Exception{
new Div();
}
public Div() throws Exception{
UIManager.put("TextField.background", new ColorUIResource(Color.green));
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
green = new JTextField("Should be changed");
red = new JTextField("Should not be changed");
JPanel cp = (JPanel)getContentPane(); cp.setLayout(new GridLayout(2,1));
cp.add(green);
cp.add(red);
red.setBackground(Color.red);
green.addActionListener(this);
setSize(200,100); setLocation(100,50);
setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
Color background = Color.YELLOW;
UIManager.put("TextField.background", new ColorUIResource(background));
SwingUtilities.updateComponentTreeUI(this);
}
}
我不太确定为什么 JButton 不起作用,但正如@mKorbel 所提到的,JButton 与其他组件不同。
我们有一个大型应用程序。在启动时我们设置了一些 UIManager 属性,比如 Button.background 和 Panel.background。几乎所有组件都使用这些值,但某些组件具有自定义背景。 现在我们希望用户可以选择自定义他们的颜色,并且能够立即查看它们,而无需重新启动应用程序。 为 Button.background 和 Panel.background 等设置新值在新组件上工作正常,例如,如果用户打开一个新的 JDialog,但不会更新现有组件。我已经在组件上尝试了 SwingUtilities.updateComponentTreeUI、updateUI 等,但是背景似乎已经在现有组件上设置好了,不会更新。我无法遍历所有组件并相应地设置背景,因为某些背景具有自定义背景。我应该怎么办?我们使用 jgoodies look&feel,但它在标准 UIManager.getCrossPlatformLookAndFeelClassName() 中也不起作用。我将提供一个我想要的小编码示例。
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Div extends JFrame implements ActionListener{
private JButton green;
private JButton red;
public static void main(String[] args) throws Exception{
new Div();
}
public Div() throws Exception{
UIManager.put("Button.background", Color.green);
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
green = new JButton("Should be changed");
red = new JButton("Should not be changed");
JPanel cp = (JPanel)getContentPane(); cp.setLayout(new GridLayout(2,1));
cp.add(green);
cp.add(red);
red.setBackground(Color.red);
green.addActionListener(this);
setSize(200,100); setLocation(100,50);
setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
UIManager.put("Button.background", ((Color)UIManager.get("Button.background")).darker());
green.updateUI(); //Should update the green button with a new color, but doesn't
}
}
EDIT/SOLUTION: camickrs 的回答似乎适用于我尝试过的所有组件,除了我提供的 JButton 示例(例如 Panel.background、ComboBox.background、TextField.background 等)而且我什至发现我们使用的 L&F, jgoodies,甚至尊重 JButton :-D 所以现在我很高兴。 因此对示例的代码更改为:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.ColorUIResource;
public class Div extends JFrame implements ActionListener{
private JButton green;
private JButton red;
private JPanel panel;
private JComboBox<?> box;
private JTextField txt;
public static void main(String[] args) throws Exception{
new Div();
}
public Div() throws Exception{
ColorUIResource r = new ColorUIResource(new Color(0,255,0));
UIManager.put("Button.background", r);
UIManager.put("Panel.background", r);
UIManager.put("ComboBox.background", r);
UIManager.put("TextField.background", r);
//UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); //Works, but not on JButtons
UIManager.setLookAndFeel("com.jgoodies.looks.plastic.PlasticXPLookAndFeel"); //Also works with JButton :-D
green = new JButton("Should be changed");
red = new JButton("Should not be changed");
panel = new JPanel();
box = new JComboBox();
txt = new JTextField();
JPanel cp = (JPanel)getContentPane(); cp.setLayout(new GridLayout(5,1));
cp.add(green);
cp.add(red);
cp.add(panel);
cp.add(box);
cp.add(txt);
red.setBackground(Color.red);
green.addActionListener(this);
setSize(200,200); setLocation(100,100);
setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
Color col = ((Color)UIManager.get("Button.background")).darker();
ColorUIResource r = new ColorUIResource(col);
UIManager.put("Button.background", r);
UIManager.put("Panel.background", r);
UIManager.put("ComboBox.background", r);
UIManager.put("TextField.background", r);
SwingUtilities.updateComponentTreeUI(this);
}
}
当 SWingUtilities 不工作时(它们不适合所有情况)这就是我所做的 例如:
JFrame frame = new JFrame("Window");
它里面有一些组件...
frame.dispose();
frame.setVisible(true);
快 它解决了 update();
的问题也类似于 link 到 Whosebug similar problem
UIManager.put("Button.background", ((Color)UIManager.get("Button.background")).darker());
我认为代码应该是:
Color background = UIManager.getColor("Button.background").darker();
UIManager.put("Button.background", new ColorUIResource(background));
SwingUtilities.updateComponentTree(...);
UIManager 只会更新属于 LAF 的属性,因此您需要使用 ColorUIResource 包装器。
编辑:
主要思想是您需要最初设置 UIManager 颜色才能使用 ColorUIResource。这适用于 JTextField:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.*;
public class Div extends JFrame implements ActionListener{
private JTextField green;
private JTextField red;
public static void main(String[] args) throws Exception{
new Div();
}
public Div() throws Exception{
UIManager.put("TextField.background", new ColorUIResource(Color.green));
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
green = new JTextField("Should be changed");
red = new JTextField("Should not be changed");
JPanel cp = (JPanel)getContentPane(); cp.setLayout(new GridLayout(2,1));
cp.add(green);
cp.add(red);
red.setBackground(Color.red);
green.addActionListener(this);
setSize(200,100); setLocation(100,50);
setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
Color background = Color.YELLOW;
UIManager.put("TextField.background", new ColorUIResource(background));
SwingUtilities.updateComponentTreeUI(this);
}
}
我不太确定为什么 JButton 不起作用,但正如@mKorbel 所提到的,JButton 与其他组件不同。