由于componentResize和长重绘命令

时间:2015-06-22 01:27:56

标签: java swing

问题很明显:我有一个很大的绘制命令,有一个非常大的for循环和一个componentResized运行paint命令大量的时间,这使我的JPanel成为黑屏,即使我按下它也无法退出x按钮(我必须在eclipse上终止它),在这里表示:

package Testing;

import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class DrawTest extends JPanel implements ComponentListener {
public DrawTest(){
    this.addComponentListener(this);
}
    @Override
    public void paint(Graphics g) {
            int gridsize=8;
    double width=getWidth()/gridsize;
    for(double i=0;i<=getWidth();i+=width){
        System.out.println("1");
        g.drawLine((int)i,0,(int)i,getHeight());
    }

    double height=getHeight()/gridsize;
    for(double i=0;i<=getHeight();i+=height){
        System.out.println("2");
        g.drawLine(0,(int)i,getWidth(),(int)i);
    }
    }
    public static void main(String[] args){
        JFrame frame=new JFrame("Fill all the squares with Ls");
        DrawTest FillSquare=new DrawTest();
        frame.add(FillSquare);
        frame.setExtendedState( frame.getExtendedState()|frame.MAXIMIZED_BOTH );
        frame.setVisible(true);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    @Override
    public void componentHidden(ComponentEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void componentMoved(ComponentEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void componentResized(ComponentEvent e) {
           ActionListener taskPerformer = new ActionListener() {
                public void actionPerformed(ActionEvent evt) {
                    //...Perform a task...

                    System.out.println("Reading SMTP Info.");
                }
            };
            Timer timer = new Timer(100 ,taskPerformer);
            timer.setRepeats(false);
            timer.start();
        repaint();

    }

    @Override
    public void componentShown(ComponentEvent e) {
        // TODO Auto-generated method stub

    }
}

我搜索了问题并在stackoverthrow上查了一下,结果是使用Timer来阻止componentResize在用户调整屏幕大小时运行一段时间,但是在实现之后,如图所示代码,它似乎仍然没有工作。我不知道我做错了什么,这是我第一次使用它。在使用System.out.println();进行游戏并进行测试后,我似乎遇到了另一个问题。用户移动框架后,paint命令的第二个循环似乎无限地进行。enter image description here

提前致谢!

1 个答案:

答案 0 :(得分:4)

四件事:

  • 不要在for(int i=1;i<=100000;i++){方法中执行paint。绘画方法应尽快返回,否则,您最终会遇到类似于现在的问题。考虑缓冲输出,这样你就不会反复更新它并浪费时间。
  • 在进行任何自定义绘画之前调用super.paint
  • 覆盖paintComponent而不是paint(并在进行任何自定义绘画之前调用super.paintComponent
  • 每次调用componentResized时,您都会创建另一个Timer,因此,如果它被调用了100次,那么您将创建一个100 Timer,这不会规模很好

作为一种可能的解决方案,您不需要使用ComponentListener,我倾向于覆盖invalidate,但您可以使用其中任何一种获得类似的结果。

您应该使用BufferedImage来表示您想要绘制的内容,这样,如果由于某种原因而调用了paint方法,则只需调整组件的大小,您可以只绘制{{1并且不用担心必须从头开始重建整个状态。

您只需要一个BufferedImage,每当您收到有关该组件已更改的通知时,都会重新启动。{/ p>

Timer触发Timer时,您将使当前缓冲区无效并重新生成它。我提供的示例使用ActionListener将工作卸载到后台线程,这将允许UI在缓冲区更新时保持响应。当缓冲区为SwingWorker表明输出已重新生成时,您可以在paintComponent方法中显示一条消息

null

查看Painting in AWT and SwingPerforming Custom PaintingHow to use Swing TimersWorker Threads and SwingWorker了解详情