repaint不会调用paintComponent

时间:2017-02-16 09:23:47

标签: java swing

重绘不是在调用PaintComponent  我试图从Try类的另一个方法调用它,但它没有用。

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;

public class Try extends JPanel {
    int i =0;

    @Override
    public void paintComponent(Graphics g){
       //super.paintComponent(g);
       System.out.println("hey");
   }

    public static void main(String[] args) {
       JFrame f=new JFrame();
       Try t = new Try();
       f.setSize(500,600);//400 width and 500 height

       Container contentPane = f.getContentPane();
       contentPane.add(new PaintComponent());
       f.setVisible(true);//making the frame visible

       while(true){
          t.repaint();
       }
    }
 }

1 个答案:

答案 0 :(得分:0)

@trashgod在评论中提到了一些问题。

  1. 您正在调用未添加到内容窗格的实例上的重绘 - 您在那里有一个不同的(实际上,那里有一些完全不同的东西 - new PaintComponent())。

  2. 除非你自己清理区域(如果它是不透明的,几乎填满整个组件背景),否则不要删除super.paintComponent ( g );,否则在重新绘制时会在这些组件上出现视觉故障。< / p>

  3. 你是垃圾邮件重绘操作非常糟糕,至少在重绘之间有一些延迟,给予Swing时间来执行重绘。最好的情况是,只有当它实际上会在视觉上显示不同的东西时重新绘制组件。如果您需要始终更新视图 - 至少将其限制为每秒30-60帧(重绘)。此外,一些内部Swing优化可能会&#34; eat&#34;一些重新调用的调用,所以期望你可能看不到你在组件上调用的重复数量paintComponent次调用。

  4. 您正在使用Event Dispatch Thread(简称EDT)之外的Swing组件,这可能会导致问题。确保始终使用它来创建Swing组件并调用它们上的任何方法。 SwingUtilities有助于此。

  5. 任何需要很长时间(或未知时间)完成的繁重操作都应该在EDT之外执行,否则,当您等待该操作完成时,您的UI将会挂起,因为所有UI更新都是在EDT上进行,而不是在其他任何地方进行。

  6. 考虑到我上面所说的一切,这就是你的例子应该是这样的:

    public class Try extends JPanel
    {
        @Override
        public void paintComponent ( final Graphics g )
        {
            super.paintComponent ( g );
    
            final Graphics2D g2d = ( Graphics2D ) g;
            g2d.drawString ( Long.toString ( System.currentTimeMillis () ), 25, 35 );
    
            System.out.println ( "repainted" );
        }
    
        public static void main ( final String[] args )
        {
            SwingUtilities.invokeLater ( new Runnable ()
            {
                @Override
                public void run ()
                {
                    final JFrame f = new JFrame ();
    
                    final Try t = new Try ();
                    f.getContentPane ().add ( t );
    
                    f.setSize ( 500, 600 );
                    f.setVisible ( true );
    
                    new Thread ( new Runnable ()
                    {
                        @Override
                        public void run ()
                        {
                            try
                            {
                                while ( true )
                                {
                                    t.repaint ();
                                    Thread.sleep ( 25 );
                                }
                            }
                            catch ( final InterruptedException e )
                            {
                                //
                            }
                        }
                    } ).start ();
                }
            } );
        }
    }
    

    希望能为你澄清一点。

    还有SwingWorker类有助于在Swing中执行长时间运行的任务,但我没有在这里使用它来保持示例尽可能简单。

    另外还有一个注意事项 - 您不需要在EDT中调用repaint (),因为它会自动将重绘请求发送到EDT,因此该方法可以安全地在任何线程上使用(就像我在示例中所做的那样) )。