无法即时更新外观
Can't update look and feel on the fly
我有一个程序,我希望能够在 "day" 和 "night" 模式之间切换,"night" 模式在所有内容上都有 50% 的灰色背景。为此,我为此页面中的所有 "background" 键调用 UIManager.put(key, new color):
http://alvinalexander.com/java/java-uimanager-color-keys-list
然后我将 SwingUtilities.updateComponentTreeUI() 与 java.awt.Window.getWindows() 结合使用,让现有的 windows 接受更改。
当我切换模式时,新创建的 windows 将具有适当的背景,因此第一部分有效。然而,现有的 windows 表现得很奇怪:它们闪烁到新的颜色一会儿,然后切换回来。因此,例如如果我在 Day 模式下启动程序,那么主程序 window 实际上停留在 Day 模式,反之亦然。
我试图制作一个示例程序。它的行为与我现有的程序并不完全相同,但它仍然表现得很奇怪:外观只能修改一次。之后,忽略新的更改:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.Frame;
import javax.swing.JLabel;
import java.awt.GridLayout;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
public class Demo {
public static void main(String[] args) {
new Demo();
}
public Demo() {
JFrame frame = new JFrame("Look and feel test");
frame.setLayout(new GridLayout(3, 3));
// Fill in non-central locations in the layout.
// Hacky way to keep the button from monopolizing the frame
for (int i = 0; i < 4; ++i) {
frame.add(new JLabel(""));
}
JButton button = new JButton("Set new LAF");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
setNewLAF();
}
});
frame.add(button);
// Fill in non-central locations in the layout.
for (int i = 0; i < 4; ++i) {
frame.add(new JLabel(""));
}
frame.setMinimumSize(new Dimension(400, 400));
frame.show();
System.out.println("Initial frame background is " + frame.getBackground());
}
public void setNewLAF() {
Random rng = new Random();
Color newBackground = new Color(rng.nextInt(255),
rng.nextInt(255), rng.nextInt(255));
System.out.println("New color is " + newBackground);
UIManager.put("Panel.background", newBackground);
for (Frame f : Frame.getFrames()) {
SwingUtilities.updateComponentTreeUI(f);
System.out.println("Frame now has background " + f.getBackground());
}
}
}
这会产生如下输出:
Initial frame background is com.apple.laf.AquaImageFactory$SystemColorProxy[r=238,g=238,b=238]
New color is java.awt.Color[r=243,g=209,b=134]
Frame now has background java.awt.Color[r=243,g=209,b=134]
New color is java.awt.Color[r=205,g=141,b=58]
Frame now has background java.awt.Color[r=243,g=209,b=134]
New color is java.awt.Color[r=141,g=22,b=92]
Frame now has background java.awt.Color[r=243,g=209,b=134]
感谢您愿意分享的任何建议。
你为什么不用类似这样的东西替换基于 UIManager
的代码?
public void setNewLAF(JFrame frame) {
Random rng = new Random();
Color newBackground = new Color(rng.nextInt(255), rng.nextInt(255),
rng.nextInt(255));
System.out.println("New color is " + newBackground);
frame.setBackground(newBackground);
frame.getContentPane().setBackground(newBackground);
}
它可能不适合你的情况(例如,如果你有很多帧)但我认为你可以将你的帧转储到 ArrayList<JFrame>
并迭代它们。
另外,特此通知您:show()
已弃用。使用 setVisible(true)
.
it still behaves oddly: the look and feel can only be modified once.
Color newBackground = new Color(rng.nextInt(255),rng.nextInt(255), rng.nextInt(255));
您需要使用:
Color newBackground = new ColorUIResource(rng.nextInt(255),rng.nextInt(255), rng.nextInt(255));
updateComponentTreeUI() 仅替换 UI 中的资源。为此,您可以将 Color
包装在 ColorUIResource
.
中
我有一个程序,我希望能够在 "day" 和 "night" 模式之间切换,"night" 模式在所有内容上都有 50% 的灰色背景。为此,我为此页面中的所有 "background" 键调用 UIManager.put(key, new color):
http://alvinalexander.com/java/java-uimanager-color-keys-list
然后我将 SwingUtilities.updateComponentTreeUI() 与 java.awt.Window.getWindows() 结合使用,让现有的 windows 接受更改。
当我切换模式时,新创建的 windows 将具有适当的背景,因此第一部分有效。然而,现有的 windows 表现得很奇怪:它们闪烁到新的颜色一会儿,然后切换回来。因此,例如如果我在 Day 模式下启动程序,那么主程序 window 实际上停留在 Day 模式,反之亦然。
我试图制作一个示例程序。它的行为与我现有的程序并不完全相同,但它仍然表现得很奇怪:外观只能修改一次。之后,忽略新的更改:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.Frame;
import javax.swing.JLabel;
import java.awt.GridLayout;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
public class Demo {
public static void main(String[] args) {
new Demo();
}
public Demo() {
JFrame frame = new JFrame("Look and feel test");
frame.setLayout(new GridLayout(3, 3));
// Fill in non-central locations in the layout.
// Hacky way to keep the button from monopolizing the frame
for (int i = 0; i < 4; ++i) {
frame.add(new JLabel(""));
}
JButton button = new JButton("Set new LAF");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
setNewLAF();
}
});
frame.add(button);
// Fill in non-central locations in the layout.
for (int i = 0; i < 4; ++i) {
frame.add(new JLabel(""));
}
frame.setMinimumSize(new Dimension(400, 400));
frame.show();
System.out.println("Initial frame background is " + frame.getBackground());
}
public void setNewLAF() {
Random rng = new Random();
Color newBackground = new Color(rng.nextInt(255),
rng.nextInt(255), rng.nextInt(255));
System.out.println("New color is " + newBackground);
UIManager.put("Panel.background", newBackground);
for (Frame f : Frame.getFrames()) {
SwingUtilities.updateComponentTreeUI(f);
System.out.println("Frame now has background " + f.getBackground());
}
}
}
这会产生如下输出:
Initial frame background is com.apple.laf.AquaImageFactory$SystemColorProxy[r=238,g=238,b=238]
New color is java.awt.Color[r=243,g=209,b=134]
Frame now has background java.awt.Color[r=243,g=209,b=134]
New color is java.awt.Color[r=205,g=141,b=58]
Frame now has background java.awt.Color[r=243,g=209,b=134]
New color is java.awt.Color[r=141,g=22,b=92]
Frame now has background java.awt.Color[r=243,g=209,b=134]
感谢您愿意分享的任何建议。
你为什么不用类似这样的东西替换基于 UIManager
的代码?
public void setNewLAF(JFrame frame) {
Random rng = new Random();
Color newBackground = new Color(rng.nextInt(255), rng.nextInt(255),
rng.nextInt(255));
System.out.println("New color is " + newBackground);
frame.setBackground(newBackground);
frame.getContentPane().setBackground(newBackground);
}
它可能不适合你的情况(例如,如果你有很多帧)但我认为你可以将你的帧转储到 ArrayList<JFrame>
并迭代它们。
另外,特此通知您:show()
已弃用。使用 setVisible(true)
.
it still behaves oddly: the look and feel can only be modified once.
Color newBackground = new Color(rng.nextInt(255),rng.nextInt(255), rng.nextInt(255));
您需要使用:
Color newBackground = new ColorUIResource(rng.nextInt(255),rng.nextInt(255), rng.nextInt(255));
updateComponentTreeUI() 仅替换 UI 中的资源。为此,您可以将 Color
包装在 ColorUIResource
.