【swing】JLabel详解以及使用示例

JLabel 对象可以显示文本、图像或同时显示二者。可以通过设置垂直和水平对齐方式,指定标签显示区中标签内容在何处对齐。默认情况下,标签在其显示区内垂直居中对齐。默认情况下,只显示文本的标签是开始边对齐;而只显示图像的标签则水平居中对齐。 还可以指定文本相对于图像的位置。默认情况下,文本位于图像的结尾边上,文本和图像都垂直对齐。

构造方法介绍:

JLabel() 创建无图像并且其标题为空字符串的 JLabel。

JLabel(Icon image) 创建具有指定图像的 JLabel 实例。

JLabel(Icon image, int horizontalAlignment) 创建具有指定图像和水平对齐方式的 JLabel 实例。

JLabel(String text) 创建具有指定文本的 JLabel 实例。

JLabel(String text, Icon icon, int horizontalAlignment) 创建具有指定文本、图像和水平对齐方式的 JLabel 实例。

JLabel(String text, int horizontalAlignment) 创建具有指定文本和水平对齐方式的 JLabel 实例。

常用方法:

getHorizontalAlignment() 返回标签内容沿 X 轴的对齐方式。

getHorizontalTextPosition() 返回标签的文本相对其图像的水平位置。

getIcon() 返回该标签显示的图形图像(字形、图标)。 getText() 返回该标签所显示的文本字符串。

setHorizontalAlignment(int alignment) 设置标签内容沿 X 轴的对齐方式。

setHorizontalTextPosition(int textPosition) 设置标签的文本相对其图像的水平位置。

setIcon(Icon icon) 定义此组件将要显示的图标。

setText(String text) 定义此组件将要显示的单行文本。 setUI(LabelUI ui) 设置呈现此组件的 L&F 对象。

setVerticalAlignment(int alignment) 设置标签内容沿 Y 轴的对齐方式。
setVerticalTextPosition(int textPosition) 设置标签的文本相对其图像的垂直位置。
在JLabel中增加图片和文本

package test;
import java.awt.FlowLayout; 
import javax.swing.ImageIcon; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.SwingConstants; 


/*在写swing的界面中发现用
JFrame.setDefaultLookAndFeelDecorated(true),对话框窗口的显示就会使用Java的外观风格比原来漂亮多了。
后来发现使用改方法没有效果了
原来是这个方法要写在new JFrame()对象之前。
错误的:
   JFrame f = new JFrame("Demo");
   JFrame.setDefaultLookAndFeelDecorated(true);
正确的:
   JFrame.setDefaultLookAndFeelDecorated(true);
   JFrame f = new JFrame("Demo");   

另外在写完界面的时候千万要注意要写一个关闭窗口的方法
我今天练习写界面写了很多界面 后来发现电脑越来越慢 内存都快没了 仔细检查才发现是  运行了一个界面之后 没有写关闭的方法 结果关闭后 还是在后台运行 这样好多界面都在后台运行 把内存耗光了。
1.
 JFrame f = new JFrame();
 f.addWindowListener(new WindowAdapter()
      {
          public void windowClosing(WindowEvent e)
          {
              System.exit(0);
          }
      });    
2.
JTable中关闭窗口后 让后台程序也一起关闭 
 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
*/

public class WorldClock { 
  public static void main(String[] args) { 
    JFrame.setDefaultLookAndFeelDecorated(true); 
    JFrame frame = new JFrame(); 
    frame.setTitle("JLabel Test"); 
    frame.setLayout(new FlowLayout()); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    ImageIcon imageIcon = new ImageIcon("001.jpg"); 

//    LEFT、RIGHT、CENTER、LEADING 、TRAILING等参数表示label中内容对齐方式:左对齐、右对齐、居中、靠顶对齐、靠下对齐
    /*第一个初始值,第二个对齐方式B:Label()构造一个空标签。
    Label(String text)
    使用指定的文本字符串构造一个新的标签,其文本对齐方式为左对齐。
    Label(String text, int alignment)
    构造一个显示指定的文本字符串的新标签,其文本对齐方式为指定的方式。
    C:label1.setHorizontalAlignment(SwingConstants.CENTER);
    label1.setVerticalAlignment(SwingConstants.TOP);
    Label类提供两个设置其对齐方式的方法:
    #setHorizontalAlignment:设置水平对齐方式;
    它的有效参数是:
    ¨ SwingConstants.LEFT:左对齐;(默认值,也就是不设置时则左对齐)
    ¨ SwingConstants.CENTER:居中对齐;
    ¨ SwingConstants.RIGHT:右对齐;*/
    JLabel label = new JLabel("Mixed", imageIcon, SwingConstants.RIGHT); 

    frame.add(label);
   /* Pack()方法的作用:调整此窗口的大小,以适合其子组件的首选大小和布局。如果该窗口和/或其所有者还不可显示,
    则在计算首选大小之前都将变得可显示。在计算首选大小之后,将会验证该窗口。*/
    frame.pack(); 
    frame.setVisible(true); 
  } 
} 
pre><p>p><p>p><p>p><p style="margin:0in; padding-top:0px; padding-bottom:0px; border:0px; list-style:none; word-wrap:normal; word-break:normal; line-height:18px; font-family:simsun; font-size:9pt">p><p><span style="background-color:rgb(255,255,255)">span>p><h2><span style="background-color:rgb(255,255,255)">JLabel中增加HTML文本span>h2><pre name="code" class="java" style="background-color: rgb(229, 231, 231);">package test;
import javax.swing.JFrame; 
import javax.swing.JLabel; 

public class WorldClock { 

  public static void main(String[] a) { 
    JFrame frame = new JFrame(); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

    JLabel label = new JLabel("<html>bold <br> plainhtml>"); 
    frame.add(label); 

    frame.setSize(300, 200); 
    frame.setVisible(true); 
  } 
} 

重写JLabel

package test;
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.io.Serializable; 

import javax.swing.JLabel; 

public class WorldClock extends JLabel implements Serializable { 
  transient private Color color; // not persistent 

  private boolean rectangular; // is persistent 

  public WorldClock() { 
    addMouseListener(new MouseAdapter() { 
      public void mousePressed(MouseEvent me) { 
        change(); 
      } 
    }); 
    rectangular = false; 
    setSize(200, 100); 
    change(); 
  } 

  public boolean getRectangular() { 
    return rectangular; 
  } 

  public void setRectangular(boolean flag) { 
    this.rectangular = flag; 
    repaint(); 
  } 

  public void change() { 
    color = randomColor(); 
    repaint(); 
  } 

  private Color randomColor() { 
    int r = (int) (255 * Math.random()); 
    int g = (int) (255 * Math.random()); 
    int b = (int) (255 * Math.random()); 
    return new Color(r, g, b); 
  } 

  public void paint(Graphics g) { 
    Dimension d = getSize(); 
    int h = d.height; 
    int w = d.width; 
    g.setColor(color); 
    if (rectangular) { 
      g.fillRect(0, 0, w - 1, h - 1); 
    } else { 
      g.fillOval(0, 0, w - 1, h - 1); 
    } 
  } 
} 

将JLabel增加到JScrollPane中便于显示大图片

package test;
import javax.swing.ImageIcon; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JScrollPane; 

public class WorldClock{ 
  public static void main(String[] args) { 
    JFrame frame = new JFrame(); 
    JLabel image = new JLabel(new ImageIcon("001.jpg")); 
//    向框架添加内容,首先获取内容面板,在此基础上不断添加元素。获取内容面板的时候有两种方法
    frame.getContentPane().add(new JScrollPane(image)); 

    frame.setSize(300, 300); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.setVisible(true); 
  } 
} 

JLabel中增加unicode编码

package test;
import java.awt.GridLayout; 

import javax.swing.JFrame; 
import javax.swing.JLabel; 

public class WorldClock { 
  public static void main(String args[]) { 
    UnicodeJFrame unicodeJFrame = new UnicodeJFrame(); 
    unicodeJFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    unicodeJFrame.setSize(350, 250); 
    unicodeJFrame.setVisible(true); 
  } 
} 

/*setToolTipText的作用?
 * 用来设置鼠标在Label上停留时显示提示信息的。
比如,你设置了 lbl.setToolTipText("This is a tip");后
那么当你运行程序,并将鼠标移动到lbl上停顿一下后,屏幕上就会显示This is a tip 。
*/

//在继承JFrame之后可以直接就是add(元素);

class UnicodeJFrame extends JFrame { 
  public UnicodeJFrame() { 
      //调用父类构造函数,在这里,里面元素表示名称
    super("Demonstrating Unicode"); 

    setLayout(new GridLayout(8, 1)); 

    JLabel englishJLabel = new JLabel("/u0057/u0065/u006C/u0063" 
        + "/u006F/u006D/u0065/u0020/u0074/u006F/u0020Unicode/u0021"); 
    englishJLabel.setToolTipText("This is English"); 
    add(englishJLabel); 

    JLabel chineseJLabel = new JLabel("/u6B22/u8FCE/u4F7F/u7528" + "/u0020/u0020Unicode/u0021"); 
    chineseJLabel.setToolTipText("This is Traditional Chinese"); 
    add(chineseJLabel); 

    JLabel cyrillicJLabel = new JLabel("/u0414/u043E/u0431/u0440" 
        + "/u043E/u0020/u043F/u043E/u0436/u0430/u043B/u043E/u0432" 
        + "/u0430/u0422/u044A/u0020/u0432/u0020Unicode/u0021"); 
    cyrillicJLabel.setToolTipText("This is Russian"); 
    add(cyrillicJLabel); 

    JLabel frenchJLabel = new JLabel("/u0042/u0069/u0065/u006E/u0076" 
        + "/u0065/u006E/u0075/u0065/u0020/u0061/u0075/u0020Unicode/u0021"); 
    frenchJLabel.setToolTipText("This is French"); 
    add(frenchJLabel); 

    JLabel germanJLabel = new JLabel("/u0057/u0069/u006C/u006B/u006F" 
        + "/u006D/u006D/u0065/u006E/u0020/u007A/u0075/u0020Unicode/u0021"); 
    germanJLabel.setToolTipText("This is German"); 
    add(germanJLabel); 

    JLabel japaneseJLabel = new JLabel("Unicode/u3078/u3087/u3045" + "/u3053/u305D/u0021"); 
    japaneseJLabel.setToolTipText("This is Japanese"); 
    add(japaneseJLabel); 

    JLabel portugueseJLabel = new JLabel("/u0053/u00E9/u006A/u0061" 
        + "/u0020/u0042/u0065/u006D/u0076/u0069/u006E/u0064/u006F/u0020" + "Unicode/u0021"); 
    portugueseJLabel.setToolTipText("This is Portuguese"); 
    add(portugueseJLabel); 

    JLabel spanishJLabel = new JLabel("/u0042/u0069/u0065/u006E" 
        + "/u0076/u0065/u006E/u0069/u0064/u0061/u0020/u0061/u0020" + "Unicode/u0021"); 
    spanishJLabel.setToolTipText("This is Spanish"); 
    add(spanishJLabel); 
  } 
} 

补充知识:

1.ImageIcon

一、问题
ImageIcon icon = new ImageIcon(“a.gif”);
执行结果是icon无法显示
二、解决
类中有如下调用:
ImageIcon icon = new ImageIcon(“a.gif”);

很自然地认为当前类文件和图片在同一路径下即可。
其实所谓的相对路径起点是工程的根目录,即project。
这行代码执行时在project目录下查找名为a.gif的文件,结果当然是找不到。
假如你的工程根目录为:project1
你的图片文件放在:project1/src/images/a.gif

所以正确的调用是:
ImageIcon icon = new ImageIcon(“src/images/a.gif”);
这行代码执行时在project目录下查找到了文件,当然也可以写成
ImageIcon icon = new ImageIcon(“./src/images/a.gif”);
注意两者的区别,要记住的是src是在project下的目录
总结起来就是一句话:所谓相对路径就是相对于工程根目录的位置^_^

三、其他
查看了一下ImageIcon的构造函数。
Public ImageIcon(String filename)//参数可以是绝对路径也可以是相对路径
Public ImageIcon(URL url)
第二种通过URL来得到图片
URL url = getClass().getResource(“a.gif”); //当前编译后class文件所在目录查找
ImageIcon icon = new ImageIcon(url);

问题讨论:
出现这种问题的原因大多是因为路径的问题,往往是在项目中运行正常,但是一旦打包成Jar后就不能正常显示了,下面总结一下解决此类问题的方法:
一、通过使用外部资源文件的方式解决
把项目打包生成Jar后,再新建一文件夹,把项目中所有使用的图片文件和生成Jar文件放在该目录下,只要代码对图片文件的引用路径正确,如:ImageIcon
image=new ImageIcon(SwingResourceManager.getImage (“icons/logo.gif”));就可以了。
这种方式下,图片文件与类文件不是一块放在包中的,类文件在包中,而图片文件在项目根目录下。
二、通过使用内部资源文件的方式解决
把所用的图片文件放在项目使用的包中,打包时把图片文件同时打进Jar文件中。这种方式在具体代码中应使用下面其中一种:
ImageIcon image = new ImageIcon(this.class.getResource(“icons/logo.gif”));
下面对这种方式详细说明:

问题解决:
当你编写一个图形界面的程序的时候,你肯定要使用各种图片资源。那么,当你发布你的程序的时候,这些图片资源如何发布呢?最简洁的方式就是将这些图片资源连同你的class文件一起打包为一个可执行Jar文件,这样你只需发布一个jar文件就囊括了所有的内容,用户只需双击该Jar文件就能运行程序。如果把图片打包在Jar文件中,编写程序的时候如何访问这些图片呢?这些图片的路径是什么呢?可以用getResource()方法来解决这个问题。下面我们具体分析2种最常见的情况:

1、你将所有资源打包为andy.jar,你的类位于一个包中:package andycpp;你的图片资源全部放在images文件夹中,而images文件夹也位于andycpp包内。这样的话,最终的路径表现为:

andy.jar
|__andycpp
|__ GUITest.class
|__ images
|__ Snap1.jpg
因为图片文件夹和引用他的类位于同一个层次,因此可以通过相对路径来访问: getResource()方法,但是你不能随便用,你只能使用和图片文件夹处于同一层次的类的getResource()方法。比如上图中,GUITest类和images处于同一层次,所以要使用该类的getResource()方法。

2、另一种情况,如果你的类有很多,并且包结构很复杂,那么你就不大可能把图片和类放在同一个层次上,而是应该把图片放到最外层,让所有的类通过绝对路径来访问该图片:

andy.jar
|__andycpp
|__ GUITest.class
|__ images
|__ Snap1.jpg
代码如下:

java.net.URL imgURL = GUITest.class.getResource(“/images/Snap1.jpg”);
ImageIcon img1 = new ImageIcon(imgURL);
大家看到和上述代码的区别了吗?区别非常细微,仅仅是在“images”的前面加了一个反斜杠”/”,这个反斜杠就表示根目录,没有反斜杠就表示相对路径。
java.net.URL imgURL = GUITest.class.getResource(“images/Snap1.jpg”);
ImageIcon img1 = new ImageIcon(imgURL);
2.implements Serializable有什么作用

http://blog.csdn.net/ukouryou/article/details/4132443
没有implements Serializable,你就不能通过rmi(包括ejb)提供远程调用。
serialization 允许你将实现了Serializable接口的对象转换为字节序列,这些字节序列可以被完全存储以备以后重新生成原来的对象。
serialization不但可以在本机做,而且可以经由网络操作(就是猫小说的RMI)。这个好处是很大的—-因为它自动屏蔽了操作系统的差异,字节顺序等。比如,在Window平台生成一个对象并序列化之,然后通过网络传到一台Unix机器上,然后可以在这台Unix机器上正确地重构这个对象。
Object serialization主要用来支持2种主要的特性:
1。Java的RMI(remote method invocation).RMI允许象在本机上一样操作远程机器上的对象。当发送消息给远程对象时,就需要用到serializaiton机制来发送参数和接收返回直。
2。Java的JavaBeans. Bean的状态信息通常是在设计时配置的。Bean的状态信息必须被存起来,以便当程序运行时能恢复这些状态信息。这也需要serializaiton机制。
总之如果在网络的环境下做类传输,应该还是implements Serializable。

package test;

import java.io.IOException; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.io.Serializable; 
import java.net.ServerSocket; 
import java.net.Socket;

//定义序列化(object)
class Student implements Serializable { 
      private int sno; 
      private String sname; 

      public Student(int sno, String sname) { 
              this.sno = sno; 
              this.sname = sname; 
      } 

      public int getSno() { 
              return sno; 
      } 

      public void setSno(int sno) { 
              this.sno = sno; 
      } 

      public String getSname() { 
              return sname; 
      } 

      public void setSname(String sname) { 
              this.sname = sname; 
      } 

      @Override 
      public String toString() { 
              return "学号:" + sno + ";姓名:" + sname; 
      } 

} 
//(object)的反序列化过程
class MyClient extends Thread { 
      @Override 
      public void run() { 
              try { 
                    Socket s = new Socket("localhost", 9999); 
                    ObjectInputStream ois = new ObjectInputStream(s.getInputStream()); 
                    Student stu = (Student) ois.readObject(); 
                    System.out.println("客户端程序收到服务器端程序传输过来的学生对象>> " + stu); 
                    ois.close(); 
                    s.close(); 
              } catch (IOException e) { 
                    // TODO Auto-generated catch block 
                    e.printStackTrace(); 
              } catch (ClassNotFoundException e) { 
                    // TODO Auto-generated catch block 
                    e.printStackTrace(); 
              } 
      } 
} 
//(object)的序列化过程
class MyServer extends Thread { 

      @Override 
      public void run() { 
              try { 
                    ServerSocket ss = new ServerSocket(9999); 
                    Socket s = ss.accept(); 
                    ObjectOutputStream ops = new ObjectOutputStream(s.getOutputStream()); 
                    Student stu = new Student(1, "赵本山"); 
                    ops.writeObject(stu); 
                    ops.close(); 
                    s.close(); 
                    ss.close(); 
              } catch (IOException e) { 
                    // TODO Auto-generated catch block 
                    e.printStackTrace(); 
              } 
      } 

} 
//测试
public class TestTransfer { 
      public static void main(String[] args) { 
              new MyServer().start(); 
              new MyClient().start(); 
      } 
}

3.transient关键字

  1. transient的作用及使用方法

    我们都知道一个对象只要实现了Serilizable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,我们可以不必关系具体序列化的过程,只要这个类实现了Serilizable接口,这个类的所有属性和方法都会自动序列化。

    然而在实际开发过程中,我们常常会遇到这样的问题,这个类的有些属性需要序列化,而其他属性不需要被序列化,打个比方,如果一个用户有一些敏感信息(如密码,银行卡号等),为了安全起见,不希望在网络操作(主要涉及到序列化操作,本地序列化缓存也适用)中被传输,这些信息对应的变量就可以加上transient关键字。换句话说,这个字段的生命周期仅存于调用者的内存中而不会写到磁盘里持久化。

    总之,java 的transient关键字为我们提供了便利,你只需要实现Serilizable接口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中。

package test;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

/**
 * @description 使用transient关键字不序列化某个变量
 *        注意读取的时候,读取数据的顺序一定要和存放数据的顺序保持一致
 *        
 */
public class TranSientTest {

    public static void main(String[] args) {

        User user = new User();
        user.setUsername("Alexia");
        user.setPasswd("123456");

        System.out.println("read before Serializable: ");
        System.out.println("username: " + user.getUsername());
        System.err.println("password: " + user.getPasswd());

        try {
            ObjectOutputStream os = new ObjectOutputStream(
                    new FileOutputStream("C:/user.txt"));
            os.writeObject(user); // 将User对象写进文件
            os.flush();
            os.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            ObjectInputStream is = new ObjectInputStream(new FileInputStream(
                    "C:/user.txt"));
            user = (User) is.readObject(); // 从流中读取User的数据
            is.close();

            System.out.println("\nread after Serializable: ");
            System.out.println("username: " + user.getUsername());
            System.err.println("password: " + user.getPasswd());

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}



class User implements Serializable {
    private static final long serialVersionUID = 8294180014912103005L;  

    private String username;
    private transient String passwd;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPasswd() {
        return passwd;
    }

    public void setPasswd(String passwd) {
        this.passwd = passwd;
    }

}

说明:
密码字段为null,说明反序列化时根本没有从文件中获取到信息。
2. transient使用小结
1)一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。

2)transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。

3)被transient关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化。

第三点可能有些人很迷惑,因为发现在User类中的username字段前加上static关键字后,程序运行结果依然不变,即static类型的username也读出来为“Alexia”了,这不与第三点说的矛盾吗?实际上是这样的:第三点确实没错(一个静态变量不管是否被transient修饰,均不能被序列化),反序列化后类中static型变量username的值为当前JVM中对应static变量的值,这个值是JVM中的不是反序列化得出的,

package test;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

/**
 * @description 使用transient关键字不序列化某个变量
 *        注意读取的时候,读取数据的顺序一定要和存放数据的顺序保持一致
 *        
 * @date  2013-10-15
 */
public class TranSientTest {

    public static void main(String[] args) {

        User user = new User();
        user.setUsername("Alexia");
        user.setPasswd("123456");

        System.out.println("read before Serializable: ");
        System.out.println("username: " + user.getUsername());
        System.err.println("password: " + user.getPasswd());

        try {
            ObjectOutputStream os = new ObjectOutputStream(
                    new FileOutputStream("C:/user.txt"));
            os.writeObject(user); // 将User对象写进文件
            os.flush();
            os.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            // 在反序列化之前改变username的值
            User.username = "jmwang";

            ObjectInputStream is = new ObjectInputStream(new FileInputStream(
                    "C:/user.txt"));
            user = (User) is.readObject(); // 从流中读取User的数据
            is.close();

            System.out.println("\nread after Serializable: ");
            System.out.println("username: " + user.getUsername());
            System.err.println("password: " + user.getPasswd());

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

class User implements Serializable {
    private static final long serialVersionUID = 8294180014912103005L;  

    public static String username;
    private transient String passwd;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPasswd() {
        return passwd;
    }

    public void setPasswd(String passwd) {
        this.passwd = passwd;
    }

}

这说明反序列化后类中static型变量username的值为当前JVM中对应static变量的值,为修改后jmwang,而不是序列化时的值Alexia。

  1. transient使用细节——被transient关键字修饰的变量真的不能被序列化吗?
import java.io.Externalizable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;

/**
 * @descripiton Externalizable接口的使用
 * 
 * @author Alexia
 * @date 2013-10-15
 *
 */
public class ExternalizableTest implements Externalizable {

    private transient String content = "是的,我将会被序列化,不管我是否被transient关键字修饰";

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeObject(content);
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException,
            ClassNotFoundException {
        content = (String) in.readObject();
    }

    public static void main(String[] args) throws Exception {

        ExternalizableTest et = new ExternalizableTest();
        ObjectOutput out = new ObjectOutputStream(new FileOutputStream(
                new File("test")));
        out.writeObject(et);

        ObjectInput in = new ObjectInputStream(new FileInputStream(new File(
                "test")));
        et = (ExternalizableTest) in.readObject();
        System.out.println(et.content);

        out.close();
        in.close();
    }
}

这是为什么呢,不是说类的变量被transient关键字修饰以后将不能序列化了吗?

  我们知道在Java中,对象的序列化可以通过实现两种接口来实现,若实现的是Serializable接口,则所有的序列化将会自动进行,若实现的是Externalizable接口,则没有任何东西可以自动序列化,需要在writeExternal方法中进行手工指定所要序列化的变量,这与是否被transient修饰无关。因此第二个例子输出的是变量content初始化的内容,而不是null。

4.继承自JLabel类

问题:java中我新建一个类,它继承自JLabel类,我重写了它的paint方法画了一个矩形,怎样使得这个类实例化以后,如果定义了这个对象的大小以后,这个矩形也会调整大小,以适应定义的大小。例如下面的代码怎样修改:
import java.awt.Graphics;

import javax.swing.JLabel;

public class RectDemo extends JLabel {
public void paint(Graphics g){
g.fillRect(0, 0, 50, 50);
}
}

import java.awt.Graphics;

import javax.swing.JLabel;

public class RectDemo extends JLabel {
int x;
int y;
int w;
int h;
public void setSize(int w,int h){
    this.w=w;
    this.h=h;
    this.repaint();
}
public void 
    public void paint(Graphics g){
        g.fillRect(x, y, w, h);
    }
}

Paint() - this method holds instructions to paint this component. Actually, in Swing, you should change paintComponent() instead of paint(), as paint calls paintBorder(), paintComponent() and paintChildren(). You shouldn’t call this method directly, you should call repaint() instead.

repaint() - this method can’t be overridden. It controls the update() -> paint() cycle. You should call this method to get a component to repaint itself. If you have done anything to change the look of the component, but not it’s size ( like changing color, animating, etc. ) then call this method.

validate() - This tells the component to lay itself out again and repaint itself. If you have done anything to change the size of the component or any of it’s children(adding, removing, resizing children), you should call this method… I think that calling revalidate() is preferred to calling validate() in Swing, though…

public void validate()验证此容器及其所有子组件。
使用 validate 方法会使容器再次布置其子组件。已经布置容器后,在修改此容器的子组件的时候应该调用上述方法。类似于刷新操作。

update() - This method is in charge of clearing the component and calling paint(). Again, you should call repaint() instead of calling this method directly… If you need to do fast updates in animation you should override this method to just call the paint() method.
animation:动画

updateUI() - Call this method if you have changed the pluggable look & feel for a component after it has been made visible.
pluggable:可插拔的
参考文献:java 2 AWT中paint()和repaint()方法的合理使用

你可能感兴趣的:(java)