日期:2014-05-20  浏览次数:21051 次

为什么paint()被调用2次?
以下代码是在jpanel上画图。启动窗口的时候,教程上paint只被调用一次,
我的程序和教程一模一样,却被调用2次,难道是我的电脑设置问题?
哪位朋友可以看出bug ?

Java code

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

public class Demo9_1 extends JFrame {

    MyPanel mp = null;

    public static void main(String[] args) {
        Demo9_1 demo9_1 = new Demo9_1();
    }

    public Demo9_1() {

        mp = new MyPanel();

        this.add(mp);

        // =========================================

        this.setSize(400, 300);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
        
        // =========================================

    }

}

class MyPanel extends JPanel {
    
    public void paint(Graphics g) {

        super.paint(g);
        
        System.out.println("paint() is called !");
        
        g.setColor(Color.red);
        g.fillRect(70, 10, 40, 60);

        g.setColor(Color.blue);
        g.fillRect(70, 90, 40, 60);
        
    }

}





------解决方案--------------------
使用万能方法试试:
Java code

////////////////////////////////////////////////////////////////////////////////////////////////
下载安装对应版本的JDK:
64位操作系统:[url=http://download.oracle.com/otn-pub/java/jdk/7/jdk-7-windows-x64.exe][/url]
32位操作系统:[url=http://download.oracle.com/otn-pub/java/jdk/7/jdk-7-windows-i586.exe][/url]
////////////////////////////////////////////////////////////////////////////////////////////////
JAVA_HOME设置(每个人都不一样,确保它的子目录有:bin,demo,include,jre,lib)
jdk目录的具体路径,比如   ;D:\Program Files\Java\jdk1.7.0;

ClassPath设置(初学者直接复制到环境变量的最前端,高手请按自己的想法做):
;%JAVA_HOME%\bin;.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\jre\lib\rt.jar;

Path设置(直接复制到环境变量的最前端):
;%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;.;%JAVA_HOME%\..\jre7\bin;%JAVA_HOME%\..\jre6\bin;%JAVA_HOME%\..\jre5\bin;
//////////////////////////////////////////////////////////////////////////////////////////////////

------解决方案--------------------
囧 刚才试了下竟然不是 真丢人`` 好好看了下代码 
this.add(mp); 你要是 放到 最后 就不会出现 这种情况``
为啥 我猜是这样滴
JFrame 默认是不会生成 Graphics的 除非是 setVisible(true); 或者 用GraphicsDivice 生成 全屏模式 会返回Graphics ````
但是 你的 JPanel 的默认 setVisible(true); 是生成 Graphics对象的;
好了 直奔主题

AWT的 EventQueue(Queue -- >队列!!) 的任务(也就是线程) 它是负责 绘画的 (当然也负责鼠标事件云云的东西) 当 先add(); AWT的线程 并不会马上调用 因为程序还没运行结束 并不知道 JFrame 是否为ture 这时 JPanel 的 paint 进入队列 等待 JFrame 的 setVisible (true) 发生` 也就是说 JFrame 为真的时候 JFrame 的 paint 也加入队列 并开始执行`` (队列么 想象先进先出 依次调用`现实JFrame 的 在 JPanel 明白了吧!) --> 看源码 没看懂 功力不够 所以 做了3个实验 `` 自己看输出结果吧: 我相信这个 说法 会让你信服的 
(--------):
public Demo9_1() {

mp = new MyPanel();

this.add(mp);
// for(int i =1 ; i <1000; i++){
// System.out.println(i);
// }
this.setSize(400, 300);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
// for(int i =1 ; i < 1000 ; i ++){
// System.out.println("i");
// }

}

注释 : 依次去掉注释 并观察 paint() 中的 paintln() 出现的位置 一定要记住 main VS AWT 线程 \(^o^)/~
希望对你有用 呼`` 累之```o(╯□╰)o