有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java无法动态更新外观和感觉

我有一个程序,我希望能够在“白天”和“夜间”模式之间切换,“夜间”模式在所有东西上都有50%的灰色背景。我会打电话给UIManager。为本页中的所有“背景”键放置(键,新颜色):

http://alvinalexander.com/java/java-uimanager-color-keys-list

然后我就用勇气。updateComponentTreeUI()与java结合使用。awt。窗getWindows()获取现有窗口以获取更改

当我切换模式时,新创建的窗口将具有适当的背景,因此第一部分工作正常。然而,现有的窗口却表现得很奇怪:它们会先闪一下新的颜色,然后再切换回来。因此,例如,如果我在日间模式下启动程序,那么主程序窗口实际上被卡在日间模式下,反之亦然

我试图制作一个示例程序。它的行为与我现有的程序并不完全相同,但它的行为仍然很奇怪:外观只能修改一次。之后,新的更改将被忽略:

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]

谢谢你的建议


共 (2) 个答案

  1. # 1 楼答案

    为什么不用这样的代码替换基于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)

  2. # 2 楼答案

    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中来实现