简体   繁体   English

如何重绘Java Swing应用程序的所有可见组件?

[英]How to repaint ALL visible components of Java Swing application?

I have a JFrame which allows user to adjust colors. 我有一个JFrame,它允许用户调整颜色。 This colors are set into static fields of class Colors using reflection. 使用反射将此颜色设置为Colors类的静态字段。 Here is the Colors class: 这是Colors类:

public class Colors {

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

There are many other components, located in several JFrame's, and they all use fields of Colors class. 还有许多其他组件,位于几个JFrame中,并且它们都使用Colors类的字段。 When I manually cause them to repaint (eg by resizing), they all repaint correctly. 当我手动使它们重新绘制(例如,通过调整大小)时,它们都正确地重新绘制。

But how can I cause all other components to repaint automatically? 但是,如何使所有其他组件自动重绘?

I tried something that seems dirty changing LookAndFeel, but it didn't work: 我尝试了一些看起来很脏的更改LookAndFeel的方法,但没有成功:

 UIManager.setLookAndFeel(UIManager.getLookAndFeel());

Update: I need to repaint components in all other JFrame's, that are currently visible. 更新:我需要重新绘制当前可见的所有其他 JFrame中的组件。

You'll need to call a method on your JFrame to let it know that its content needs to be repainted when you change colors. 您需要在JFrame上调用一个方法,以使它知道更改颜色时需要重绘其内容。 I believe the correct method is revalidate() , but repaint() may work as well. 我相信正确的方法是revalidate() ,但是repaint()可能也可以工作。 For more information on painting in Swing, try looking here: 有关在Swing中绘画的更多信息,请尝试在此处查看:

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

Sounds like you don't have a good handle on which components might be out there using your Colors class. 听起来您可能无法使用Colors类很好地处理哪些组件可能在那里。 In this case I'd give Colors the ability to support PropertyChangeListener s. 在这种情况下,我将为Colors提供支持PropertyChangeListener的能力。

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);
  }
}

Then whenever a component uses Colors define it as a PropertyChangeListener and let Colors know about it. 然后,每当组件使用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();
  }
}

Have a class extend JPanel and override the public void paintComponent function. 让一个类扩展JPanel并重写公共void paintComponent函数。

when you call frame.repaint(), it will reference code in paintComponent. 当您调用frame.repaint()时,它将引用paintComponent中的代码。

This will repaint all owner-less windows 这将重新粉刷所有无所有者的窗口

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

This colors are set into static fields of class Colors using reflection. 使用反射将此颜色设置为Colors类的静态字段。

This is your problem. 这是你的问题。 Rather than a) storing the colors in static variables, b) using reflection to update these values, or c) looping over the array of ownerless windows, use Swing as it's designed. 与其将a)将颜色存储在静态变量中,要么b)使用反射来更新这些值,或者c)在无主窗口的数组上循环,请使用Swing。 It's a little more code, but it will work cleaner and more efficiently do what you want. 这是一些代码,但是它将更干净,更有效地执行您想要的操作。

  1. Don't use reflection. 不要使用反射。 Create an actual interface for users to update color values, in an instance rather than a static, and tie this into the frame your users will work with to specify the colors they want. 创建一个实际的界面供用户更新实例而不是静态的颜色值,并将其绑定到用户将使用的框架中以指定所需的颜色。

  2. Put methods on your ColorManager object that accept ChangeListener objects. 在您的ColorManager对象上放置接受ChangeListener对象的方法。 At a minimum, simply create at addChangeListener() method, but alternatively you could add more granular control by defining several methods, addBackgroundListener() , addForegroundListener() , etc. These methods should store a list of registered listeners which will be notified when the associated action (the user updates the color) is performed. 至少,只需在addChangeListener()方法上创建即可,但您也可以通过定义几个方法addBackgroundListener()addForegroundListener()等来添加更精细的控件。这些方法应存储已注册侦听器的列表,当侦听到关联的操作(用户更新颜色)被执行。

  3. Make your windows implement the ChangeListener interface, and register them with the ColorManager object. 使您的窗口实现ChangeListener接口,并向ColorManager对象注册它们。 When the stateChanged() method is called your windows can handle it, updating the color and calling repaint() in the same place. 调用stateChanged()方法时,Windows可以处理它,更新颜色并在同一位置调用repaint()

The key advantage here is that now each class is doing exactly what it's supposed to, and has no unexpected side-effects on other classes. 这里的主要优点是,现在每个类都在按预期的方式运行,而对其他类没有任何意外的副作用。 The ColorManager is directly (as opposed to via reflection) updated by the user, it notifies exactly the objects that have explicitly asked to be notified (which can still be all windows, if that's what you want), and those objects can do with that information what they need to, whether that's repainting or doing something more complex. ColorManager由用户直接更新(而不是通过反射),它准确地通知明确要求通知的对象(如果您要的话,仍然可以是所有窗口),并且这些对象可以使用知道他们需要什么,无论是重新粉刷还是做更复杂的事情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM