【问题标题】:How to repaint ALL visible components of Java Swing application?如何重绘 Java Swing 应用程序的所有可见组件?
【发布时间】:2013-07-31 19:50:18
【问题描述】:

我有一个允许用户调整颜色的 JFrame。使用反射将此颜色设置为 Colors 类的静态字段。这是Colors 类:

public class Colors {

    public static Color TextBackground = Color.black;
    public static Color TextForeground = Color.white;
}

还有很多其他的组件,位于几个JFrame中,它们都使用Colors类的字段。当我手动使它们重新绘制时(例如通过调整大小),它们都正确地重新绘制。

但是如何使所有其他组件自动重绘?

我尝试了一些看起来很脏的方法来更改 LookAndFeel,但没有成功:

 UIManager.setLookAndFeel(UIManager.getLookAndFeel());

更新:我需要重新绘制当前可见的所有其他 JFrame 中的组件。

【问题讨论】:

  • 他们都使用Colors类的字段多么糟糕的设计……你说的自动是什么意思?循环遍历帧列表并重新绘制它们是更改字段后最少需要做的事情。

标签: java swing user-interface


【解决方案1】:

您需要在 JFrame 上调用一个方法,让它知道在您更改颜色时需要重新绘制其内容。我相信正确的方法是revalidate(),但repaint() 也可以。有关在 Swing 中绘画的更多信息,请尝试查看此处:

http://www.oracle.com/technetwork/java/painting-140037.html

【讨论】:

  • 谢谢,但这不是我问的。请参阅更新中的说明。
  • 在这种情况下,也许维护所有 JFrame 的集合,当颜色改变时,遍历列表并让每个 JFrame 重新绘制?
【解决方案2】:

听起来您没有很好地处理使用Colors 类可能存在哪些组件。在这种情况下,我会给Colors 支持PropertyChangeListeners 的能力。

class Colors {

  private static Colors instance = new Colors();

  public static Colors getInstance() {
    return instance;
  }

  private Color textBackground = Color.black;

  private PropertyChangeSupport backgroundProp = new PropertyChangeSupport(textBackground);

  public void setBackgroundColor(Color color) {
    this.textBackground = color;
  }

  public void addBackgroundListener(PropertyChangeListener listener) {
    backgroundProp.addPropertyChangeListener(listener);
  }
}

然后每当组件使用Colors 时,将其定义为PropertyChangeListener 并让Colors 知道它。

class MyTextField extends JTextField implements PropertyChangeListener {

  public MyTextField() {
    super();
    Colors.getInstance().addBackgroundListener(this);
  }

  public void propertyChange(PropertyChangeEvent evt) {
    Color background = (Color)evt.getNewValue();
    setBackground(background);
    repaint();
  }
}

【讨论】:

    【解决方案3】:

    让一个类扩展 JPanel 并覆盖 public void paintComponent 函数。

    调用frame.repaint()时,会引用paintComponent中的代码。

    【讨论】:

      【解决方案4】:

      这将重绘所有无主窗口

      Window[] windows = Frame.getOwnerlessWindows();
      for (int i = 0; i < windows.length; i++) {
          windows[i].repaint();
      }
      

      【讨论】:

        【解决方案5】:

        这些颜色使用反射设置到 Colors 类的静态字段中。

        这是你的问题。与其 a) 将颜色存储在静态变量中,b) 使用反射来更新这些值,或者 c) 循环遍历无主窗口数组,不如使用 Swing 的设计。它的代码有点多,但它会更干净、更有效地做你想做的事。

        1. 不要使用反射。为用户创建一个实际的界面来更新颜色值,在实例中而不是静态中,并将其绑定到您的用户将使用的框架中以指定他们想要的颜色。

        2. 在您的 ColorManager 对象上放置接受 ChangeListener 对象的方法。至少,只需在addChangeListener() 方法创建,但您也可以通过定义多个方法来添加更精细的控制,addBackgroundListener()addForegroundListener() 等。这些方法应该存储已注册侦听器的列表,当执行相关操作(用户更新颜色)。

        3. 让您的窗口实现 ChangeListener 接口,并将它们注册到 ColorManager 对象。当调用stateChanged() 方法时,您的窗口可以处理它,更新颜色并在同一位置调用repaint()

        这里的关键优势是现在每个类都在做它应该做的事情,并且对其他类没有意外的副作用。 ColorManager 由用户直接(而不是通过反射)更新,它准确地通知已明确要求通知的对象(仍然可以是所有窗口,如果这是您想要的),并且这些对象可以这样做了解他们需要什么,无论是重新粉刷还是做一些更复杂的事情。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-01-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多