1、介绍下我知道的轻量级和重量级组件
轻量级组件 是用JAVA代码画出来的,这样具有平台移植性.
重量级组件 是调用操作系统的函数画出来的组件,比如主窗体.
一般来说尽量用轻量级的组件,这样对程序的移植性很好,一般javax.swing包里的组件大部分是轻量级的java.awt里面的是重量级的。
Swing是由100%纯Java实现的,Swing组件是用Java实现的轻量级( light-weight)组件,没有本地代码,不依赖操作系统的支持,这是它与AWT组件的最大区别。由于AWT组件通过与具体平台相关的对等类(Peer)实现,因此Swing比AWT组件具有更强的实用性。Swing在不同的平台上表现一致,并且有能力提供本地窗口系统不支持的其它特性。2、在重量级组件中,清空背景的动作在update中实现,之后调用paint()。
import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;public class HeavyWeightPaintDEMO extends Canvas { /* Canvas是重量级组件 */
int i = 20;
int j = 30;
public HeavyWeightPaintDEMO() {
this.setPreferredSize(new Dimension(250, 350));
}//1、根据我的理解,如果不覆写update,那么将先调用update清空背景,在调用paint,这时只显示最新画出的那根直线,和预期效果一样。
//2、如果覆写update(即使用下面覆写的update函数),则先调用update(update中只有paint函数,背景不会被清空,并且调用paint,update结束后,会看到2根直
//线),再调用paint函数,也就是说paint函数被调用了2次;效果和预期一样,但是paint 只调用了一次,为啥子只调用一次呢????
//
/* public void update(Graphics g){ 
paint(g); //不擦除背景 
}*/ public void paint(Graphics g) {
g.setColor(Color.BLACK);
g.drawLine(i, i + 30, j, j + 40);
} public static void main(String[] args) {
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame myFrame = new JFrame("HeavyWeightPaintDEMO");
final HeavyWeightPaintDEMO t1 = new HeavyWeightPaintDEMO();
myFrame.add(t1);
JButton move = new JButton("移动");
move.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
t1.i = t1.i + 5;
t1.repaint();
}
}
); myFrame.add(BorderLayout.SOUTH, move);
myFrame.pack();
myFrame.setVisible(true);
}
}3、而对于轻量级组件,用户调用repaint()后,repaint()调用paint()实现绘制的动作。因此清空背景的动作在repaint()中实现,因此我们覆盖update不再有用,因为轻量级组件repaint()不再调用update。但是如果我们覆盖了repaint(),就可以达到同样的效果。import java.awt.*;
import java.awt.event.*;
import javax.swing.*;public class DrawString extends JPanel {
private int x = 20;
private int y = 20; public void paint(Graphics g) {
g.setColor(Color.red);
g.drawString("string ", x, y);
x = x + 20;
}

public static void main(String[] args) {
JFrame myFrame = new JFrame("DrawString");
final DrawString t1 = new DrawString();
myFrame.add(t1);
JButton move = new JButton("移动");
move.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
t1.repaint();
}
}
); myFrame.add(BorderLayout.SOUTH, move);
myFrame.setSize(400, 300);
myFrame.setVisible(true);
}
}为什么实际效果背景没有被清除呢?我哪里理解错误,请知道的解释下,谢谢。

解决方案 »

  1.   

    是原来的update()方法里面就调用了paint()方法吧
    而不是说是分开调用update();再paint();
      

  2.   

    我再表达自己观点清楚点
    就是说update()方法响应repaint()方法
    update()方法包括两个部分 1使用背景色填充 2调用paint()而不是说repaint()方法调用update()再调用paint()
      

  3.   

    你重写之前
    repaint()方法调用
    update()响应
    update
    {
       清屏();
       paint();
    }
    所以你只看到一条直线重写后
    update()
    {
      paint();
    }
    repaint()调用
    update()响应
    原来屏幕上有一条直线
    现在update()由于没有清屏,所以原来那条直线还在
    然后再画一条,就两条了
      

  4.   

    你意思是  重写之前
    调用了update 就不会调paint 了吧。
      

  5.   

    repaint()
    方法只是会调用update()方法
    如果还有疑问  你可以看下src包中的Canvas
      

  6.   

    从上面我的第三个程序来看,我并没有覆写repaint 方法,但是开始绘出的并没有清除。
      

  7.   

    api中JComponent的paint方法
    public void paint(Graphics g)由 Swing 调用,以绘制组件。应用程序不应直接调用 paint,而是应该使用 repaint 方法来安排重绘组件。 
    此方法实际上将绘制工作委托给三个受保护的方法:paintComponent、paintBorder 和 paintChildren。按列出的顺序调用这些方法,以确保子组件出现在组件本身的顶部。一般来说,不应在分配给边框的 insets 区域绘制组件及其子组件。子类可以始终重写此方法。只想特殊化 UI(外观)委托的 paint 方法的子类只需重写 paintComponent。 你要是重写paintComponent()方法就不会出现你的背景问题import java.awt.*; 
    import java.awt.event.*; 
    import javax.swing.*; public class DrawString extends JPanel { 
    private int x = 20; 
    private int y = 20; public void paintComponent(Graphics g) {
    super.paintComponent(g); 
    g.setColor(Color.red); 
    g.drawString("string ", x, y); 
    x = x + 20; 
    } public static void main(String[] args) { 
    JFrame myFrame = new JFrame("DrawString"); 
    final DrawString t1 = new DrawString(); 
    myFrame.add(t1); 
    JButton move = new JButton("移动"); 
    move.addActionListener(new ActionListener() { 
    public void actionPerformed(ActionEvent e) { 
    t1.repaint(); 


    ); myFrame.add(BorderLayout.SOUTH, move); 
    myFrame.setSize(400, 300); 
    myFrame.setVisible(true); 

    }