Java p> 好的,为什么我不想在paintComponent中设置JLabel的文本

Java p> 好的,为什么我不想在paintComponent中设置JLabel的文本,java,swing,paintcomponent,Java,Swing,Paintcomponent,paintComponent方法仅用于绘制和绘制。不应使用它来设置程序或组件的状态,原因有几个,包括您无法完全控制何时或是否调用此方法(如您所发现的),因此代码的状态不应取决于其被调用 我应该如何让JLabel在调用repaint时更新 同样,您不应该使用重新绘制来触发此操作。JLabel应该显示什么?为什么你觉得它必须在重新油漆时改变 编辑2 我以为这是个好地方。“我的显示器”由许多嵌套组件组成,这些组件的标签和背景不断变化。我应该从主处理循环中检索组件并在那里设置值,而不是使用paintC

paintComponent
方法仅用于绘制和绘制。不应使用它来设置程序或组件的状态,原因有几个,包括您无法完全控制何时或是否调用此方法(如您所发现的),因此代码的状态不应取决于其被调用

我应该如何让JLabel在调用repaint时更新

同样,您不应该使用重新绘制来触发此操作。JLabel应该显示什么?为什么你觉得它必须在重新油漆时改变


编辑2

我以为这是个好地方。“我的显示器”由许多嵌套组件组成,这些组件的标签和背景不断变化。我应该从主处理循环中检索组件并在那里设置值,而不是使用paintComponent吗

不,不允许外部类像这样直接操纵视图。相反,将您的模型和视图分开,并使用诸如PropertyChangeListener之类的侦听器以及公共方法来为您执行此操作

例如,通过将TestObject的值字段设置为“绑定属性”,可以轻松地更新JLabel文本。这可以通过给类一个PropertyChangeSupport对象(实际上,因为这是Swing,一个SwingPropertyChangeSupport对象)并允许外部类监听值的更改来轻松实现,如下所示:

class DisplayJPanel extends javax.swing.JPanel {

   private TestObject to = null;

   public DisplayJPanel() {
      initComponents();
   }

   public TestObject getTo() {
      return to;
   }

   public void setTo(final TestObject to) {
      this.to = to;

      // add listener to listen and react to changes in to value's state
      to.addPropertyChangeListener(new PropertyChangeListener() {

         @Override
         public void propertyChange(PropertyChangeEvent evt) {
            if (TestObject.VALUE.equals(evt.getPropertyName())) {
               setLabel2Text(String.valueOf(to.getValue()));
            }
         }
      });
   }

   private void initComponents() {

      // etc...

   }

   public void setLabel2Text(String text) {
      jLabel2.setText(text);
   }

   private javax.swing.JLabel jLabel2;
   private javax.swing.JPanel jPanel1;
}

class TestObject {
   public static final String VALUE = "value";
   private int value = 0;
   private SwingPropertyChangeSupport propChangeSupport = new SwingPropertyChangeSupport(this);

   public int getValue() {
      return value;
   }

   public void setValue(int value) {
      int oldValue = this.value;
      int newValue = value;
      this.value = newValue;

      propChangeSupport.firePropertyChange(VALUE, oldValue, newValue);
   }

   public void addPropertyChangeListener(PropertyChangeListener listener) {
      propChangeSupport.addPropertyChangeListener(listener);
   }

   public void removePropertyChangeListener(PropertyChangeListener listener) {
      propChangeSupport.removePropertyChangeListener(listener);
   }

}

请澄清——您到底希望这段代码做什么,它没有做什么?也是不相关的问题,但
super.paintComponents(g)
不是
paintComponent(g)
方法的超级选项。这是paintComponents的结尾,它会把你搞得一团糟。我的主要问题是,如果我删除jLabel1,那么paintComponent永远不会被调用。你几乎永远不会强烈建议删除“几乎”并注释以下几行;-)好的,为什么我不想在paintComponent中设置JLabel的文本?每当调用“重新绘制”时,我应该如何使JLabel更新?@充满鳗鱼的气垫船:我想显示一个在我的主程序中不断更新的值,以及更改背景颜色的值。@充满鳗鱼的气垫船:我以为是在paintComponent中进行此操作的。“我的显示器”由许多嵌套组件组成,这些组件的标签和背景不断变化。我应该从我的主处理循环中检索组件并在那里设置值,而不是使用paintComponent吗?@user2408629:请参见编辑2来回答。
        for (int i = 10; i < 20; i++) {
           to.setValue(i);
           try {
              Thread.sleep(100);
           } catch (InterruptedException ex) {
              Logger.getLogger(DisplayJFrame.class.getName()).log(
                    Level.SEVERE, null, ex);
           }

           df.draw();
        }
     public void run() {
        final DisplayJFrame df = new DisplayJFrame();
        df.setVisible(true);
        final TestObject to = new TestObject();
        df.setTO(to);

        int timerDelay = 100;
        final int maxCount = 20;
        new Timer(timerDelay, new ActionListener() {
           private int count = 0;

           @Override
           public void actionPerformed(ActionEvent evt) {
              if (count < maxCount) {
                 df.repaint();
                 to.setValue(count);
                 count++;
              } else {
                 ((Timer) evt.getSource()).stop();
              }
           }
        }).start();
        // for (int i = 10; i < 20; i++) {
        // to.setValue(i);
        // try {
        // Thread.sleep(100);
        // } catch (InterruptedException ex) {
        // Logger.getLogger(DisplayJFrame.class.getName()).log(
        // Level.SEVERE, null, ex);
        // }
        //
        // df.draw();
        // }
     }
// TODO: delete this method
public void paintComponent(Graphics g) {
  System.out.println("paintComponent");
  // super.paintComponents(g); // *** !! No -- this is not the super method ***
  super.paintComponent(g);
  if (to != null) {
     int i = to.getValue();
     System.out.println("paintComponent " + i);

     // of course you'll never set a JLabel's text from within this method
     jLabel1.setText(String.valueOf(i));
     jLabel2.setText(String.valueOf(i + 1));
  }
}
class DisplayJPanel extends javax.swing.JPanel {

   private TestObject to = null;

   public DisplayJPanel() {
      initComponents();
   }

   public TestObject getTo() {
      return to;
   }

   public void setTo(final TestObject to) {
      this.to = to;

      // add listener to listen and react to changes in to value's state
      to.addPropertyChangeListener(new PropertyChangeListener() {

         @Override
         public void propertyChange(PropertyChangeEvent evt) {
            if (TestObject.VALUE.equals(evt.getPropertyName())) {
               setLabel2Text(String.valueOf(to.getValue()));
            }
         }
      });
   }

   private void initComponents() {

      // etc...

   }

   public void setLabel2Text(String text) {
      jLabel2.setText(text);
   }

   private javax.swing.JLabel jLabel2;
   private javax.swing.JPanel jPanel1;
}

class TestObject {
   public static final String VALUE = "value";
   private int value = 0;
   private SwingPropertyChangeSupport propChangeSupport = new SwingPropertyChangeSupport(this);

   public int getValue() {
      return value;
   }

   public void setValue(int value) {
      int oldValue = this.value;
      int newValue = value;
      this.value = newValue;

      propChangeSupport.firePropertyChange(VALUE, oldValue, newValue);
   }

   public void addPropertyChangeListener(PropertyChangeListener listener) {
      propChangeSupport.addPropertyChangeListener(listener);
   }

   public void removePropertyChangeListener(PropertyChangeListener listener) {
      propChangeSupport.removePropertyChangeListener(listener);
   }

}