`

文字输入组件的使用与介绍

阅读更多

认识Swing的文字输入组件:
          Swing与文字输入有关的组件分别是JTextField、JPasswordField、JTextArea、JEditorPane与JTextPane.JTextField与
JPasswordField为单行的文本编辑器;JTextArea为多行的文本编辑器;JEditorPane可显示多种文件格式;JTextPane可设置文件各种
样式。这些组件都继承了JTextComponent为类,它们之间的关系如下:

                 |--JTextField--JPasswordField
                 |
   JTextComponent|
                 |--JTextArea
                 |
                 |--JEditorPane--JTextPane

     JTextComponent提供了相当多实用的方法,可使处理输入组件更为方便,例如copy(),paste(),cut(),getText(),setText()等
相当直觉的方法:另外还有设置是否可编辑(setEditable()),setSelectionEnd(),setSelectionStart())、设置或取得光标位置
(getCaretPosition(),setCaretPosition())等等,这些相当常用的方法你都可以在JTextComponent类中找到.
     Swing的文字输入组件均以Document来当作数据模式,当输入组件的内容有所改变时,均是更改此Document的内容。因此你可
以将同一个Document内容以不同的输入组件来显示,这就是MVC概念的一个基本应用。Document为一个interface,你可以实现此界
面或利用java提供的默认类来构造文字输入组件。


         |---implements-->AbstractDocument---extends->PlainDocument
         |                    
Document |                      
         |
         |--extends-->StyleDocument---implements--->DefaultStyleDocument---extends--->HTMLDocument
  
    AbstractDocument----extends-->DefaultStyleDocument

  PlainDocument是一个实体类,已经实现了AbstractDocument与Document中的所有抽象方法,你可以用此类直接构造出JTextField
、JPasswordField与JTextArea组件;相同的,你可以使用DefaultStyledDocument构造出JTextPane组件,这些关系我们均会在下面
各节中提到。下面我们开始介绍各种文字输入组件的使用:


9-2:使用JTextField组件:
JTextField继承JTextComponent类,因此它也可以使用JTextComponent抽象类里面许多好用的方法,如copy(),paste(),setText()
,isEditable()等等。我们可以在很多地方使用JTextField,JTextField是一个单行的输入组件,那么有没有多行的输入组件呢?有
的,就是JTextArea,我们将在后面介绍.

JTextField构造函数:
JTextField()
JTextField(Document doc,String text,int columns):使用指定的文件存储模式建立一个新的JTextField并设置其初始化字符串和
                                                字段长度。
JTextField(int columns):建立一个新的JTextField并设置其初始字段长度。
JTextField(String text):建立一个新的JTextField并设置其初始字字符串。
JTextField(String text,int columns):建立一个新的JTextField并设置其初始字符串和字段长度.

9-2-1:构造一般的JTextField组件:

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

public class JTextField1{

    public static void main(String args[])    {

    JFrame f = new JFrame("JTextField1");
    Container contentPane = f.getContentPane();
    contentPane.setLayout(new BorderLayout());

    JPanel p1 = new JPanel();
    p1.setLayout(new GridBagLayout());
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.anchor = GridBagConstraints.WEST; //设定Layout的位置
    gbc.insets = new Insets(2,2,2,2); //设定与边界的距离(上,左,下,右)
   
    p1.setBorder(BorderFactory.createTitledBorder("您的基本数据"));        
    JLabel l1 = new JLabel("姓名:");       
    JLabel l2 = new JLabel("性别:");       
    JLabel l3 = new JLabel("身高:");       
    JLabel l4 = new JLabel("体重:");       
    JTextField t1 = new JTextField();
    JTextField t2 = new JTextField(2);
    JTextField t3 = new JTextField("175cm");       
    JTextField t4 = new JTextField("50kg太瘦了",10);

    gbc.gridy=1;
    gbc.gridx=0;
    p1.add(l1,gbc);
    gbc.gridx=1;
    p1.add(t1,gbc);
    gbc.gridy=2;
    gbc.gridx=0;
    p1.add(l2,gbc);
    gbc.gridx=1;
    p1.add(t2,gbc);
    gbc.gridy=3;
    gbc.gridx=0;       
   p1.add(l3,gbc);
   gbc.gridx=1;
    p1.add(t3,gbc);
    gbc.gridy=4;
    gbc.gridx=0;       
    p1.add(l4,gbc);
    gbc.gridx=1;
    p1.add(t4,gbc);       
   
    contentPane.add(p1);       
    f.pack();       
    f.show();       
    f.addWindowListener(new WindowAdapter() {           
    public void windowClosing(WindowEvent e) {                   
    System.exit(0);           
    }       
    });   
    }
}

9-2-2:利用Document构造JTextField:
     Document是一个interface,主要的功能是定义一些方法,让我们在使用所有与Text相关的组件时,能够将输入文字的内容加以
结构化或规格化。将文字内容结构化又是什么呢?举例来说,就好像一本书的内容,它的结构一定会有各个大章,在各章中又会分
成许多小节,小节内会再有各个小重点等等,这样的树状组件结构就是结构化的一种。由于这个interface定义了10几个方法,但是
在这里我们所会用到的只有少数几个方法,为了不让大家混淆,因此我们先列出这个interface常被使用到的方法,有兴趣的可查阅
java api文件:

void   addDocumentListener(DocumentListener listener):增加DocumentListener,使组件具有处理DocumentEvent功能。

void   addUndoableEditListener(UndoableEditListener listener):增加UndoableEditListener,使组件具有处理UndoableEditEv
                                        Ent功能,当文件中的内容被修改时自动记忆可以被复原的内容。

String getText(int offset,int length):取得document中的文字内容。

void   insertString(int offset,String str,AttributeSet a):将字符串加入到Text组件的内容中。

void   removeDocumentListener(DocumentListener listener):移除DocumentListener.

void   removeUndoableEditListener(UndoableEditListener listener):移除UndoableEditListener,使复原功能失效。

   还记得我们一开始在介绍JTextField时所提到的构造函数吗?其中有一个JTextField的构造函数是这样子的:
         JTextField(Document doc,String text,int columns):使用指定的文件存储模式建立一个新的JTextField并设置其初始
                     化字符串和字段长度。
因此我们必须实作Document所有的方法,才能利用Document构造出JTextField,这样的做法有点麻烦,因为我们之前有提到Document
的方法有数十种,但是我们要用到的却只有其中几种,若是要将全部的方法实作那是相当费时的做法。大家还记行我们前几章介绍
JList时,利用继承AbstractListModel的抽象类来构造JList吗?由于抽象类已经了许多接口的方法,所以当我们继承这个抽象类后
便不需要实作这些方法。同样的java在这里也提供了一个AbstractDocument的抽象类来供我们使用。不过在这里我们并不是要使用
AbstractDocument,因为java在这部份已经提供了一个实体类:PlainDocument.这个实体类继承AbstractDocument,也就是具备了所
有AbstractDocument的方法,所以我们只要直接继承PlainDocument这个实体类就能利用Document来构造JTextField.这种概念跟
JList或是JTable的模式结构均是相同的。我们来看下面的范例:
JTextField3.java

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

public class JTextField3{

    public static void main(String args[])    {

    JFrame f = new JFrame("JTextField3");
    Container contentPane = f.getContentPane();
    contentPane.setLayout(new BorderLayout());

    JPanel p1 = new JPanel();       
    //p1.setLayout(new GridLayout(4,2));
    p1.setLayout(new GridBagLayout());
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.anchor = GridBagConstraints.WEST; //设定Layout的位置
    gbc.insets = new Insets(2,2,2,2); //设定与边界的距离(上,左,下,右)
   
    p1.setBorder(BorderFactory.createTitledBorder("您的基本数据"));        
    JLabel l1 = new JLabel("姓名:");       
    JLabel l2 = new JLabel("性别:");       
    JLabel l3 = new JLabel("身高:");       
    JLabel l4 = new JLabel("体重:");       
    JTextField t1 = new JTextField(new JTextField3_FixedLengthDocument(10),"",10);
    JTextField t2 = new JTextField(new JTextField3_FixedLengthDocument(1),"",2);
    JTextField t3 = new JTextField(new JTextField3_FixedLengthDocument(5),"",5);       
    JTextField t4 = new JTextField(new JTextField3_FixedLengthDocument(5),"",5);

    gbc.gridy=1;
    gbc.gridx=0;
    p1.add(l1,gbc);
    gbc.gridx=1;
    p1.add(t1,gbc);
    gbc.gridy=2;
    gbc.gridx=0;
    p1.add(l2,gbc);
    gbc.gridx=1;
    p1.add(t2,gbc);
    gbc.gridy=3;
    gbc.gridx=0;       
   p1.add(l3,gbc);
   gbc.gridx=1;
    p1.add(t3,gbc);
    gbc.gridy=4;
    gbc.gridx=0;       
    p1.add(l4,gbc);
    gbc.gridx=1;
    p1.add(t4,gbc);       
   
    contentPane.add(p1);       
    f.pack();       
    f.show();       
    f.addWindowListener(new WindowAdapter() {           
    public void windowClosing(WindowEvent e) {                   
    System.exit(0);           
    }       
    });   
    }
}

JTextField3_FixedLengthDocument.java

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

public class JTextField3_FixedLengthDocument extends PlainDocument{

private int maxLength;

public JTextField3_FixedLengthDocument(int maxLength){
this.maxLength = maxLength;
}

public void insertString(int offset,String str,AttributeSet att) throws BadLocationException
{
if ( getLength() + str.length() > maxLength ){
Toolkit.getDefaultToolkit().beep();
}else{
super.insertString(offset,str,att);
}
}
}

9-2-3:JTextField的事件处理:

  在JTextField类中有addActionListener()方法,可以检测到用户是否在JTextField上按下Enter键,就如同前面所介绍JButton按
下按钮时所产生的事件(Event)一样,我们来看下面这个范例:

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

public class JTextField4{
  public static void main(String[] args){
    JFrame f=new JFrame("JTextField4");
    Container contentPane=f.getContentPane();
    contentPane.setLayout(new BorderLayout());
   
    JPanel p1=new JPanel();
    p1.setLayout(new GridLayout(2,2));
    p1.setBorder(BorderFactory.createTitledBorder("JTextField事件处理范例"));
    JLabel l1=new JLabel("输入");
      JLabel l2=new JLabel("输入后,按下Enter==>");
    final JLabel l3=new JLabel("");
    final JTextField t1=new JTextField();
    t1.addActionListener(new ActionListener(){
    public void actionPerformed(ActionEvent ev){
      l3.setText(t1.getText());
    }
    });
    p1.add(l1);
    p1.add(t1);
    p1.add(l2);
    p1.add(l3);
    contentPane.add(p1);
    f.pack();       
    f.show();       
    f.addWindowListener(new WindowAdapter() {           
    public void windowClosing(WindowEvent e) {                   
    System.exit(0);           
    }       
    });   
  }
}

9-3:使用JPasswordField组件:
     JPasswordField的类层次结构图:
       java.lang.Object
             --java.awt.Component
               --javax.swing.JComponent
                --javax.swing.text.JTextComponent
                  --javax.swing.JTextField
                   --javax.swing.JPasswordField
    一般我们在网络中填写登录密码时,密码都会显示"*"号代表用户输入的字段,这样可避免用户输入的密码信息被旁人所偷窥。
而Swing中的JPasswordField就可以提供这样的功能。JPasswordField继承JTextField类,因此它也可以使用JTextField类里面许多
好用的方法,如addActionListener()、removeActionListener()、setHorizontalAlignment()等等。如同JTextField一样
JPasswordField也是一个单行的输入组件,不同的是JPasswordField多了屏蔽(Mask)的功能,也就是说在JPasswordField中的字符
都会以单一种的字符类型表现出来。
   在使用JPasswordField之前,我们先看看它的构造函数:
JPasswordField()
JPasswordField(Document doc,String text,int columns):使用指定的文件存储模式建立一个新的JPasswordField并设置其初始化
                                    字符串和字段长度。
JPasswordField(int columns):建立一个新的JPasswordField并设置其初始字段长度。
JPasswordField(String text):建立一个新的JPasswordField并设置其初始字字符串。
JPasswordField(String text,int columns):建立一个新的JPasswordField并设置其初始字符串和字段长度.

9-3-1:构造一般的JPasswordField组件:
   JPasswordField的构造函数和JTextField的构造函数几乎一模本样,唯一不同的是在JPasswordField输入时字符会以屏蔽字符的
类型表示。我们来看下面这个范例:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class JPasswordField1{

    public static void main(String args[])    {

    JFrame f = new JFrame("JPasswordField1");
    Container contentPane = f.getContentPane();
    contentPane.setLayout(new BorderLayout());

    JPanel p1 = new JPanel();       
    //p1.setLayout(new GridLayout(4,2));
    p1.setLayout(new GridBagLayout());
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.anchor = GridBagConstraints.WEST; //设定Layout的位置
    gbc.insets = new Insets(2,2,2,2); //设定与边界的距离(上,左,下,右)
   
    p1.setBorder(BorderFactory.createTitledBorder("您的基本数据"));        
    JLabel l1 = new JLabel("姓名:");       
    JLabel l2 = new JLabel("性别:");       
    JLabel l3 = new JLabel("身高:");       
    JLabel l4 = new JLabel("体重:");       
    JPasswordField t1 = new JPasswordField();
    JPasswordField t2 = new JPasswordField(2);
    JPasswordField t3 = new JPasswordField(" 175cm");
    JPasswordField t4 = new JPasswordField(" 50kg太瘦了",10);

t1.setPreferredSize(t1.getPreferredSize());   
    gbc.gridy=1;
    gbc.gridx=0;
    p1.add(l1,gbc);
    gbc.gridx=1;
    p1.add(t1,gbc);
    gbc.gridy=2;
    gbc.gridx=0;
    p1.add(l2,gbc);
    gbc.gridx=1;
    p1.add(t2,gbc);
    gbc.gridy=3;
    gbc.gridx=0;       
   p1.add(l3,gbc);
   gbc.gridx=1;
    p1.add(t3,gbc);
    gbc.gridy=4;
    gbc.gridx=0;       
    p1.add(l4,gbc);
    gbc.gridx=1;
    p1.add(t4,gbc);       
   
    contentPane.add(p1);       
    f.pack();       
    f.show();       
    f.addWindowListener(new WindowAdapter() {           
    public void windowClosing(WindowEvent e) {                   
    System.exit(0);           
    }       
    });   
    }
}

  我们可以看到默认的字符串都以屏蔽字符"*"来表示,"*"字符是JPasswordField默认的屏蔽字符,我们可以利用JPasswordField
提供的setEchoChar()方法来改用其他字符来作为屏蔽字符。我们来看下面的范例:

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

public class JPasswordField2{

    public static void main(String args[])    {

    JFrame f = new JFrame("JPasswordField2");
    Container contentPane = f.getContentPane();
    contentPane.setLayout(new BorderLayout());

    JPanel p1 = new JPanel();       
    p1.setLayout(new GridLayout(4,2));       
    p1.setBorder(BorderFactory.createTitledBorder("您的基本数据"));        
    JLabel l1 = new JLabel("姓名:");       
    JLabel l2 = new JLabel("性别:");       
    JLabel l3 = new JLabel("身高:");       
    JLabel l4 = new JLabel("体重:");       
    JPasswordField t1 = new JPasswordField(10);
    JPasswordField t2 = new JPasswordField(2);
    JPasswordField t3 = new JPasswordField(" 175cm");
    JPasswordField t4 = new JPasswordField(" 50kg太瘦了",10);
   
    t1.setEchoChar('#');
    t2.setEchoChar('%');
    t3.setEchoChar('&');
    t4.setEchoChar('M');
   
    p1.add(l1);       
    p1.add(t1);       
    p1.add(l2);       
    p1.add(t2);       
   p1.add(l3);       
    p1.add(t3);       
    p1.add(l4);       
    p1.add(t4);       
   
    contentPane.add(p1);       
    f.pack();       
    f.show();       
    f.addWindowListener(new WindowAdapter() {           
    public void windowClosing(WindowEvent e) {                   
    System.exit(0);           
    }       
    });   
    }
}

9-3-2:利用Document构造JPasswordField:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class JPasswordField3{

    public static void main(String args[])    {

    JFrame f = new JFrame("JPasswordField3");
    Container contentPane = f.getContentPane();
    contentPane.setLayout(new BorderLayout());

    JPanel p1 = new JPanel();       
    //p1.setLayout(new GridLayout(4,2));
    p1.setLayout(new GridBagLayout());
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.anchor = GridBagConstraints.WEST; //设定Layout的位置
    gbc.insets = new Insets(2,2,2,2); //设定与边界的距离(上,左,下,右)
   
    p1.setBorder(BorderFactory.createTitledBorder("您的基本数据"));        
    JLabel l1 = new JLabel("姓名:");       
    JLabel l2 = new JLabel("性别:");       
    JLabel l3 = new JLabel("身高:");       
    JLabel l4 = new JLabel("体重:");       
    JPasswordField t1 = new JPasswordField(new JPasswordField3_OnlyNumberDocument(10),"",10);
    JPasswordField t2 = new JPasswordField(new JPasswordField3_OnlyNumberDocument(1),"",2);
    JPasswordField t3 = new JPasswordField(new JPasswordField3_OnlyNumberDocument(5),"",5);       
    JPasswordField t4 = new JPasswordField(new JPasswordField3_OnlyNumberDocument(5),"",5);

    gbc.gridy=1;
    gbc.gridx=0;
    p1.add(l1,gbc);
    gbc.gridx=1;
    p1.add(t1,gbc);
    gbc.gridy=2;
    gbc.gridx=0;
    p1.add(l2,gbc);
    gbc.gridx=1;
    p1.add(t2,gbc);
    gbc.gridy=3;
    gbc.gridx=0;       
       p1.add(l3,gbc);
       gbc.gridx=1;
    p1.add(t3,gbc);
    gbc.gridy=4;
    gbc.gridx=0;       
    p1.add(l4,gbc);
    gbc.gridx=1;
    p1.add(t4,gbc);       
   
    contentPane.add(p1);       
    f.pack();       
    f.show();       
    f.addWindowListener(new WindowAdapter() {           
    public void windowClosing(WindowEvent e) {                   
    System.exit(0);           
    }       
    });   
    }
}

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

public class JPasswordField3_OnlyNumberDocument extends PlainDocument{

private int maxLength;
int result;

public JPasswordField3_OnlyNumberDocument(int maxLength){
this.maxLength = maxLength;
}

public void insertString(int offset,String str,AttributeSet att) throws BadLocationException
{
for(int i=0;i<=9;i++){
result = Integer.toString(i).compareTo(str);
if (result == 0){ //是数字才处理

  if ( getLength() + str.length() > maxLength ){
   Toolkit.getDefaultToolkit().beep();
  }else{
super.insertString(offset,str,att);
  }
}
}
}
}

9-4:使用JTextArea组件:
   JTextArea的类层次结构图:
       java.lang.Object
           --java.awt.Component
            --java.awt.Container
              --javax.swing.JCompontent
                --javax.swing.text.JTextComponent
                  --javax.swing.JTextArea
    JTextArea继承JTextComponent为类,因此它也可以使用JTextComponent抽象类里面许多好用的方法,如compy(),paste(),
setText(),isEditable()等等。我们在前面有提到JTextArea是一个多行的输入组件,在这个组件中可以利用Enter来做换行的操作

在使用JTextArea之前,我们先看看JTextArea有哪些构造函数可以使用:

JTextArea的构造函数:
  JTextArea():建立一个新的JTextArea.
  JTextArea(Document doc):使用指定的文件存储模式建立一个新的JTextArea.
  JTextArea(Document doc,String text,int row ,int columns):使用指定的文件存储模式建立一个新的JTextArea并设置其初始
                                  字符串和列、字段长度。
  JTextArea(int row,int columns):建立一个新的JTextArea并设置其初始列、字段长度。
  JTextArea(String text):建立一个新的JTextArea并设置其初始字符串.
  JTextArea(String text,int row,int columns):建立一个新的JTextArea并设置其初始字符串和列、字段长度。

9-4-1:构造JTextArea组件:
   我们可以发现到JTextArea的构造函数和JTextField及JPasswordField的构造函数是相同雷同,而JTextArea多了一个字段的参数
值是因为JTextArea是二维的输入组件,在构造时不仅要设置字段长度也要设置行数。我们来看下面这个范例:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class JTextArea1{
  public static void main(String[] args){
     JFrame f=new JFrame("JTextArea1");
     Container contentPane=f.getContentPane();
     contentPane.setLayout(new BorderLayout());
    
     JPanel p1=new JPanel();
     p1.setLayout(new GridBagLayout());
     GridBagConstraints gbc=new GridBagConstraints();
     gbc.anchor=GridBagConstraints.WEST;
     gbc.insets=new Insets(2,2,2,2);
    
     p1.setBorder(BorderFactory.createTitledBorder("构造一般的JTextArea"));
     JLabel l1=new JLabel("一:");
     JLabel l2=new JLabel("二:");
     JLabel l3=new JLabel("三:");
     JLabel l4=new JLabel("四:");
    
     JTextArea t1=new JTextArea();
     JTextArea t2=new JTextArea(2,8);
     JTextArea t3=new JTextArea("JTextArea3");
     JTextArea t4=new JTextArea("JTextArea4",5,10);
    
        t1.setText("JTextArea1");//setText()方法会将原来的内容清除
        t2.append("JTextArea2");//append()方法会将设置的字符串接在原来JTextArea内容文字之后.
        t4.setLineWrap(true);//设置换行
       
        gbc.gridy=1;
        gbc.gridx=0;
        p1.add(l1,gbc);
        gbc.gridx=1;
        p1.add(t1,gbc);
        gbc.gridy=2;
        gbc.gridx=0;
        p1.add(l2,gbc);
        gbc.gridx=1;
        p1.add(t2,gbc);
           gbc.gridy=3;
           gbc.gridx=0;
           p1.add(l3,gbc);
           gbc.gridx=1;
          p1.add(t3,gbc);
          gbc.gridy=4;
          gbc.gridx=0;
          p1.add(l4,gbc);
          gbc.gridx=1;
          p1.add(t4,gbc);
          contentPane.add(p1);
          f.pack();
          f.show();
          f.addWindowListener(new WindowAdapter(){
          public void windowClosing(WindowEvent e){
            System.exit(0);
          }
          });
  }
}

    在JTextArea中我们可以使用setTabSize()方法设置[Tab]键的跳离距离,或是setFont()方法设置字体。当我们输入的文字超过
JTextArea的右边界及下边界时,会看不到接下来打的内容,那该怎么办呢?你可以使用JScrollPane使JTextArea具备滚动的能力,
或是搭配setLineWrap()方法就能让文字自动换行。JTextArea还提供一个setWrapStyleWord()方法,可以让换行的时候不会造成断
字的现象,这在Word或使用OutLook写信时都可以看到这个效果。例如我们在行尾中输入“自动换行”四个字,但此行最多只能在容
纳两个字,因此JTextArea会将此四个字均移到下一行,不会造成“自动”在上行,"换行"在下行的情形。这在处理英文输入上较为
重要,因为setWrapStyleWord()是利用空白当作是一个字输入的结果。我们来看下面的范例:

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

public class JTextArea2{
  public static void main(String[] args){
    JFrame f=new JFrame("JTextArea2");
    Container contentPane=f.getContentPane();
    contentPane.setLayout(new BorderLayout());
   
    JPanel p1=new JPanel();
    p1.setLayout(new GridLayout(1,1));
    p1.setBorder(BorderFactory.createTitledBorder("构造TextArea-使用GridLayout,加ScrollBar"));
   
    JTextArea t1=new JTextArea(5,25);
    t1.setTabSize(10);
    t1.setFont(new Font("标楷体",Font.BOLD,16));
    t1.setLineWrap(true);//激活自动换行功能
      t1.setWrapStyleWord(true);//激活断行不断字功能
     
      p1.add(new JScrollPane(t1));//将JTextArea放入JScrollPane中,这样就能利用滚动的效果看到输入超过JTextArea高度的
                                  //文字.
      contentPane.add(p1);
      f.pack();
      f.show();
      f.addWindowListener(new WindowAdapter(){
      public void windowClosing(WindowEvent e){
        System.exit(0);
      }
      });
  }
}
     我们再举一个例子,使JTextArea具有copy、paste、cut的功能:

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

public class JTextArea3 implements ActionListener{
JTextArea textarea=null;
JButton b1,b2,b3;

    public JTextArea3(){
      JFrame f=new JFrame("JTextArea3");
      Container contentPane=f.getContentPane();
      contentPane.setLayout(new BorderLayout());
     
      textarea=new JTextArea(10,15);
      JScrollPane scrollPane=new JScrollPane(textarea);
      JPanel panel=new JPanel();
         panel.setLayout(new GridLayout(1,3));
         b1=new JButton("Copy");
         b1.addActionListener(this);
         b2=new JButton("Paste");
         b2.addActionListener(this);
         b3=new JButton("Cut");
         b3.addActionListener(this);
           panel.add(b1);
           panel.add(b2);
           panel.add(b3);
          
           contentPane.add(scrollPane,BorderLayout.CENTER);
           contentPane.add(panel,BorderLayout.SOUTH);
          
           f.pack();
           f.show();
           f.addWindowListener(new WindowAdapter(){
             public void windowClosing(WindowEvent e){
             System.exit(0);
             }
           });
    }
    public static void main(String[] args){
     new JTextArea3();
    }
    public void actionPerformed(ActionEvent e){
      if (e.getSource()==b1){
        textarea.copy();
      }
      if (e.getSource()==b2){
        textarea.paste();
      }
      if (e.getSource()==b3){
        textarea.cut();
      }
    }
}

9-4-2:JTextArea的事件处理:
   由于JTextArea是一个二维的输入组件,因此[Enter]键在JTextArea中代表的意义只是单纯的换行字符而不再是一个事件驱动的
切入点。那么我们该 如何来处理JTextArea的事件呢?还记得我们在前面介绍过Listener的机制吗?相同的,我们一样需要使用
Listener的机制来处理发生在JTextArea中的事件,只是不再是以前提到的ActionListener了。在JTextArea中使用的Listener有两
种,一个是UndoableEditListener,另一个是DocumentListener.UndoableEditListener interface是负责纪录JTextArea中所有操作
发生的顺序并且可以运行还原上一步的功能。这个功能在目前的软件中应用相当广泛,如文书编辑软件Word中的复原功能、小画家
中的复原功能,相信大家都有使用过。DocumentListener interface则是纪录发生在JTextArea中所有的事件(如键入字符、删除
字符、剪下、贴上)并将所有的事件以树状的层次式结构组织起来;也就是说当JTextArea中的内容有任何变动时,会DocumentEvent
,此时必须使用DocumentListener接口中的方法来处理此事件。我们来看下面这个范例,使JTextArea具有复原的功能:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/*由于会使用到复原和事件驱动功能,因此需要将javax.swing.undo和javax.swing.event两个package包含进来
  */
import javax.swing.undo.*;
import javax.swing.event.*;
/*JTextArea4类继承JFrame类并实作UndoableEditListener interface.实作UndoableEditListener interface就必须要编写其中的
*undoableEditHappened().
*/
public class JTextArea4 extends JFrame implements UndoableEditListener{

    private UndoableEdit edit;
    private JTextArea    jta;
    private JTextArea    message;
    private JMenuItem    undoitem;
    private JMenuItem    redoitem;
  
    public JTextArea4(){
   
    super("JTextArea4");
    jta = new JTextArea();
    jta.getDocument().addUndoableEditListener(this);//将JTextArea加入UndoableEditListener.

        message = new JTextArea();
        message.setEditable(false);//利用setEditable()方法将另一个JTextArea设置为不可编辑.

        JPanel p1 = new JPanel();
        p1.setLayout(new GridLayout(1,1));
        p1.setBorder(BorderFactory.createTitledBorder("Edit Area")); 
        p1.add(new JScrollPane(jta));
//--begin:分别将两个JTextArea通过JPanel放到JFrame中。
        JPanel p2 = new JPanel();
        p2.setLayout(new GridLayout(1,1));
        p2.setBorder(BorderFactory.createTitledBorder("Message")); 
        p2.add(new JScrollPane(message));       
       
    getContentPane().setLayout(new GridLayout(2,1));
    getContentPane().add(p1);
    getContentPane().add(p2);
//--end  
     //建立目录菜单并放置到JFrame中.
    JMenuBar bar  = new JMenuBar();
    JMenu theMenu = new JMenu("Edit");
    undoitem = new JMenuItem("Undo");
    redoitem = new JMenuItem("Redo");
    theMenu.add(undoitem);
    theMenu.add(redoitem);
    bar.add(theMenu);
    updateMenuItem();//构造目录菜单
   
    setJMenuBar(bar);
    setSize(300,300);
   
        //采用inner class方式,分别构造菜单选项被点选后的运行操作。分别调用undo(),redo()方法来完成.
    undoitem.addActionListener(new ActionListener(){
    public void actionPerformed(ActionEvent ev){
    edit.undo();
    updateMenuItem();//运行undo功能
    message.append("- Undo -\n");
    }
    });

    redoitem.addActionListener(new ActionListener(){
    public void actionPerformed(ActionEvent ev){
    edit.redo();
    updateMenuItem();//运行redo功能
    message.append("- Redo -\n");
    }
    });   
    }//end of JTextArea4()

    public void undoableEditHappened(UndoableEditEvent ev){
    StringBuffer buf = new StringBuffer(200);
         /*当用户在Text Area中有所操作时,就可以用getEdit()方法取得UndoableEdit对象,此对象纪录着刚刚用户的操作,因
          *此可由些对象的undo()或redo()达到取消或复原的功能.
          */
    edit = ev.getEdit();
    buf.append("undoableEdit:");
    buf.append(edit.getPresentationName());
    buf.append("\n");
    message.append(buf.toString());
    updateMenuItem();
    }//end of undoableEditHappened()
//判断是否此时是否可以运行undo或redo的功能,并且改变目录菜单的状态值.
    public void updateMenuItem(){
   
    if (edit != null){
  undoitem.setEnabled(edit.canUndo());
  redoitem.setEnabled(edit.canRedo());
  undoitem.setText(edit.getUndoPresentationName());
  redoitem.setText(edit.getRedoPresentationName());
    }else{
  undoitem.setEnabled(false);
    redoitem.setEnabled(false);
  undoitem.setText("Undo");
  redoitem.setText("Redo");
}
    }//end of updateMenu()

    public static void main(String args[])    {

    JFrame f = new JTextArea4();
    f.addWindowListener(new WindowAdapter() {           
    public void windowClosing(WindowEvent e) {                   
    System.exit(0);           
    }       
    });
    f.show();
    }//end of main()
}//end of class JTextArea4
   我们在前面提到Enter键在JTextArea中不再是事件驱动的切入点,因此我们要利用Listener的机制来控制JTextArea的事件驱动
。但是,我们要怎么样知道在JTextArea中的数据内容呢?这就要了解JTextArea的存储模式了,JTextArea把输入区内的每一行当成
一个独立的单无(Element),并依照Document内规划的树状结构来存储,也就是说在JTextArea的第一行属于Element 0、第二行属于
Element 1、第三行属于Element 2等等。不论我们在费心的去处理。接下来我们来看看,Element和DocumentListener interface的
用法。我们改写JTextArea4.java加入DocumentListener,将程序存储为JTextArea5.java.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.undo.*;
import javax.swing.event.*;
import javax.swing.text.*;

public class JTextArea5 extends JFrame implements UndoableEditListener,DocumentListener{
   private UndoableEdit edit;
   private JTextArea  jta;
   private JTextArea  message;
   private JMenuItem undoitem;
   private JMenuItem redoitem;
   public JTextArea5(){
      super("JTextArea");
      jta=new JTextArea();
      jta.getDocument().addUndoableEditListener(this);
      jta.getDocument().addDocumentListener(this);
        message = new JTextArea();
        message.setEditable(false);

        JPanel p1 = new JPanel();
        p1.setLayout(new GridLayout(1,1));
        p1.setBorder(BorderFactory.createTitledBorder("Edit Area")); 
        p1.add(new JScrollPane(jta));

        JPanel p2 = new JPanel();
        p2.setLayout(new GridLayout(1,1));
        p2.setBorder(BorderFactory.createTitledBorder("Message")); 
        p2.add(new JScrollPane(message));       
       
    getContentPane().setLayout(new GridLayout(2,1));
    getContentPane().add(p1);
    getContentPane().add(p2);
   
    JMenuBar bar  = new JMenuBar();
    JMenu theMenu = new JMenu("Edit");
    undoitem = new JMenuItem("Undo");
    redoitem = new JMenuItem("Redo");
    theMenu.add(undoitem);
    theMenu.add(redoitem);
    bar.add(theMenu);
    updateMenuItem();
   
    setJMenuBar(bar);
    setSize(300,300);
   
    undoitem.addActionListener(new ActionListener(){
    public void actionPerformed(ActionEvent ev){
    edit.undo();
    updateMenuItem();
    message.append("- Undo -\n");
    }
    });

    redoitem.addActionListener(new ActionListener(){
    public void actionPerformed(ActionEvent ev){
    edit.redo();
    updateMenuItem();
    message.append("- Redo -\n");
    }
    });   
   } //end of JTextArea5
    public void undoableEditHappened(UndoableEditEvent ev){
    StringBuffer buf = new StringBuffer(200);
    edit = ev.getEdit();
    buf.append("undoableEdit:");
    buf.append(edit.getPresentationName());
    buf.append("\n");
    message.append(buf.toString());
    updateMenuItem();
    }//end of undoableEditHappened()

    public void updateMenuItem(){
   
    if (edit != null){
  undoitem.setEnabled(edit.canUndo());
  redoitem.setEnabled(edit.canRedo());
  undoitem.setText(edit.getUndoPresentationName());
  redoitem.setText(edit.getRedoPresentationName());
    }else{
  undoitem.setEnabled(false);
    redoitem.setEnabled(false);
  undoitem.setText("Undo");
  redoitem.setText("Redo");
    }
    }//end of updateMenu()
    public void showDE(DocumentEvent de){
      StringBuffer debuf=new StringBuffer(100);
      debuf.append(de.getType());
      debuf.append("Offset:");
      debuf.append(de.getOffset());
      debuf.append("Length:");
      debuf.append(de.getLength());
     
      Element Eroot=jta.getDocument().getDefaultRootElement();
      DocumentEvent.ElementChange Echange=de.getChange(Eroot);
      if (Echange==null) {
      debuf.append("(No Element Change)");
      }else{
      debuf.append("Element Change:index");
      debuf.append("Echange.getIndex()");
      }
      debuf.append("\n");
      message.append(debuf.toString());
    }
    public void changedUpdate(DocumentEvent de){
      showDE(de);
    }
    public void insertUpdate(DocumentEvent de){
      showDE(de);
    }
    public void removeUpdate(DocumentEvent de){
      showDE(de);
    }
    public static void main(String[] args){
      JFrame f=new JTextArea5() ;
      f.addWindowListener(new WindowAdapter(){
      public void windowClosing(WindowEvent e){
        System.exit(0);
      }
      });
      f.show();
    }
}

9-5:使用JEditorPane组件:
JEditorPane的类层次结构图:
    java.lang.Object
      --java.awt.Component
        --java.awt.Container
          --javax.swing.JComponent
           --javax.swing.text.JTextComponent
             --javax.swing.JEditorPane
    JEditorPane继承JTextComponent类,因此它也可以使用JTextComponent抽象类里面的方法。JEditorPane的最主要功能在于展
现不同类型的文件格式内容。JEditorPane支持的文件类型有三种:第一种是纯文本类型,其类型的表示法为"text/plain",这种类型
的文件就是我们最常使用的txt文件,这类型的文件可以用记事本或WordPad等文书编辑软件来编辑。第二种是RTF类型,其表示法
为"text/rtf",这种类型的文件特色是能对文字内容做字体缩放、变形、上色等特殊效果。第三类是HTML类型,也就是我们在网络上
所浏览的网页类型,其表示法为"text/html",这类文件的特色相信大家都非常的清楚,除了在对字体效果的表现之外还具有在文件
内加入图片、超级链接等相关功能。但是JEditorPane并不是一个全功能的Web Browser,它仅能支持简单的HTML语法.JEditorPane支
持HTML类型的文件最主要的用途是用来制作在线辅助说明文件。
JEditorPane构造函数:
JEditorPane():建立一个新的JEditorPane.
JEditorPane(String url):以详细的URL字符串为基础来建立一个JEditorPane。
JEditorPane(String type,String text):建立一个被指定字符串text并指定初始化JEditorPane的类型。
JEditorPane(URL initialPage):以详细的URL字符串当作输入值来建立一个JEditorPane.

9-5-1:构造JEditorPane组件:
   我们将一个HTML文件放在构造完成的JEditPane中:
import javax.swing.*;
import javax.swing.event.*;
import java.io.*;
import java.awt.event.*;

public class JEditorPane1{
   public static void main(String[] args){
     JEditorPane editPane=null;
     try{
       File file=new File("docs/JEditorPane_1.html");
       String str=file.getAbsolutePath();//取得文件位置的绝对路径
       str="file:"+str;//将绝对路径合成一完整的输入字符串

/*利用setPage()方法将字符串中路径所指的文件加载JEditorPane.
  *在setPage()方法中,输入的数据是String类型的字符串,其实这样的构造方式等同于利用JEditorPane的另一个构造函数
  *JEditorPane(String str)来构造。因此如果我们将下面两行程序改写如下行:
  *               editPane=new JEditorPane(str);
  *会得到相同的效果,所以我们就不再对此种构造方式再多加说明.
  */ 
       editPane=new JEditorPane();//构造一个空的JEditorPane
       editPane.setPage(str);
     }catch(IOException ioe){
       ioe.printStackTrace(System.err);
       System.exit(0);
     }
    /*利用setEditable()方法将JEditorPane设为不可编辑.请注意,这行是相当重要的,若是我们将这个方法设为true,我们将会
     *失去HTML文件本身的特性,如超级链接的功能等等。因此我们在使用下面JEditorPane2的例子时,一般都会将编辑的功能取
     *消(设置false).目前这个超级链接功能并没有作用,这部份将在JEditorPane的事件处理中介绍.
     */
     editPane.setEditable(false);
     JFrame f=new JFrame("JEditorPane1");
     f.setContentPane(new JScrollPane(editPane));
     f.setSize(200,200);
     f.show();
     f.addWindowListener(new WindowAdapter(){
     public void windowClosing(WindowEvent e){
       System.exit(0);
     }
     });
   }
}
    我们在前面提到JEditorPane支持三种类型的文件格式,在上面的例子里我们并没有看到设置文件格式的步骤,那是因为在上面
的构造方法中系统会依照输入文件名称来自动判别文件类型。若是我们想要自己设置文件类型可利用setContentType()方法,或是
直接在JEditorPane构造函数中设置。如下面这个范例:
import javax.swing.*;
import javax.swing.event.*;
import java.awt.event.*;

public class JEditorPane2{
  public static void main(String[] args){
    String str=new String("This is a test.\nthis is Line2!\nThis is Line 3!");
    JEditorPane editPane=new JEditorPane("text/plain",str);
    editPane.setEditable(false);
   
    JFrame f=new JFrame("JEditorPane2");
    f.setContentPane(new JScrollPane(editPane));
    f.pack();
    f.show();
    f.addWindowListener(new WindowAdapter(){
      public void windowClosing(WindowEvent e){
      System.exit(0);
      }
    });
  }
}
     以URL类当作JEditPane的参数来构造,但是要注意的地方是使用这种方式来构造里,计算机要连接上局域网络或网际网络不然
程序会找不到URL指定的位置而产生Exception使得程序无法动作.我们来看下面的范例吧!
import javax.swing.*;
import javax.swing.event.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;

public class JEditorPane3{
  public static void main(String[] args){
  JEditorPane editPane=null;
  try{
     URL address=new URL("http://www.sina.com.cn");
     editPane=new JEditorPane(address);    
  }catch(MalformedURLException e){
     System.out.println("Malformed URL:"+e);
  }catch(IOException e){
     System.out.println("IOException:"+e);
  }
     editPane.setEditable(false);
     JFrame f=new JFrame("JEditorPane3");
     f.setContentPane(new JScrollPane(editPane));
     f.setSize(200,250);
     f.show();
    f.addWindowListener(new WindowAdapter(){
      public void windowClosing(WindowEvent e){
      System.exit(0);
      }
    });
  }
}


9-5-2:JEditorPane的事件处理:
   在JEditorPane文件中最常用到事件处理的部份就是HTML文件,那是因为HTML文件本身具有超级链接的功能来做文章链接的用途
。大家还记得我们这一节的第一个范例吗?我们不是加载了一份HTML文件到JEditorPane中吗?虽然画面上都有确实的将超级链接和
图片信息展现出来,可是你有没有发现当你想要点选超级链接的地方时却没有反应呢?那是因为我们并没有在JEditorPane中加入事
件处理机制的缘故。我们改写JEditorPane1.java加入事件处理机制,使JEditorPane具有正常的超链接功能。如下范例:
import javax.swing.*;
import javax.swing.event.*;
import java.io.*;
import java.awt.event.*;

public class JEditorPane4{

public static void main(String[] args){

JEditorPane editPane = null;
try{
  File thef = new File ("docs/JEditorPane_1.html");
      String str = thef.getAbsolutePath();
      str = "file:"+str;
      editPane = new JEditorPane();
      editPane.setPage(str);
    }
catch(IOException ioe){
  ioe.printStackTrace(System.err);
  System.exit(0);
}
editPane.setEditable(false);

final JEditorPane thePane = editPane;
        //采用inner class的方式编写触发超级链接事件时的对应操作类
editPane.addHyperlinkListener(new HyperlinkListener(){
  public void hyperlinkUpdate(HyperlinkEvent hle){//覆写hyperlinkUpdate()方法,当超级链接事件触发时会进入这                                             
//个区段运行.
    try{
               //判断是否为超级链接运行操作。若操作为真,则将新的HTML文件放到JEditorPane中,
               //操作为(thePane.setPage(hle.getURL());)
      if (hle.getEventType() == HyperlinkEvent.EventType.ACTIVATED)
       
    }
    catch(IOException ioe){
      ioe.printStackTrace(System.err);
    }
  }
});

JFrame f = new JFrame("JEditorPane4");
f.setContentPane(new JScrollPane(editPane));
f.setSize(200,250);
    f.show();
    f.addWindowListener(new WindowAdapter() {           
      public void windowClosing(WindowEvent e) {                   
      System.exit(0);           
      }       
    });   
}//end of main()
}//end of class JEditPane1
   另外,若是我们是在纯文字模式(Plain Text)或RTF模式(RTF Text)下需要事件处理模式又该怎么办呢?你还记得我们在
JTextArea中是如何加入事件处理模式的吗?没错!在JEditorPane中也是相同的做法,也就是利用DocumentListener interface的
机制来处理,由于做法相当类似,因此我们就不在这里重复的说明.

9-6:使用JTextPane组件:
   JTextPane的类层次结构图:
    java.lang.Object
     --java.awt.Component
      --java.awt.Container
       --javax.swing.JComponent
        --javax.swing.text.JTextComponent
          --javax.swing.JEditorPane
            --javax.swing.JTextPane
    我们在前面有介绍过JTextArea类,虽然JTextArea在某些功能上已经能够满足我们的需求,但是当我们想再加入更多的变化时
(如文字加入色彩、插入图片...)就会发现JTextArea类根本无法做到。要做到这些功能,我们必须使用JEditorPane的子类:
JTextpane。JTextPane提供了许多对文字的处理,如改变颜色、字体缩放、文字风格、加入图片等。我们先来看看JTextPane的构
造方法:
JTextPane构造函数:
JTextPane():建立一个新的JTextPane.
JTextPane(StyledDocument doc):以指定的文件模式建立一个新的JTextPane.

9-6-1:JTextPane的特性:
    相信大家都有用过Word来写过报告或文章,那么你一定会知道我们在Word中可以对文章中的文字做很多的变化,这些变化都是
属于文字的“属性”变化。由于在JTextPane中产生的效果几乎都是由属性的变化而来,所以改变属性的类组件在JTextpane中是少
不了的。因此在介绍如何构造JTextPane之前,我们要先介绍两个在JTextPane中常用到属性类:
   SimpleAttributeSet和StyleConstant.
属性的变化原本是利用AttributeSet interface来处理的,但是这个interface中包含了太多的方法,若是我们直接实作
AttributeSet interface那就需要实作此interface里所有的方法,这对编写程序来说并不是一个很理想的做法;而java另外提供了
SimpleAttributeSet类,实作了AttributeSet interface.因此,只要我们直接使用SimpleAttributeSet类就能具备AttributeSet
interface的所有功能,而不用一个个的编写AttributeSet中的方法。另外StyleConstant类则是提供AttributeSet类许多常用的属
性键值(Attribute Key)和方法来设置或取得JTextPane内容的状态。在StyleConstant类中包含了许多的常用的属性设置,包括本文
与边界空白区段设置、文字字体/大小/类型设置、背景颜色设置等。利用这两个类来辅助设计JTextPane便使JTextPane有更丰富
的内容变化。
   JTextPane是专为文字和版面处理设计的组件。JTextPane对可输入区域内容的设计概念是一个类似Word的设计概念,也就是说在
JTextPane中的文字结构是有段落概念的。“段落”的概念就是以[Enter]键为每一段落的分界点,每按一次[Enter]键就增加一个段
落。记得我们在JTextArea中提过的Element存储模式吗?在JTextPane中也是采用相同的做法,但是差别在于规划存储的方式不同。
在JTextArea中并没有分段落,只是单纯的以[Enter]键当作存储成两个Element的分界。而在JTextPane则是以整个编辑区哉为根节
点,每个段落为枝节点 ,每个字符为叶节点来存储文件。也因为JTextPane是采用这样的方式来存储数据,因此在JTextPane中也可
以像Word文件一样将各个段落设置成不同的属性,如第一段为斜体字、字体大小为14号字、粗体字,第二段为斜体字、字体颜色为
蓝色、向左边界缩排2厘米等;另外,我们还可以设置JTextPane编辑区内输入的文字与各个边界间的距离。由这些功能看来,对于一
个TextComponent来说JTextPane是一个具有相当多实用功能的组件。

9-6-2:构造JTextPane组件:
   在了解JTextPane的各项特性之后,我们现在马上来看JTextPane可以呈现什么样的效果,在下面这个例子中我们将对JTextPane
区域内的文字设置颜色、粗斜体、与底线等相关属性。

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

public class JTextPane1{
private JTextPane textPane;

public JTextPane1(){
  textPane=new JTextPane();
  textPane.setBackground(Color.black);
  textPane.setEditable(false);
}
public void setYellow_Bold_20(String str){
  SimpleAttributeSet attrset=new SimpleAttributeSet();
  StyleConstants.setForeground(attrset,Color.yellow);
  StyleConstants.setBold(attrset,true);
  insert(str,attrset);
}
public void setBlue_Italic_Bold_22(String str){
  SimpleAttributeSet attrset=new SimpleAttributeSet();
  StyleConstants.setForeground(attrset,Color.blue);
  StyleConstants.setItalic(attrset,true);
  StyleConstants.setFontSize(attrset,24);
  insert(str,attrset);
}
public void setRed_UnderLine_Italic_24(String str){
  SimpleAttributeSet attrset=new SimpleAttributeSet();
  StyleConstants.setForeground(attrset,Color.red);
  StyleConstants.setUnderline(attrset,true);
  StyleConstants.setItalic(attrset,true);
  StyleConstants.setFontSize(attrset,24);
  insert(str,attrset);
}
   //这个方法最主要的用途是将字符串插入到JTextPane中。
public void insert(String str,AttributeSet attrset){
  Document docs=textPane.getDocument();//利用getDocument()方法取得JTextPane的Document instance.0
  str=str+"\n";
  try{
    docs.insertString(docs.getLength(),str,attrset);    
  }catch(BadLocationException ble){
     System.out.println("BadLocationException:"+ble);
  }
}
public Component getComponent(){
  return textPane;
}
public static void main(String[] args){
  JTextPane1 pane=new JTextPane1();
  pane.setYellow_Bold_20("This is Line 1,yellow,Bold,Size 20");
  pane.setBlue_Italic_Bold_22("This is Line 2,blue,Italic,Bold,Size 22");
  pane.setRed_UnderLine_Italic_24("This is Line 3,red,UnderLine,Italic,Size 24");
 
  JFrame f=new JFrame("JTextPane1");
  f.getContentPane().add(pane.getComponent());
  f.setSize(450,180);
          f.show();
          f.addWindowListener(new WindowAdapter(){
          public void windowClosing(WindowEvent e){
            System.exit(0);
          }
          });
}
}

若你想在JTextPane上置入图形或其他组件(如表格或按钮),你可以分别使用JTextPane所提供的insetIcon()与insertComponent()
方法来达到这个效果。
  至于另外一种JTextPane的构造方式和JTextArea一样,差别在于JTextArea是采用Document interface而JTextPane是采用

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics