public void paint(java.awt.Graphics g)
{
if(m_offImage == null){
m_offImage = this.createImage(this.getWidth(),this.getHeight());
}
java.awt.Graphics gOff = m_offImage.getGraphics();
gOff.setColor(java.awt.Color.white);
gOff.fillRect(0,0,this.getWidth(),this.getHeight()); java.awt.FontMetrics fm = gOff.getFontMetrics();
//rectangle 外框
gOff.setColor(java.awt.Color.blue);
gOff.drawRect(0,0,this.getWidth()-1,this.getHeight()-1);
gOff.drawRect(0,0,this.getWidth()-1,this.getHeight()-1); gOff.setClip(1,1,this.getWidth()-2,this.getHeight()-2); //调整视图左界,使目标区位置在视图区
int W = this.getWidth()-4; //视图宽度
int view_left_bound = m_view_x, view_right_bound = m_view_x+W; //视图界
int zone0_left_bound = 0, zone0_right_bound = m_text.length()>0 ? fm.stringWidth(m_text.substring(0,1))/2 : 0; //0区界
int zoneN_left_bound = m_text.length()>0 ? (fm.stringWidth(m_text.substring(0,m_text.length()-1))+fm.stringWidth(m_text.substring(0,m_text.length())))/2 : 0,
zoneN_right_bound = m_text.length()>0 ? fm.stringWidth(m_text.substring(0,m_text.length())) : 0; //N区界 int cpos = (m_csel_end==-1 ? m_cpos : m_csel_end); //目标区位置 if(cpos==0){ //光标在0区
if(zone0_left_bound<view_left_bound){
m_view_x = zone0_left_bound;
}
if(zone0_right_bound>view_right_bound){
m_view_x = zone0_right_bound-W;
}
}else if(cpos==m_text.length()){ //光标在N区
if(zoneN_left_bound<view_left_bound){
m_view_x = zoneN_left_bound;
}
if(zoneN_right_bound>view_right_bound){
m_view_x = zoneN_right_bound-W;
}
}else{ //光标在其他区
int zone_cpos_left_bound = (fm.stringWidth(m_text.substring(0,cpos-1))+fm.stringWidth(m_text.substring(0,cpos)))/2,
zone_cpos_right_bound = (fm.stringWidth(m_text.substring(0,cpos))+fm.stringWidth(m_text.substring(0,cpos+1)))/2; //cpos区界 if(zone_cpos_left_bound<view_left_bound){
m_view_x = zone_cpos_left_bound;
}
if(zone_cpos_right_bound>view_right_bound){
m_view_x = zone_cpos_right_bound-W;
}
}
//设置视图
gOff.translate(1-m_view_x,1);
//draw text 画文本
gOff.setColor(java.awt.Color.black);
gOff.drawString(m_text.toString(),0,fm.getMaxAscent()); //draw selection 画选择
if(m_csel_end != -1){
int csel_start,csel_end;
if(m_cpos<m_csel_end){
csel_start = m_cpos;
csel_end = m_csel_end;
}else{
csel_start = m_csel_end;
csel_end = m_cpos;
}
int selstartx = fm.stringWidth(m_text.substring(0,csel_start));
int selendx = fm.stringWidth(m_text.substring(0,csel_end));
gOff.setColor(java.awt.Color.blue.darker());
gOff.fillRect(selstartx,0,selendx-selstartx+1,fm.getHeight());
gOff.setColor(java.awt.Color.white);
gOff.drawString(m_text.substring(csel_start,csel_end),selstartx,fm.getMaxAscent());
}
//draw caret
if(this.hasFocus() && m_csel_end==-1){
if(m_cursor_sparkling_light){
int cur_pos = fm.stringWidth(m_text.substring(0,m_cpos));
gOff.setColor(java.awt.Color.red);
gOff.drawLine(cur_pos,1,cur_pos,fm.getHeight()-1);
gOff.drawLine(cur_pos-1,1,cur_pos+1,1);
gOff.drawLine(cur_pos-1,fm.getHeight()-1,cur_pos+1,fm.getHeight()-1);
}
} g.drawImage(m_offImage,0,0,null);
gOff.dispose();
}
private void this_keyLeft(java.awt.event.KeyEvent e)
{
if((e.getModifiers()&java.awt.event.KeyEvent.SHIFT_MASK) != 0){ //for selection method
if(m_csel_end==-1){ //no selection
m_csel_end = m_cpos>0? m_cpos-1 : -1;
}else{ //selection
m_csel_end = (m_csel_end>0 ? m_csel_end-1 : 0);
if(m_csel_end==m_cpos){
m_csel_end = -1;
}
}
}else{ //for movement
if(m_csel_end != -1){
m_csel_end = -1;
}
if(m_cpos>0){
m_cpos--;
}
}
onSelChanged();
onCaretChanged();
repaint();
}
private void this_keyRight(java.awt.event.KeyEvent e)
{
if((e.getModifiers()&java.awt.event.KeyEvent.SHIFT_MASK) != 0){ //for selection
if(m_csel_end==-1){ //have not selection
m_csel_end = m_cpos<m_text.length()? m_cpos+1 : -1;
}else{
m_csel_end = (m_csel_end<m_text.length() ? m_csel_end+1 : m_text.length());
if(m_csel_end==m_cpos){
m_csel_end = -1;
}
}
}else{
m_csel_end = -1;
if(m_cpos<m_text.length()){
m_cpos++;
}
}
onCaretChanged();
onSelChanged();
repaint();
}
private void this_keyHome(java.awt.event.KeyEvent e)
{
if((e.getModifiers()&java.awt.event.KeyEvent.SHIFT_MASK) != 0){ //for selection
m_csel_end = m_cpos>0 ? 0 : -1;
}else{
m_csel_end = -1;
m_cpos = 0;
}
onCaretChanged();
onSelChanged();
repaint();
}

解决方案 »

  1.   

    private void this_keyEnd(java.awt.event.KeyEvent e)
    {
    if((e.getModifiers()&java.awt.event.KeyEvent.SHIFT_MASK) != 0){ //for selection
    m_csel_end = m_cpos<m_text.length() ? m_text.length() : -1;
    }else{
    m_csel_end = -1;
    m_cpos = m_text.length();
    }
    onCaretChanged();
    onSelChanged();
    repaint();
    }
    private int find_cpos(int x) //查找像素x所在的光标区,使用对分搜索方法
    {
    int cpos = 0;
    int N = m_text.length();
    if(N > 0){
    java.awt.FontMetrics fm = this.getFontMetrics(this.getFont());
    if(x <= fm.stringWidth(m_text.substring(0,1))/2-1){ //x在0区右界,注意这个0区的右界要归到0区
    cpos = 0;
    }else if(x >= (fm.stringWidth(m_text.substring(0,N-1))+fm.stringWidth(m_text.substring(0,N)))/2){ //x在N区左界
    cpos = N;
    }else{
    boolean suitable = false;
    int L = 1,H = N-1; //上界、下界
    while(! suitable){ //使用对分搜索寻找区域
    cpos = (L+H)/2; //中点
    if(x>=(fm.stringWidth(m_text.substring(0,cpos-1))+fm.stringWidth(m_text.substring(0,cpos)))/2 && x<(fm.stringWidth(m_text.substring(0,cpos))+fm.stringWidth(m_text.substring(0,cpos+1)))/2){ //x在cpos所在的区
    suitable = true;
    }else if(x >= (fm.stringWidth(m_text.substring(0,cpos))+fm.stringWidth(m_text.substring(0,cpos+1)))/2){
    L = cpos+1;
    }else{
    H = cpos-1;
    }
    }
    }
    }
    return cpos;
    }
    private void this_mousePressed(int x)
    {
    m_csel_end = -1;
    int cpos = find_cpos(x);
    if(m_cpos != cpos){
    m_cpos = cpos;
    }
    onCaretChanged();
    repaint();
    }
    private void this_mouseDragged(int x) { int m_csel_end1 = find_cpos(x);
    if(m_csel_end1 != m_csel_end){
    m_csel_end = m_csel_end1;
    if(m_csel_end==m_cpos){
    m_csel_end = -1;
    }
    onSelChanged();
    repaint();
    }
    }
    private void this_keyTyped(char c)
    {
    if(m_isEditable){
    if(m_csel_end != -1){
    int csel_start,csel_end;
    if(m_cpos<m_csel_end){
    csel_start = m_cpos;
    csel_end = m_csel_end;
    }else{
    csel_start = m_csel_end;
    csel_end = m_cpos;
    }
    m_text.delete(csel_start,csel_end);
    m_csel_end = -1;
    m_cpos = csel_start;
    }
    m_text.insert(m_cpos,c);
    m_cpos++;
    onTextChanged();
    onSelChanged();
    onCaretChanged();
    repaint();
    }
    }
    private void this_keyBackspace()
    {
    if(m_isEditable){
    if(m_csel_end != -1){
    int csel_start,csel_end;
    if(m_cpos<m_csel_end){
    csel_start = m_cpos;
    csel_end = m_csel_end;
    }else{
    csel_start = m_csel_end;
    csel_end = m_cpos;
    }
    m_text.delete(csel_start,csel_end);
    m_csel_end = -1;
    m_cpos = csel_start;
    }else{
    if(m_cpos>0){
    m_text.deleteCharAt(m_cpos-1);
    m_cpos--;
    }
    }
    onSelChanged();
    onTextChanged();
    onCaretChanged();
    repaint();
    }
    }
    private void this_keyDelete()
    {
    if(m_isEditable){
    if(m_csel_end != -1){
    int csel_start,csel_end;
    if(m_cpos<m_csel_end){
    csel_start = m_cpos;
    csel_end = m_csel_end;
    }else{
    csel_start = m_csel_end;
    csel_end = m_cpos;
    }
    m_text.delete(csel_start,csel_end);
    m_csel_end = -1;
    m_cpos = csel_start;
    }else{
    if(m_cpos<m_text.length()){
    m_text.deleteCharAt(m_cpos);
    }
    }
    onSelChanged();
    onCaretChanged();
    onTextChanged();
    repaint();
    }
    }
    public java.awt.Dimension getPreferredSize()
    {
    return new java.awt.Dimension(this.getFontMetrics(this.getFont()).stringWidth(m_text.toString()),this.getFontMetrics(this.getFont()).getHeight());
    }
    public  boolean isFocusTraversable()
    {
    return true;
    }
    }
      

  2.   

    public class MyApp extends java.awt.Frame
    {
    public static void main(String[] args) throws Exception
    {
    MyApp myApp1 = new MyApp();
    }
    private KTextField m_textField1 = new KTextField("欢迎使用轻量级组件编写的文本编辑器。");
    private KTextField m_textField2 = new KTextField("这个演示了修改光标的方法,你可以使用鼠标点击或键盘的光标键来修改光标");
    private KTextField m_textField3 = new KTextField("这个演示了选择区域的方法,你可以使用鼠标拖动或光标键+SHIFT来修改选择区域");
    private KTextField m_textField4 = new KTextField("这个演示了不可编辑的文本组件");
    public MyApp() throws Exception
    {
    addWindowListener(new java.awt.event.WindowAdapter(){
    public void windowClosing(java.awt.event.WindowEvent e)
    {
    dispose();
    }
    public void windowClosed(java.awt.event.WindowEvent e)
    {
    System.exit(0);
    }
    });
    setSize(250,200);
    // setResizable(false);
    setLayout(new java.awt.GridLayout(0,1,5,10)); add(m_textField1);
    add(m_textField2);
    m_textField2.setCaretPosition(6);
    add(m_textField3);
    m_textField3.select(4,14);
    add(m_textField4);
    m_textField4.setEditable(false);
    add(new java.awt.TextField("这是AWT提供的文本编辑组件,用于对照。"));
    // pack();
    setLocation((java.awt.Toolkit.getDefaultToolkit().getScreenSize().width-this.getSize().width)/2,(java.awt.Toolkit.getDefaultToolkit().getScreenSize().height-this.getSize().height)/2);
    setVisible(true);
    m_textField1.setFont(new java.awt.Font(this.getFont().getName(),this.getFont().getStyle(),this.getFont().getSize()+2));
    m_textField4.setFont(new java.awt.Font(this.getFont().getName(),this.getFont().getStyle(),this.getFont().getSize()+5));
    m_textField2.requestFocus();
    }
    }
      

  3.   

    public class MyApp extends java.awt.Frame
    {
    public static void main(String[] args) throws Exception
    {
    MyApp myApp1 = new MyApp();
    }
    private KTextField m_textField1 = new KTextField("欢迎使用轻量级组件编写的文本编辑器。");
    private KTextField m_textField2 = new KTextField("这个演示了修改光标的方法,你可以使用鼠标点击或键盘的光标键来修改光标");
    private KTextField m_textField3 = new KTextField("这个演示了选择区域的方法,你可以使用鼠标拖动或光标键+SHIFT来修改选择区域");
    private KTextField m_textField4 = new KTextField("这个演示了不可编辑的文本组件");
    public MyApp() throws Exception
    {
    addWindowListener(new java.awt.event.WindowAdapter(){
    public void windowClosing(java.awt.event.WindowEvent e)
    {
    dispose();
    }
    public void windowClosed(java.awt.event.WindowEvent e)
    {
    System.exit(0);
    }
    });
    setSize(250,200);
    // setResizable(false);
    setLayout(new java.awt.GridLayout(0,1,5,10)); add(m_textField1);
    add(m_textField2);
    m_textField2.setCaretPosition(6);
    add(m_textField3);
    m_textField3.select(4,14);
    add(m_textField4);
    m_textField4.setEditable(false);
    add(new java.awt.TextField("这是AWT提供的文本编辑组件,用于对照。"));
    // pack();
    setLocation((java.awt.Toolkit.getDefaultToolkit().getScreenSize().width-this.getSize().width)/2,(java.awt.Toolkit.getDefaultToolkit().getScreenSize().height-this.getSize().height)/2);
    setVisible(true);
    m_textField1.setFont(new java.awt.Font(this.getFont().getName(),this.getFont().getStyle(),this.getFont().getSize()+2));
    m_textField4.setFont(new java.awt.Font(this.getFont().getName(),this.getFont().getStyle(),this.getFont().getSize()+5));
    m_textField2.requestFocus();
    }
    }
      

  4.   

    上面是测试程序,这个组件的用法基本与java.awt.TextField相同
    多行文便编辑器组件的源代码在:
    http://community.csdn.net/Expert/topic/3161/3161119.xml?temp=.1555445