`

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

阅读更多

认识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是采用

分享到:
评论

相关推荐

    含热电联供的智能楼宇群协同能量管理策略:基于多主体协同与需求响应的热电混合运行策略研究,“基于Stackelberg博弈与需求响应的智能楼宇群热电协同能量管理策略”,MATLAB代码:含热电联供的智能

    含热电联供的智能楼宇群协同能量管理策略:基于多主体协同与需求响应的热电混合运行策略研究,“基于Stackelberg博弈与需求响应的智能楼宇群热电协同能量管理策略”,MATLAB代码:含热电联供的智能楼宇群协同能量管理 关键词:楼宇能量管理系统;热电联供系统;Stackelberg博弈;需求响应 参考文档:《含热电联供的智能楼宇群协同能量管理》华北电力硕士lunwen 仿真平台:MATLAB 主要内容:本文提出了一种计及热电耦合需求响应的智能楼宇群的多主体协同能量管理策略。 传统热电联供系统采取单一的“以电定热”或“以热定电”运行策略,在实际运用中将无可避免地造成能源的浪费。 针对这一现状,本文采取“热电混合运行”策略对联供系统进行调控,在该运行策略下,运营商可以结合不同时段的价格信息、负荷水平等因素灵活采取使自身收益最大化的运行策略。 在热电协同能量管理层面,以楼宇群运营商的收益以及用户的效益最大化为目标,提出了智能楼宇群内部的优化定价策略,运营商在系统中负责向用户供电与供热,并自主制定电与热价格引导用户进行需求响应;其次,用户具有可平移电负荷以及可削减热负荷,可根据当前的价格信息自

    随机规划下的虚拟电厂与微网双不确定性优化调度模型研究:基于MATLAB与CPLEX的仿真平台实现,计及双重不确定性的虚拟电厂微网日前随机优化调度策略-基于MATLAB与CPLEX平台的研究,MATL

    随机规划下的虚拟电厂与微网双不确定性优化调度模型研究:基于MATLAB与CPLEX的仿真平台实现,计及双重不确定性的虚拟电厂微网日前随机优化调度策略——基于MATLAB与CPLEX平台的研究,MATLAB代码:计及源-荷双重不确定性的电厂 微网日前随机优化调度 关键词:电厂 微网 随机优化 随机调度 源-荷双重不确定性 电厂调度 参考文档:《Virtual power plant mid-term dispatch optimization》参考其燃气轮机、以及储能部分模型,另外随机优化算法也是和该文档一致; 仿真平台:MATLAB+CPLEX 主要内容:代码主要做的是一个电厂或者微网单元的日前优化调度模型,考虑了光伏出力和负荷功率的双重不确定性,采用随机规划法处理不确定性变量,构建了电厂随机优化调度模型。 具体来看,首先是基于蒙特卡洛算法,对预测的光伏以及负荷曲线进行场景生成,然后基于快概率距离快速消除法进行削减,直至削减至5个场景,然后采用随机调度的方法,对多场景下的电厂调度策略进行优化,程序实现效果良好,纯程序为本人亲自所写,一行一注释, ,关键词:虚拟电厂; 微网; 随

    rsyslog-mmaudit-8.24.0-57.el7-9.3.x64-86.rpm.tar.gz

    1、文件内容:rsyslog-mmaudit-8.24.0-57.el7_9.3.rpm以及相关依赖 2、文件形式:tar.gz压缩包 3、安装指令: #Step1、解压 tar -zxvf /mnt/data/output/rsyslog-mmaudit-8.24.0-57.el7_9.3.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm 4、更多资源/技术支持:公众号禅静编程坊

    基于Web的增材制造预处理平台的设计与实现.zip(毕设&课设&实训&大作业&竞赛&项目)

    项目工程资源经过严格测试运行并且功能上ok,可实现复现复刻,拿到资料包后可实现复现出一样的项目,本人系统开发经验充足(全栈全领域),有任何使用问题欢迎随时与我联系,我会抽时间努力为您解惑,提供帮助 【资源内容】:包含源码+工程文件+说明等。答辩评审平均分达到96分,放心下载使用!可实现复现;设计报告也可借鉴此项目;该资源内项目代码都经过测试运行,功能ok 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 【提供帮助】:有任何使用上的问题欢迎随时与我联系,抽时间努力解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 下载后请首先打开说明文件(如有);整理时不同项目所包含资源内容不同;项目工程可实现复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用,资源为网络商品(电子资料类)基于网络商品和电子资料商品的性质和特征不支持退款,质量优质,放心下载使用

    博客系统完整开发流程(上)

    前端博客系统代码

    18考试真题最近的t67.txt

    18考试真题最近的t67.txt

    Javaweb期中作业会议管理系统,SSM+JSP.zip(课设&实训&大作业&项目)

    项目工程资源经过严格测试运行并且功能上ok,可实现复现复刻,拿到资料包后可实现复现出一样的项目,本人系统开发经验充足(全栈全领域),有任何使用问题欢迎随时与我联系,我会抽时间努力为您解惑,提供帮助 【资源内容】:包含源码+工程文件+说明等。答辩评审平均分达到96分,放心下载使用!可实现复现;设计报告也可借鉴此项目;该资源内项目代码都经过测试运行,功能ok 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 【提供帮助】:有任何使用上的问题欢迎随时与我联系,抽时间努力解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 下载后请首先打开说明文件(如有);整理时不同项目所包含资源内容不同;项目工程可实现复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用,资源为网络商品(电子资料类)基于网络商品和电子资料商品的性质和特征不支持退款,质量优质,放心下载使用

    基于Plecs的模块化多电平换流器设计:PMW调制下的小输出电压纹波半桥子模块实现,基于Plecs实现的模块化多电平半桥换流器,采用PWM调制方式实现低电压纹波输出,用plecs实现的模块化多电平流器

    基于Plecs的模块化多电平换流器设计:PMW调制下的小输出电压纹波半桥子模块实现,基于Plecs实现的模块化多电平半桥换流器,采用PWM调制方式实现低电压纹波输出,用plecs实现的模块化多电平流器,调制方式是PMW,输出电压纹波小,子模块是半桥 ,关键词提取结果:plecs;模块化多电平换流器;PWM调制;输出电压纹波小;半桥子模块;,《Plecs模拟模块化半桥式PWM多电平换流器》——输出低纹波电压的研究与应用

    最新更新!!!上市公司-股票流动性指标(2000-2023年)

    ## 01、数据简介 股票流动性是指股票在市场上被买卖的容易程度和速度,即投资者能够在不造成显著价格变动的情况下迅速买卖股票的能力。 Amihud指标结果这是一个衡量股票流动性的指标,为股票在一段时间的收益率与交易额的比值的负对数值。如果股票交易量的变动会带来股价的剧烈波动(暴涨暴跌),则Amihud指标越大,股票流动性越差;反之,如果交易量的变化对股价变化的影响越小,则说明股票的流动性较好。由于这是一个计算结果,因此需要根据实际的股票交易数据来计算。 数据名称:上市公司-股票流动性指标 数据年份:2000-2023年 ## 02、相关数据 stkcd、年份、证券代码、Amihud指标结果、交易天数。

    Simulink在DSP2833x开发板上的电机控制与通讯模型自动生成代码教程,Simulink在DSP2833x开发板上的电机控制与通讯模型自动生成代码教程,模型开发域控制Simulik自动生成代码

    Simulink在DSP2833x开发板上的电机控制与通讯模型自动生成代码教程,Simulink在DSP2833x开发板上的电机控制与通讯模型自动生成代码教程,模型开发域控制Simulik自动生成代码 DSP2833x基于模型的电机控制设计 MATLAb Simulik自动生成代码 基于dsp2833x 底层驱动库的自动代码生成 MATLAB Simulink仿真及代码生成技术入门教程 内容为Simulink在嵌入式领域的应用,具体是Simulink在DSP28335这块开发版上的应用模型:包括直流电机、PMSM、步进电机控制模型,还有常见的LED、串口、CAN等通讯相关Simulink模型,模型都有相关解释文件。 ,核心关键词: Simulink应用; DSP2833x开发版; 电机控制模型; 直流电机模型; PMSM模型; 步进电机模型; LED模型; 串口模型; CAN通讯模型; 自动代码生成; 底层驱动库。,MATLAB Simulink在DSP2833x上的嵌入式开发:自动生成代码的模型应用与实践教程

    19考试真题最近的t24.txt

    19考试真题最近的t24.txt

    C51/STM32仿真软件,主要通过三极管、电阻、电容、单片机等等元器件进行搭载电路,软件程序调试的过程,完成项目功能

    protues8.17安装包,无须积分,即可下载

    计及电动汽车灵活性的微网三阶段多时间尺度协调调度模型:优化经济调度、实时调整与减少功率波动策略,计及电动汽车灵活性的微网多时间尺度经济协调调度模型,计及电动汽车灵活性的微网多时间尺度协调调度模型 摘要

    计及电动汽车灵活性的微网三阶段多时间尺度协调调度模型:优化经济调度、实时调整与减少功率波动策略,计及电动汽车灵活性的微网多时间尺度经济协调调度模型,计及电动汽车灵活性的微网多时间尺度协调调度模型 摘要:构建了含有电动汽车参与的微网 电厂多时间尺度协调优化模型,其中包括日前-日内-实时三阶段,日前阶段由于风光出力具有不确定性,结合风光预测值作初步经济调度;日内阶段,风光出力观测的更加准确,通过调节储能、需求响应等单元对调度方案作进一步调整,避免遭受高额的不平衡惩罚;实时阶段,风光出力的预测结果更准确,为了进一步降低微网与上级电网并网功率的波动性,充分利用电动汽车的灵活性,调度电动汽车的充放电以减少功率波动,兼顾调度的安全性与经济性。 ,微网协调调度模型; 电动汽车灵活性; 多时间尺度; 风光出力; 储能需求响应; 实时调整; 经济性,电动汽车灵活性的微网多尺度协调调度模型研究

    基于MPC的电动汽车分布式协同自适应巡航控制:上下分层控制与仿真结果展示,基于MPC的电动汽车协同自适应巡航控制:上下分层控制与仿真结果展示,基于MPC的分布式电动汽车协同自适应巡航控制,采用上下分层

    基于MPC的电动汽车分布式协同自适应巡航控制:上下分层控制与仿真结果展示,基于MPC的电动汽车协同自适应巡航控制:上下分层控制与仿真结果展示,基于MPC的分布式电动汽车协同自适应巡航控制,采用上下分层控制方式,上层控制器采用模型预测控制mpc方式,产生期望的加速度,下层根据期望的加速度分配扭矩;仿真结果良好,能够实现前车在加减速情况下,规划期望的跟车距离,产生期望的加速度进行自适应巡航控制。 ,关键词:MPC(模型预测控制); 分布式电动汽车; 协同自适应巡航控制; 上下分层控制方式; 期望加速度; 扭矩分配; 仿真结果良好; 前车加减速; 跟车距离。,基于MPC的分层控制电动汽车自适应巡航系统,仿真实现前车加减速跟车距离自适应

    MATLAB代码实现电-气-热综合能源系统耦合优化调度模型:精细注释与实用模块子程序,MATLAB实现电-气-热综合能源系统优化调度的精细化建模与求解策略利用电网、热网与气网耦合交互的复杂系统特性进行

    MATLAB代码实现电-气-热综合能源系统耦合优化调度模型:精细注释与实用模块子程序,MATLAB实现电-气-热综合能源系统优化调度的精细化建模与求解策略利用电网、热网与气网耦合交互的复杂系统特性进行深度调度分析,MATLAB代码:电-气-热综合能源系统耦合优化调度 关键词:综合能源系统 优化调度 电气热耦合 参考文档:自编文档,非常细致详细,可联系我查阅 仿真平台:MATLAB YALMIP+cplex gurobi 主要内容:代码主要做的是一个考虑电网、热网以及气网耦合调度的综合能源系统优化调度模型,考虑了电网与气网,电网与热网的耦合,算例系统中,电网部分为10机39节点的综合能源系统,气网部分为比利时20节点的配气网络,潮流部分电网是用了直流潮流,气网部分也进行了线性化的操作处理,代码质量非常高,保姆级的注释以及人性化的模块子程序,所有数据均有可靠来源 ,关键词:综合能源系统; 优化调度; 电气热耦合; 10机39节点; 比利时20节点; 直流潮流; 线性化处理; MATLAB YALMIP; cplex gurobi。,MATLAB代码:电-气-热综合能源系统耦合优化调度

    元器件基础知识文档(适合初学者学习)

    报告电子元器件手册目录,常见电子元器件的参考资料以及70种电子元器件封装等等,非常适合初学者进行学习和掌握。希望大家都能够在电子领域进行深耕。

    19考试真题最近的t63.txt

    19考试真题最近的t63.txt

    基于MATLAB Simulink开发的FCU与PEMFC燃料电池系统模型开发:空压机、电堆等模块仿真与控制策略开发,基于MATLAB Simulink开发的PEMFC燃料电池系统模型及控制策略仿真开

    基于MATLAB Simulink开发的FCU与PEMFC燃料电池系统模型开发:空压机、电堆等模块仿真与控制策略开发,基于MATLAB Simulink开发的PEMFC燃料电池系统模型及控制策略仿真开发资料,fcu,燃料电池控制器,质子交膜燃料电池系统模型(PEMFC),基于MATLAB simulink开发,主要部分有空压机模型,供气系统模型(阴极和阳极),背压阀模型,电堆模型等。 可进行控制策略等仿真开发工作。 提供相关文档学习建模资料等 ,fcu; 燃料电池控制器; PEMFC; MATLAB simulink; 空压机模型; 供气系统模型; 背压阀模型; 电堆模型; 控制策略仿真; 文档学习建模资料,基于MATLAB Simulink的PEMFC燃料电池控制器开发:模型构建与控制策略仿真

    上门预约服务小程序v4.10.9+前端.zip

    上门预约服务小程序v4.10.9+前端 文章列表单图时,图标统一左侧对齐 文章内增加视频位置,显示在文章顶部 文章内底部导航增加首页、分享、自定义按钮,可跳转内部页面、其他小程序、业务域名内的H5页面,方便宣传使用

    19考试真题最近的t41.txt

    19考试真题最近的t41.txt

Global site tag (gtag.js) - Google Analytics