I have a program that I want to be able to switch between "day" and "night" modes, with the "night" mode having 50% gray backgrounds on everything. I'm doing this by calling UIManager.put(key, new color) for all of the "background" keys from this page:
我有一个程序,我希望能够在“白天”和“夜”模式之间切换,“夜”模式有50%的灰色背景。我是通过调用UIManager来实现的。从这一页的“背景”键中输入(键,新颜色):
http://alvinalexander.com/java/java-uimanager-color-keys-list
http://alvinalexander.com/java/java-uimanager-color-keys-list
Then I use SwingUtilities.updateComponentTreeUI() in conjunction with java.awt.Window.getWindows() to get existing windows to pick up the change.
然后,我使用swinguse . updatecomponenttreeui()和java.awt.Window.getWindows()来获取现有的窗口来获取更改。
When I switch modes, newly-created windows will have the proper background, so the first part works. However, existing windows are behaving oddly: they flash to the new color for a moment, and then switch back. Thus e.g. if I start up the program in Day mode, then the main program window is effectively stuck in Day mode, and vice versa.
当我切换模式时,新创建的窗口会有合适的背景,所以第一部分工作。然而,现有的windows操作系统却表现得很奇怪:它们在一瞬间闪现出新的颜色,然后切换回来。因此,如果我在Day模式下启动程序,那么主程序窗口就会在Day模式中被有效地卡住,反之亦然。
I attempted to make an example program. It doesn't behave exactly like my existing program, but it still behaves oddly: the look and feel can only be modified once. After that, new changes are ignored:
我试图做一个示例程序。它的行为与我现有的程序不一样,但它仍然表现得很奇怪:外观和感觉只能修改一次。在那之后,新的变化被忽略了:
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());
}
}
}
This produces output such as:
这产生的输出如下:
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]
Thanks for any advice you'd care to share.
谢谢你给我的建议。
2 个解决方案
#1
1
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));
You need to use:
你需要使用:
Color newBackground = new ColorUIResource(rng.nextInt(255),rng.nextInt(255), rng.nextInt(255));
The updateComponentTreeUI() only replaces resources that are part of the UI. You do this by wrapping the Color
in a ColorUIResource
.
updateComponentTreeUI()只是替换了UI中一部分的资源。您可以通过在ColorUIResource中包装颜色来实现这一点。
#2
0
Why don't you replace your UIManager
based code with something like this?
你为什么不把你的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);
}
It might not work well with your case (e.g., if you have many frames) but I think that you can probably just dump your frames into an ArrayList<JFrame>
and iterate over them.
它可能不适用于您的情况(例如,如果您有许多帧),但是我认为您可能只是将您的框架转储到一个ArrayList
Also, just to let you know: show()
is deprecated. Use setVisible(true)
.
另外,只是让您知道:show()是不赞成的。使用setVisible(true)。
#1
1
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));
You need to use:
你需要使用:
Color newBackground = new ColorUIResource(rng.nextInt(255),rng.nextInt(255), rng.nextInt(255));
The updateComponentTreeUI() only replaces resources that are part of the UI. You do this by wrapping the Color
in a ColorUIResource
.
updateComponentTreeUI()只是替换了UI中一部分的资源。您可以通过在ColorUIResource中包装颜色来实现这一点。
#2
0
Why don't you replace your UIManager
based code with something like this?
你为什么不把你的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);
}
It might not work well with your case (e.g., if you have many frames) but I think that you can probably just dump your frames into an ArrayList<JFrame>
and iterate over them.
它可能不适用于您的情况(例如,如果您有许多帧),但是我认为您可能只是将您的框架转储到一个ArrayList
Also, just to let you know: show()
is deprecated. Use setVisible(true)
.
另外,只是让您知道:show()是不赞成的。使用setVisible(true)。