您的位置:首页 > 编程语言 > Java开发

JAVA图形编程Swing之——JPanel绘图

2015-07-04 19:38 519 查看
JAVA图形编程Swing之——JPanel绘图

一直搞不清怎么在JPanel中绘2D图像,主要是不知怎样得到Graphics类的对像来画图,今天查了查资料,测试N种方法,终于搞明白。下面做一个测试总结。

一、自定义一个类,继承JPanel,直接重写它的paint方法。
/**
* 定义一个继承自JPanel的类,重写它的paint方法 *
*/
class MyPanel extends JPanel
{
private int x = 200;
private int y = 200;

public void display()
{
x ++;
y ++;

//重绘JPanel
this.repaint();
}

/**
* repaint方法会调用paint方法,并自动获得Graphics对像
* 然后可以用该对像进行2D画图
* 注:该方法是重写了JPanel的paint方法
*/
public void paint(Graphics g)
{
//调用的super.paint(g),让父类做一些事前的工作,如刷新屏幕
super.paint(g);
Graphics2D g2d = (Graphics2D)g;

g2d.setColor(Color.RED);//设置画图的颜色
g2d.fill3DRect(x, y, 100, 100, true);//填充一个矩形
}
}

public class PanelTest
{
public static void main(String[] args)
{
JFrame  jf = new JFrame();
MyPanel jp = new MyPanel();

jf.setBounds(200, 200, 500, 500);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.add(jp);
jf.setVisible(true);

while(true)
{
//不停的重绘JPanel,实现动画的效果
jp.display();

try
{
Thread.sleep(300);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
然而,上面的方法不总是有效的,在开始的时候,如果为得到Graphics对像,那么g就为null,而下面直接使用g,就会产生空指针异常 。稳妥的办法是在使用g之前要加上判断 if(g != null) { ........}

二、图像缓冲

第二种方法就是使用Image和BufferImage技术,预先在一个图形缓冲中绘好要显示的内容,然后在paint方法中,一次性的把图形缓冲刷新到JPanel里肌,这种方法涉及到AWT中的Image和BufferImage,前者是一个接口,后者是一个可以实例化的类。其实,JPanel也是继承自AWT的Component类,该类有一个方法:Image createImage(int width, int height) ,这个方法也常在继承自JPanel的类中用于创建一幅用于双缓冲的、可在屏幕外绘制的图像。
实现方法一:
/**
* 定义一个继承自JPanel的类,重写它的paint方法 *
*/
class MyPanel1 extends JPanel
{
private int x = 200;
private int y = 200;
private Image image;	//图像缓冲
private Graphics og;

public void display()
{
x ++;
y ++;

if(og == null)
{
//JPanel继承自Component类,可以使用它的方法createImage创建一幅和JPanel大小相同的图形缓冲
//然后用它Image接口的方法获得绘图对像
image = this.createImage(this.getWidth(),this.getHeight());
if(image != null)og = image.getGraphics();
}

if(og != null)
{
//调用的super.paint(g),让父类做一些事前的工作,如刷新屏幕
super.paint(og);

og.setColor(Color.RED);				//设置画图的颜色
og.fill3DRect(x, y, 100, 100, true);//绘图
//this.paint(this.getGraphics());
}
//重绘JPanel
this.repaint();
}

/**
* repaint方法会调用paint方法,并自动获得Graphics对像
* 然后可以用该对像进行2D画图
* 注:该方法是重写了JPanel的paint方法
*/
public void paint(Graphics g)
{
g.drawImage(image, 0, 0, this);
}
}

public class PanelTest2
{
public static void main(String[] args)
{
JFrame  jf = new JFrame();
MyPanel1 jp = new MyPanel1();

jf.setBounds(200, 200, 500, 500);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.add(jp);
jf.setVisible(true);

while(true)
{
//不停的重绘JPanel,实现动画的效果
jp.display();

try
{
Thread.sleep(300);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
上面的方法是在自定义Panel的内部实现了Image对像的创建,绘图,刷新,然后有时候程序的模块化划分方法并不是这样,所以还可以在该类的外部创建一个Image对像,并完成绘图,将该对像的引用传递给自定义Panel的绘图方法,也可以完成绘图,并且,我觉得这样更灵活。

实现方法二:
class MyPanel3 extends JPanel
{
private int x = 200;
private int y = 200;

private Graphics g;
private Image im ;

//构造方法,获得外部Image对像的引用
public MyPanel3(Image im)
{
if(im != null)
{
this.im = im;
g = im.getGraphics();
}
}

public void display()
{
x ++;
y ++;
if(g != null)
{
//调用的super.paint(g),让父类做一些事前的工作,如刷新屏幕
super.paint(g);
g.setColor(Color.RED);				//设置画图的颜色
g.fill3DRect(x, y, 100, 100, true);	//填充一个矩形
//更新缓图
this.repaint();
}
}

/**
* repaint方法会调用paint方法,并自动获得Graphics对像
* 然后可以用该对像进行2D画图
* 注:该方法是重写了JPanel的paint方法
*/
public void paint(Graphics g)
{
g.drawImage(im, 0, 0, this);
}
}

public class PanelTEST4
{
public static void main(String[] args)
{
//在自定义Panel的外部定义一个Image绘图区
Image im = new BufferedImage(500,500,BufferedImage.TYPE_INT_RGB);

JFrame   jf = new JFrame();
//通过构造方法将缓冲缓冲区对像的引用传给自定义Panel
MyPanel3 jp = new MyPanel3(im);

jf.setBounds(200,200,500, 500);
jp.setSize(300, 300);
jf.add(jp);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setVisible(true);

while(true)
{
jp.display();

try
{
Thread.sleep(300);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}


总结:在绘制2D图形和实现动画的效果时,要用到AWT中的绘图技术和缓冲技术,如果只是简单的绘图,那么自定义Panel类,重写Paint方法,把要绘图代码放到paint方法中,由系统自动调用paint方法即可。
要实现动画效果则就要定时的调用repaint方法,repaint方法则会调用paint方法实现Panel重绘。

JPanel在什么情况下会被重绘呢?
1. 在repaint方法被显式的调用时。
2. 在窗口最小化然后又被显示时。
3. 在窗口被拉伸时。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: